adcp 2.15.0__tar.gz → 2.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {adcp-2.15.0/src/adcp.egg-info → adcp-2.16.0}/PKG-INFO +1 -1
- {adcp-2.15.0 → adcp-2.16.0}/pyproject.toml +1 -1
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/__init__.py +1 -1
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/_ergonomic.py +185 -0
- {adcp-2.15.0 → adcp-2.16.0/src/adcp.egg-info}/PKG-INFO +1 -1
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_type_coercion.py +218 -0
- {adcp-2.15.0 → adcp-2.16.0}/LICENSE +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/MANIFEST.in +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/README.md +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/setup.cfg +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/ADCP_VERSION +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/__main__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/adagents.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/client.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/config.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/exceptions.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/protocols/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/protocols/a2a.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/protocols/base.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/protocols/mcp.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/py.typed +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/simple.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/testing/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/testing/test_helpers.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/_generated.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/aliases.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/base.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/coercion.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/core.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/adagents.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/activation_key.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/audio_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/css_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/daast_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/html_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/image_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/javascript_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/text_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/url_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/vast_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/video_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/assets/webhook_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/async_response_data.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/brand_manifest.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/brand_manifest_ref.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/context.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/creative_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/creative_assignment.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/creative_filters.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/creative_manifest.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/creative_policy.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/delivery_metrics.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/deployment.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/destination.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/error.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/ext.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/format.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/format_id.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/frequency_cap.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/mcp_webhook_payload.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/measurement.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/media_buy.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/package.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/performance_feedback.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/placement.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/pricing_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/product.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/product_filters.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/promoted_offerings.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/promoted_products.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/property.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/property_id.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/property_tag.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/protocol_envelope.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/publisher_property_selector.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/push_notification_config.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/reporting_capabilities.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/signal_filters.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/start_timing.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/sub_asset.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/core/targeting.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/creative/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/creative/list_creative_formats_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/creative/list_creative_formats_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/creative/preview_creative_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/creative/preview_creative_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/creative/preview_render.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/adcp_domain.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/asset_content_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/auth_scheme.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/available_metric.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/channels.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/co_branding_requirement.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/creative_action.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/creative_agent_capability.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/creative_sort_field.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/creative_status.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/daast_tracking_event.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/daast_version.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/delivery_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/dimension_unit.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/feed_format.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/feedback_source.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/format_category.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/format_id_parameter.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/frequency_cap_scope.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/history_entry_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/http_method.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/identifier_types.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/javascript_module_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/landing_page_requirement.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/markdown_flavor.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/media_buy_status.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/metric_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/notification_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/pacing.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/preview_output_format.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/pricing_model.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/property_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/publisher_identifier_types.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/reporting_frequency.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/signal_catalog_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/sort_direction.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/standard_format_ids.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/task_status.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/task_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/update_frequency.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/url_asset_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/validation_mode.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/vast_tracking_event.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/vast_version.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/webhook_response_type.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/enums/webhook_security_method.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/build_creative_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/build_creative_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_input_required.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_submitted.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/create_media_buy_async_response_working.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/create_media_buy_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/create_media_buy_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/get_media_buy_delivery_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/get_products_async_response_input_required.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/get_products_async_response_submitted.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/get_products_async_response_working.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/get_products_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/get_products_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/list_authorized_properties_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/list_authorized_properties_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/list_creative_formats_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/list_creative_formats_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/list_creatives_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/list_creatives_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/package_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/provide_performance_feedback_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_input_required.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_submitted.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/sync_creatives_async_response_working.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/sync_creatives_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/sync_creatives_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_input_required.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_submitted.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/update_media_buy_async_response_working.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/update_media_buy_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/media_buy/update_media_buy_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/cpc_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/cpcv_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/cpm_auction_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/cpm_fixed_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/cpp_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/cpv_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/flat_rate_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/vcpm_auction_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/pricing_options/vcpm_fixed_option.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/protocols/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/protocols/adcp_extension.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/signals/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/signals/activate_signal_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/signals/activate_signal_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/signals/get_signals_request.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/types/generated_poc/signals/get_signals_response.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/utils/__init__.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/utils/operation_id.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/utils/preview_cache.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/utils/response_parser.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/validation.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp/webhooks.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp.egg-info/SOURCES.txt +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp.egg-info/dependency_links.txt +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp.egg-info/entry_points.txt +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp.egg-info/requires.txt +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/src/adcp.egg-info/top_level.txt +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_adagents.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_cli.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_client.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_code_generation.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_discriminated_unions.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_format_id_validation.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_helpers.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_preview_html.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_protocols.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_public_api.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_response_parser.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_response_str.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_simple_api.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_type_aliases.py +0 -0
- {adcp-2.15.0 → adcp-2.16.0}/tests/test_webhook_handling.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "adcp"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.16.0"
|
|
8
8
|
description = "Official Python client for the Ad Context Protocol (AdCP)"
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "AdCP Community", email = "maintainers@adcontextprotocol.org"}
|
|
@@ -44,7 +44,11 @@ from adcp.types.coercion import (
|
|
|
44
44
|
from adcp.types.generated_poc.core.context import ContextObject
|
|
45
45
|
from adcp.types.generated_poc.core.creative_asset import CreativeAsset
|
|
46
46
|
from adcp.types.generated_poc.core.creative_assignment import CreativeAssignment
|
|
47
|
+
from adcp.types.generated_poc.core.error import Error
|
|
47
48
|
from adcp.types.generated_poc.core.ext import ExtensionObject
|
|
49
|
+
from adcp.types.generated_poc.core.format import Format
|
|
50
|
+
from adcp.types.generated_poc.core.package import Package
|
|
51
|
+
from adcp.types.generated_poc.core.product import Product
|
|
48
52
|
from adcp.types.generated_poc.enums.asset_content_type import AssetContentType
|
|
49
53
|
from adcp.types.generated_poc.enums.creative_sort_field import CreativeSortField
|
|
50
54
|
from adcp.types.generated_poc.enums.format_category import FormatCategory
|
|
@@ -53,15 +57,34 @@ from adcp.types.generated_poc.enums.sort_direction import SortDirection
|
|
|
53
57
|
from adcp.types.generated_poc.media_buy.create_media_buy_request import (
|
|
54
58
|
CreateMediaBuyRequest,
|
|
55
59
|
)
|
|
60
|
+
|
|
61
|
+
# Response types
|
|
62
|
+
from adcp.types.generated_poc.media_buy.create_media_buy_response import (
|
|
63
|
+
CreateMediaBuyResponse1,
|
|
64
|
+
)
|
|
65
|
+
from adcp.types.generated_poc.media_buy.get_media_buy_delivery_response import (
|
|
66
|
+
GetMediaBuyDeliveryResponse,
|
|
67
|
+
MediaBuyDelivery,
|
|
68
|
+
NotificationType,
|
|
69
|
+
)
|
|
56
70
|
from adcp.types.generated_poc.media_buy.get_products_request import GetProductsRequest
|
|
71
|
+
from adcp.types.generated_poc.media_buy.get_products_response import GetProductsResponse
|
|
57
72
|
from adcp.types.generated_poc.media_buy.list_creative_formats_request import (
|
|
58
73
|
ListCreativeFormatsRequest,
|
|
59
74
|
)
|
|
75
|
+
from adcp.types.generated_poc.media_buy.list_creative_formats_response import (
|
|
76
|
+
CreativeAgent,
|
|
77
|
+
ListCreativeFormatsResponse,
|
|
78
|
+
)
|
|
60
79
|
from adcp.types.generated_poc.media_buy.list_creatives_request import (
|
|
61
80
|
FieldModel,
|
|
62
81
|
ListCreativesRequest,
|
|
63
82
|
Sort,
|
|
64
83
|
)
|
|
84
|
+
from adcp.types.generated_poc.media_buy.list_creatives_response import (
|
|
85
|
+
Creative,
|
|
86
|
+
ListCreativesResponse,
|
|
87
|
+
)
|
|
65
88
|
from adcp.types.generated_poc.media_buy.package_request import PackageRequest
|
|
66
89
|
from adcp.types.generated_poc.media_buy.update_media_buy_request import (
|
|
67
90
|
Packages,
|
|
@@ -261,6 +284,168 @@ def _apply_coercion() -> None:
|
|
|
261
284
|
)
|
|
262
285
|
Packages1.model_rebuild(force=True)
|
|
263
286
|
|
|
287
|
+
# Apply coercion to GetProductsResponse
|
|
288
|
+
# - context: ContextObject | dict | None
|
|
289
|
+
# - errors: list[Error] (accepts subclass instances)
|
|
290
|
+
# - ext: ExtensionObject | dict | None
|
|
291
|
+
# - products: list[Product] (accepts subclass instances)
|
|
292
|
+
_patch_field_annotation(
|
|
293
|
+
GetProductsResponse,
|
|
294
|
+
"context",
|
|
295
|
+
Annotated[ContextObject | None, BeforeValidator(coerce_to_model(ContextObject))],
|
|
296
|
+
)
|
|
297
|
+
_patch_field_annotation(
|
|
298
|
+
GetProductsResponse,
|
|
299
|
+
"errors",
|
|
300
|
+
Annotated[
|
|
301
|
+
list[Error] | None,
|
|
302
|
+
BeforeValidator(coerce_subclass_list(Error)),
|
|
303
|
+
],
|
|
304
|
+
)
|
|
305
|
+
_patch_field_annotation(
|
|
306
|
+
GetProductsResponse,
|
|
307
|
+
"ext",
|
|
308
|
+
Annotated[ExtensionObject | None, BeforeValidator(coerce_to_model(ExtensionObject))],
|
|
309
|
+
)
|
|
310
|
+
_patch_field_annotation(
|
|
311
|
+
GetProductsResponse,
|
|
312
|
+
"products",
|
|
313
|
+
Annotated[
|
|
314
|
+
list[Product],
|
|
315
|
+
BeforeValidator(coerce_subclass_list(Product)),
|
|
316
|
+
],
|
|
317
|
+
)
|
|
318
|
+
GetProductsResponse.model_rebuild(force=True)
|
|
319
|
+
|
|
320
|
+
# Apply coercion to ListCreativesResponse
|
|
321
|
+
# - context: ContextObject | dict | None
|
|
322
|
+
# - creatives: list[Creative] (accepts subclass instances)
|
|
323
|
+
# - ext: ExtensionObject | dict | None
|
|
324
|
+
_patch_field_annotation(
|
|
325
|
+
ListCreativesResponse,
|
|
326
|
+
"context",
|
|
327
|
+
Annotated[ContextObject | None, BeforeValidator(coerce_to_model(ContextObject))],
|
|
328
|
+
)
|
|
329
|
+
_patch_field_annotation(
|
|
330
|
+
ListCreativesResponse,
|
|
331
|
+
"creatives",
|
|
332
|
+
Annotated[
|
|
333
|
+
list[Creative],
|
|
334
|
+
BeforeValidator(coerce_subclass_list(Creative)),
|
|
335
|
+
],
|
|
336
|
+
)
|
|
337
|
+
_patch_field_annotation(
|
|
338
|
+
ListCreativesResponse,
|
|
339
|
+
"ext",
|
|
340
|
+
Annotated[ExtensionObject | None, BeforeValidator(coerce_to_model(ExtensionObject))],
|
|
341
|
+
)
|
|
342
|
+
ListCreativesResponse.model_rebuild(force=True)
|
|
343
|
+
|
|
344
|
+
# Apply coercion to ListCreativeFormatsResponse
|
|
345
|
+
# - context: ContextObject | dict | None
|
|
346
|
+
# - creative_agents: list[CreativeAgent] (accepts subclass instances)
|
|
347
|
+
# - errors: list[Error] (accepts subclass instances)
|
|
348
|
+
# - ext: ExtensionObject | dict | None
|
|
349
|
+
# - formats: list[Format] (accepts subclass instances)
|
|
350
|
+
_patch_field_annotation(
|
|
351
|
+
ListCreativeFormatsResponse,
|
|
352
|
+
"context",
|
|
353
|
+
Annotated[ContextObject | None, BeforeValidator(coerce_to_model(ContextObject))],
|
|
354
|
+
)
|
|
355
|
+
_patch_field_annotation(
|
|
356
|
+
ListCreativeFormatsResponse,
|
|
357
|
+
"creative_agents",
|
|
358
|
+
Annotated[
|
|
359
|
+
list[CreativeAgent] | None,
|
|
360
|
+
BeforeValidator(coerce_subclass_list(CreativeAgent)),
|
|
361
|
+
],
|
|
362
|
+
)
|
|
363
|
+
_patch_field_annotation(
|
|
364
|
+
ListCreativeFormatsResponse,
|
|
365
|
+
"errors",
|
|
366
|
+
Annotated[
|
|
367
|
+
list[Error] | None,
|
|
368
|
+
BeforeValidator(coerce_subclass_list(Error)),
|
|
369
|
+
],
|
|
370
|
+
)
|
|
371
|
+
_patch_field_annotation(
|
|
372
|
+
ListCreativeFormatsResponse,
|
|
373
|
+
"ext",
|
|
374
|
+
Annotated[ExtensionObject | None, BeforeValidator(coerce_to_model(ExtensionObject))],
|
|
375
|
+
)
|
|
376
|
+
_patch_field_annotation(
|
|
377
|
+
ListCreativeFormatsResponse,
|
|
378
|
+
"formats",
|
|
379
|
+
Annotated[
|
|
380
|
+
list[Format],
|
|
381
|
+
BeforeValidator(coerce_subclass_list(Format)),
|
|
382
|
+
],
|
|
383
|
+
)
|
|
384
|
+
ListCreativeFormatsResponse.model_rebuild(force=True)
|
|
385
|
+
|
|
386
|
+
# Apply coercion to CreateMediaBuyResponse1
|
|
387
|
+
# - context: ContextObject | dict | None
|
|
388
|
+
# - ext: ExtensionObject | dict | None
|
|
389
|
+
# - packages: list[Package] (accepts subclass instances)
|
|
390
|
+
_patch_field_annotation(
|
|
391
|
+
CreateMediaBuyResponse1,
|
|
392
|
+
"context",
|
|
393
|
+
Annotated[ContextObject | None, BeforeValidator(coerce_to_model(ContextObject))],
|
|
394
|
+
)
|
|
395
|
+
_patch_field_annotation(
|
|
396
|
+
CreateMediaBuyResponse1,
|
|
397
|
+
"ext",
|
|
398
|
+
Annotated[ExtensionObject | None, BeforeValidator(coerce_to_model(ExtensionObject))],
|
|
399
|
+
)
|
|
400
|
+
_patch_field_annotation(
|
|
401
|
+
CreateMediaBuyResponse1,
|
|
402
|
+
"packages",
|
|
403
|
+
Annotated[
|
|
404
|
+
list[Package],
|
|
405
|
+
BeforeValidator(coerce_subclass_list(Package)),
|
|
406
|
+
],
|
|
407
|
+
)
|
|
408
|
+
CreateMediaBuyResponse1.model_rebuild(force=True)
|
|
409
|
+
|
|
410
|
+
# Apply coercion to GetMediaBuyDeliveryResponse
|
|
411
|
+
# - context: ContextObject | dict | None
|
|
412
|
+
# - errors: list[Error] (accepts subclass instances)
|
|
413
|
+
# - ext: ExtensionObject | dict | None
|
|
414
|
+
# - media_buy_deliveries: list[MediaBuyDelivery] (accepts subclass instances)
|
|
415
|
+
# - notification_type: NotificationType | str | None
|
|
416
|
+
_patch_field_annotation(
|
|
417
|
+
GetMediaBuyDeliveryResponse,
|
|
418
|
+
"context",
|
|
419
|
+
Annotated[ContextObject | None, BeforeValidator(coerce_to_model(ContextObject))],
|
|
420
|
+
)
|
|
421
|
+
_patch_field_annotation(
|
|
422
|
+
GetMediaBuyDeliveryResponse,
|
|
423
|
+
"errors",
|
|
424
|
+
Annotated[
|
|
425
|
+
list[Error] | None,
|
|
426
|
+
BeforeValidator(coerce_subclass_list(Error)),
|
|
427
|
+
],
|
|
428
|
+
)
|
|
429
|
+
_patch_field_annotation(
|
|
430
|
+
GetMediaBuyDeliveryResponse,
|
|
431
|
+
"ext",
|
|
432
|
+
Annotated[ExtensionObject | None, BeforeValidator(coerce_to_model(ExtensionObject))],
|
|
433
|
+
)
|
|
434
|
+
_patch_field_annotation(
|
|
435
|
+
GetMediaBuyDeliveryResponse,
|
|
436
|
+
"media_buy_deliveries",
|
|
437
|
+
Annotated[
|
|
438
|
+
list[MediaBuyDelivery],
|
|
439
|
+
BeforeValidator(coerce_subclass_list(MediaBuyDelivery)),
|
|
440
|
+
],
|
|
441
|
+
)
|
|
442
|
+
_patch_field_annotation(
|
|
443
|
+
GetMediaBuyDeliveryResponse,
|
|
444
|
+
"notification_type",
|
|
445
|
+
Annotated[NotificationType | None, BeforeValidator(coerce_to_enum(NotificationType))],
|
|
446
|
+
)
|
|
447
|
+
GetMediaBuyDeliveryResponse.model_rebuild(force=True)
|
|
448
|
+
|
|
264
449
|
|
|
265
450
|
def _patch_field_annotation(
|
|
266
451
|
model: type,
|
|
@@ -394,3 +394,221 @@ class TestSerializationRoundtrip:
|
|
|
394
394
|
assert restored.asset_types == [AssetContentType.image, AssetContentType.html]
|
|
395
395
|
assert restored.context.key == "value"
|
|
396
396
|
assert restored.name_search == "test"
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
class TestResponseTypeCoercion:
|
|
400
|
+
"""Test that response types accept flexible input types.
|
|
401
|
+
|
|
402
|
+
These tests verify the ergonomics improvements from GitHub issue #105,
|
|
403
|
+
which extends type coercion from request types to response types.
|
|
404
|
+
"""
|
|
405
|
+
|
|
406
|
+
def test_list_creative_formats_response_accepts_dict_context(self):
|
|
407
|
+
"""ListCreativeFormatsResponse.context accepts dict."""
|
|
408
|
+
from adcp.types import Format, FormatCategory, ListCreativeFormatsResponse
|
|
409
|
+
|
|
410
|
+
format_obj = Format(
|
|
411
|
+
format_id={"agent_url": "https://example.com", "id": "banner-300x250"},
|
|
412
|
+
name="Banner 300x250",
|
|
413
|
+
type=FormatCategory.display,
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
response = ListCreativeFormatsResponse(
|
|
417
|
+
formats=[format_obj],
|
|
418
|
+
context={"request_id": "456"},
|
|
419
|
+
)
|
|
420
|
+
assert isinstance(response.context, ContextObject)
|
|
421
|
+
assert response.context.request_id == "456"
|
|
422
|
+
|
|
423
|
+
def test_list_creative_formats_response_accepts_format_subclass(self):
|
|
424
|
+
"""ListCreativeFormatsResponse.formats accepts Format subclass instances."""
|
|
425
|
+
from pydantic import Field
|
|
426
|
+
|
|
427
|
+
from adcp.types import Format, FormatCategory, ListCreativeFormatsResponse
|
|
428
|
+
|
|
429
|
+
class ExtendedFormat(Format):
|
|
430
|
+
"""Extended with internal tracking fields."""
|
|
431
|
+
|
|
432
|
+
internal_id: str | None = Field(None, exclude=True)
|
|
433
|
+
|
|
434
|
+
format_obj = ExtendedFormat(
|
|
435
|
+
format_id={"agent_url": "https://example.com", "id": "banner-300x250"},
|
|
436
|
+
name="Banner 300x250",
|
|
437
|
+
type=FormatCategory.display,
|
|
438
|
+
internal_id="format-internal-123",
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
# No cast() needed!
|
|
442
|
+
response = ListCreativeFormatsResponse(
|
|
443
|
+
formats=[format_obj], # type: ignore[list-item] # Ignoring due to Python list covariance limitation
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
assert len(response.formats) == 1
|
|
447
|
+
assert response.formats[0].name == "Banner 300x250"
|
|
448
|
+
# Internal field is preserved at runtime
|
|
449
|
+
assert response.formats[0].internal_id == "format-internal-123" # type: ignore[attr-defined]
|
|
450
|
+
|
|
451
|
+
def test_create_media_buy_response_accepts_package_subclass(self):
|
|
452
|
+
"""CreateMediaBuySuccessResponse.packages accepts Package subclass instances."""
|
|
453
|
+
from pydantic import Field
|
|
454
|
+
|
|
455
|
+
from adcp.types import CreateMediaBuySuccessResponse, Package
|
|
456
|
+
|
|
457
|
+
class ExtendedPackage(Package):
|
|
458
|
+
"""Extended with internal tracking fields."""
|
|
459
|
+
|
|
460
|
+
campaign_id: str | None = Field(None, exclude=True)
|
|
461
|
+
|
|
462
|
+
package = ExtendedPackage(
|
|
463
|
+
package_id="pkg1",
|
|
464
|
+
campaign_id="campaign-456",
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
# No cast() needed!
|
|
468
|
+
response = CreateMediaBuySuccessResponse(
|
|
469
|
+
media_buy_id="mb1",
|
|
470
|
+
buyer_ref="buyer-ref",
|
|
471
|
+
packages=[package], # type: ignore[list-item] # Ignoring due to Python list covariance limitation
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
assert len(response.packages) == 1
|
|
475
|
+
assert response.packages[0].package_id == "pkg1"
|
|
476
|
+
# Internal field is preserved at runtime
|
|
477
|
+
assert response.packages[0].campaign_id == "campaign-456" # type: ignore[attr-defined]
|
|
478
|
+
|
|
479
|
+
def test_get_media_buy_delivery_response_accepts_dict_context(self):
|
|
480
|
+
"""GetMediaBuyDeliveryResponse.context accepts dict."""
|
|
481
|
+
from datetime import datetime, timezone
|
|
482
|
+
|
|
483
|
+
from adcp.types import GetMediaBuyDeliveryResponse, MediaBuyDelivery
|
|
484
|
+
|
|
485
|
+
delivery = MediaBuyDelivery(
|
|
486
|
+
media_buy_id="mb1",
|
|
487
|
+
status="active",
|
|
488
|
+
by_package=[
|
|
489
|
+
{
|
|
490
|
+
"package_id": "pkg1",
|
|
491
|
+
"currency": "USD",
|
|
492
|
+
"pricing_model": "cpm",
|
|
493
|
+
"rate": 10.0,
|
|
494
|
+
"impressions": 1000,
|
|
495
|
+
"spend": 10.0,
|
|
496
|
+
}
|
|
497
|
+
],
|
|
498
|
+
totals={"impressions": 1000, "spend": 10.0},
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
response = GetMediaBuyDeliveryResponse(
|
|
502
|
+
currency="USD",
|
|
503
|
+
reporting_period={
|
|
504
|
+
"start": datetime(2024, 1, 1, tzinfo=timezone.utc),
|
|
505
|
+
"end": datetime(2024, 1, 31, tzinfo=timezone.utc),
|
|
506
|
+
},
|
|
507
|
+
media_buy_deliveries=[delivery],
|
|
508
|
+
context={"request_id": "789"},
|
|
509
|
+
)
|
|
510
|
+
assert isinstance(response.context, ContextObject)
|
|
511
|
+
assert response.context.request_id == "789"
|
|
512
|
+
|
|
513
|
+
def test_response_serialization_roundtrip(self):
|
|
514
|
+
"""Response types with coerced values can roundtrip through JSON."""
|
|
515
|
+
from adcp.types import Format, FormatCategory, ListCreativeFormatsResponse
|
|
516
|
+
|
|
517
|
+
format_obj = Format(
|
|
518
|
+
format_id={"agent_url": "https://example.com", "id": "banner-300x250"},
|
|
519
|
+
name="Banner 300x250",
|
|
520
|
+
type=FormatCategory.display,
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
response = ListCreativeFormatsResponse(
|
|
524
|
+
formats=[format_obj],
|
|
525
|
+
context={"key": "value"},
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
json_str = response.model_dump_json()
|
|
529
|
+
restored = ListCreativeFormatsResponse.model_validate_json(json_str)
|
|
530
|
+
|
|
531
|
+
assert len(restored.formats) == 1
|
|
532
|
+
assert restored.formats[0].name == "Banner 300x250"
|
|
533
|
+
assert restored.context.key == "value"
|
|
534
|
+
|
|
535
|
+
def test_get_products_response_accepts_product_subclass(self):
|
|
536
|
+
"""GetProductsResponse.products accepts Product subclass instances."""
|
|
537
|
+
from pydantic import Field
|
|
538
|
+
|
|
539
|
+
from adcp.types import (
|
|
540
|
+
CpmFixedRatePricingOption,
|
|
541
|
+
DeliveryType,
|
|
542
|
+
FormatId,
|
|
543
|
+
GetProductsResponse,
|
|
544
|
+
Product,
|
|
545
|
+
PublisherPropertiesAll,
|
|
546
|
+
)
|
|
547
|
+
from adcp.types.generated_poc.core.product import DeliveryMeasurement
|
|
548
|
+
|
|
549
|
+
class ExtendedProduct(Product):
|
|
550
|
+
"""Extended with internal tracking fields."""
|
|
551
|
+
|
|
552
|
+
internal_sku: str | None = Field(None, exclude=True)
|
|
553
|
+
|
|
554
|
+
product = ExtendedProduct(
|
|
555
|
+
product_id="prod-123",
|
|
556
|
+
name="Premium Display",
|
|
557
|
+
description="A premium display product",
|
|
558
|
+
delivery_type=DeliveryType.guaranteed,
|
|
559
|
+
delivery_measurement=DeliveryMeasurement(provider="Test Provider"),
|
|
560
|
+
format_ids=[FormatId(agent_url="https://example.com", id="banner-300x250")],
|
|
561
|
+
pricing_options=[
|
|
562
|
+
CpmFixedRatePricingOption(
|
|
563
|
+
currency="USD",
|
|
564
|
+
pricing_option_id="opt-1",
|
|
565
|
+
rate=5.0,
|
|
566
|
+
is_fixed=True,
|
|
567
|
+
pricing_model="cpm",
|
|
568
|
+
)
|
|
569
|
+
],
|
|
570
|
+
publisher_properties=[
|
|
571
|
+
PublisherPropertiesAll(
|
|
572
|
+
publisher_domain="example.com",
|
|
573
|
+
selection_type="all",
|
|
574
|
+
)
|
|
575
|
+
],
|
|
576
|
+
internal_sku="SKU-12345",
|
|
577
|
+
)
|
|
578
|
+
|
|
579
|
+
# No cast() needed!
|
|
580
|
+
response = GetProductsResponse(
|
|
581
|
+
products=[product], # type: ignore[list-item] # Ignoring due to Python list covariance limitation
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
assert len(response.products) == 1
|
|
585
|
+
assert response.products[0].product_id == "prod-123"
|
|
586
|
+
# Internal field is preserved at runtime
|
|
587
|
+
assert response.products[0].internal_sku == "SKU-12345" # type: ignore[attr-defined]
|
|
588
|
+
|
|
589
|
+
def test_response_errors_accepts_error_subclass(self):
|
|
590
|
+
"""Response types with errors field accept Error subclass instances."""
|
|
591
|
+
from pydantic import Field
|
|
592
|
+
|
|
593
|
+
from adcp.types import Error, GetProductsResponse
|
|
594
|
+
|
|
595
|
+
class ExtendedError(Error):
|
|
596
|
+
"""Extended with internal tracking fields."""
|
|
597
|
+
|
|
598
|
+
internal_trace_id: str | None = Field(None, exclude=True)
|
|
599
|
+
|
|
600
|
+
error = ExtendedError(
|
|
601
|
+
code="INVALID_REQUEST",
|
|
602
|
+
message="Product ID is required",
|
|
603
|
+
internal_trace_id="trace-abc-123",
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
response = GetProductsResponse(
|
|
607
|
+
products=[],
|
|
608
|
+
errors=[error], # type: ignore[list-item] # Ignoring due to Python list covariance limitation
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
assert len(response.errors) == 1
|
|
612
|
+
assert response.errors[0].code == "INVALID_REQUEST"
|
|
613
|
+
# Internal field is preserved at runtime
|
|
614
|
+
assert response.errors[0].internal_trace_id == "trace-abc-123" # type: ignore[attr-defined]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|