-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Summary
PricingOption is implemented as a RootModel (discriminated union), which means the obvious pattern for iterating a product's pricing options fails:
from adcp.types import Product
product: Product = ...
for po in product.pricing_options:
print(po.pricing_option_id) # AttributeError!
print(po.root.pricing_option_id) # works, but non-obviousThis is the single biggest DX friction point when building a sales agent with the library.
Steps to Reproduce
from adcp.types import (
Product, FlatRatePricingOption, FormatId,
DeliveryMeasurement, DeliveryType, PublisherPropertiesAll,
)
product = Product(
product_id="test",
name="Test",
description="Test product",
publisher_properties=[
PublisherPropertiesAll(publisher_domain="example.com", selection_type="all")
],
format_ids=[FormatId(agent_url="http://localhost", id="display_300x250")],
delivery_type=DeliveryType.guaranteed,
delivery_measurement=DeliveryMeasurement(provider="Test"),
pricing_options=[
FlatRatePricingOption(
pricing_option_id="flat_1",
pricing_model="flat_rate",
fixed_price=100.0,
currency="USD",
)
],
)
po = product.pricing_options[0]
print(type(po))
# <class 'adcp.types.generated_poc.core.pricing_option.PricingOption'>
print(po.pricing_option_id)
# AttributeError: 'PricingOption' object has no attribute 'pricing_option_id'
print(po.root.pricing_option_id)
# 'flat_1' — works but requires knowing the RootModel internalsExpected Behavior
po.pricing_option_id should work directly. The RootModel wrapper should be transparent to consumers.
Suggested Fix
Add __getattr__ delegation to the PricingOption RootModel:
class PricingOption(RootModel[CpmPricingOption | FlatRatePricingOption | ...]):
def __getattr__(self, name: str):
return getattr(self.root, name)This is backward-compatible — existing .root access still works, but direct attribute access also works.
Relationship to Prior Issues
- GetSignalsRequest as RootModel breaks the library's own inheritance pattern in consumers #138 covered
GetSignalsRequestas RootModel breaking inheritance. This is a different symptom of the same pattern: RootModel unions are opaque to consumers. - Feature Request: Improve Type Ergonomics for Library Consumers #102 covered type ergonomics broadly. This is a specific, actionable instance.
Impact
Anyone building a sales agent needs to iterate pricing options to validate create_media_buy requests. The .root workaround is non-obvious and not documented in any example.
Environment
- adcp: 3.6.0
- Python: 3.12
- Pydantic: 2.x
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels