Module adcp.types.canonical_creative
Canonical-first creative models for the Python 7 public API.
The generated protocol models intentionally remain wire-faithful through the
AdCP 3.x transition and therefore contain legacy named-format identity.
They
are exposed from :mod:adcp.types.legacy.
This module provides the primary
application-facing models: legacy identity is absent from their declared
fields, JSON Schema, and serialized output at every nesting depth.
format_kind is a str, not the generated enum — a deliberate override
core/canonical-format-kind.json declares a closed 16-member enum
and, in the same file, states as normative:
Consumer SDKs MUST treat this enum as **open** at parse time: an unknown
<code>format\_kind</code> value MUST be retained as-is on the in-memory object (not
silently dropped or rewritten to ``"custom"``) and MUST NOT cause the
surrounding payload to fail validation. ... The producer-side enum stays
closed (sellers MUST NOT mint ad-hoc <code>format\_kind</code> values ...); the
consumer-side enum stays open for forward compatibility.
The schema already knows the rule is directional, and then encodes it as a
single closed enum, which cannot carry that. So this override implements what
the schema says rather than contradicting it: every reference to that schema
generates a bare str — OPEN_VOCABULARY_SCHEMAS in
scripts/generate_types.py, one schema-level transform rather than a
widening at each call site.
The SDK refuses nothing, in either direction, and that is deliberate. A
seller supports some set of format kinds; that set is the seller's, not this
library's and not the pinned enum's. It can be larger — the seller handles a
kind promoted in a spec newer than the pin — or smaller, four of the sixteen.
A pinned SDK cannot tell "a kind the seller invented" from "a kind defined
after my pin": both are simply "not in my 16". Refusing the second to prevent
the first would make this SDK's version a ceiling on what the protocol permits,
which is the same defect as the closed enum with the enforcement moved into a
validator. The producer-side MUST is a seller's obligation; this library gives
it the vocabulary and :func:is_canonical_format_kind() to meet it, and leaves
the decision where the knowledge is.
So the vocabulary is not discarded, it is relocated:
:class:CanonicalFormatKind stays a first-class export, used for comparison
(creative.format_kind == CanonicalFormatKind.image — it is a StrEnum,
so that holds against a plain string field and no adopter writes a literal) and
for membership through :func:is_canonical_format_kind(), whose vocabulary is a
parameter. What changed is only that the field no longer refuses the
seventeenth value a newer server sends. That is the registry pattern the
sibling fields already use: format_shape and asset_group_id are plain
strings governed by versioned registries whose own governance says
non-canonical values stay valid and validators may warn.
The one cost is that the generated models no longer agree with the bundled
schema for this one field. That is declared, by name and with this reason, as a
single entry in tests/conformance/_schema_parity.py's DECLARED —
format_kind_is_an_open_vocabulary_by_decision. The parity rule itself is
not relaxed.
Upstream ask: adcontextprotocol/adcp#7929
<https://github.com/adcontextprotocol/adcp/issues/7929>_. If it lands — the
schema stating the directional rule in a form that can carry it, the way
format_shape is governed — delete the transform, delete this section, and
the generated models go back to agreeing with their schema.
Functions
def is_canonical_format_kind(value: object,
vocabulary: Iterable[str] = adcp.types.domains.core.canonical_format_kind.CanonicalFormatKind) ‑> bool-
Expand source code
def is_canonical_format_kind( value: object, vocabulary: Iterable[str] = CanonicalFormatKind, ) -> bool: """Is *value* one of *vocabulary*'s format kinds? The vocabulary defaults to :class:`CanonicalFormatKind`, the sixteen kinds the pinned AdCP bundle declares — but it is a PARAMETER, because the set that matters is the seller's, not this SDK's. A seller may support a kind promoted in a spec newer than the pin, or only four of the sixteen, and neither is expressible by anything this library knows. **The SDK never calls this for you.** ``format_kind`` is a ``str`` everywhere, on the way out and on the way back, and no model refuses a value. That is deliberate: a pinned library cannot tell "a kind the seller invented" from "a kind defined after my pin", so refusing the second to prevent the first would make this SDK's version a ceiling on what the protocol permits. "I accept the request and then tell you I cannot process this creative" is a seller's answer, not a type error. This function is the sanctioned way to be strict, where the caller knows which spec version its counterpart speaks:: from adcp.types import is_canonical_format_kind if not is_canonical_format_kind(creative.format_kind): route_as_declared_but_unsupported(creative) if not is_canonical_format_kind(manifest.format_kind, MY_SUPPORTED_KINDS): reject_with_unsupported_format(manifest) Comparison needs no helper: ``CanonicalFormatKind`` is a ``StrEnum``, so ``creative.format_kind == CanonicalFormatKind.image`` holds against a plain string field and an adopter never writes a literal. """ return isinstance(value, str) and any(value == kind for kind in vocabulary)Is value one of vocabulary's format kinds?
The vocabulary defaults to :class:
CanonicalFormatKind, the sixteen kinds the pinned AdCP bundle declares — but it is a PARAMETER, because the set that matters is the seller's, not this SDK's. A seller may support a kind promoted in a spec newer than the pin, or only four of the sixteen, and neither is expressible by anything this library knows.The SDK never calls this for you.
format_kindis astreverywhere, on the way out and on the way back, and no model refuses a value. That is deliberate: a pinned library cannot tell "a kind the seller invented" from "a kind defined after my pin", so refusing the second to prevent the first would make this SDK's version a ceiling on what the protocol permits. "I accept the request and then tell you I cannot process this creative" is a seller's answer, not a type error.This function is the sanctioned way to be strict, where the caller knows which spec version its counterpart speaks::
from adcp.types import is_canonical_format_kind if not is_canonical_format_kind(creative.format_kind): route_as_declared_but_unsupported(creative) if not is_canonical_format_kind(manifest.format_kind, MY_SUPPORTED_KINDS): reject_with_unsupported_format(manifest)Comparison needs no helper:
CanonicalFormatKindis aStrEnum, socreative.format_kind == CanonicalFormatKind.imageholds against a plain string field and an adopter never writes a literal. def is_legacy_creative_identity_key(key: object) ‑> bool-
Expand source code
def is_legacy_creative_identity_key(key: object) -> bool: """Return whether *key* names legacy creative routing identity.""" return isinstance(key, str) and bool(_LEGACY_IDENTITY_KEY.search(key))Return whether key names legacy creative routing identity.
def sanitize_canonical_schema(schema: dict[str, Any]) ‑> dict[str, typing.Any]-
Expand source code
def sanitize_canonical_schema(schema: dict[str, Any]) -> dict[str, Any]: """Return a defensive deep copy with legacy identity removed.""" sanitized: dict[str, Any] = _sanitize_schema_node(copy.deepcopy(schema)) return sanitizedReturn a defensive deep copy with legacy identity removed.
def strip_legacy_creative_identity(value: Any) ‑> Any-
Expand source code
def strip_legacy_creative_identity( value: Any, *, _path: str = "$", _format_scope: bool = False, ) -> Any: """Recursively remove legacy creative identity from a serialized value. This is deliberately a runtime boundary rather than a typing convention. Unknown extension bags are traversed too, so ``extra='allow'`` can never be used to smuggle ``format_id`` or ``format_ids`` through a primary model. """ if isinstance(value, dict): legacy_tuple = _is_format_scoped_agent_tuple( value, path=_path, ) return { key: strip_legacy_creative_identity( item, _path=f"{_path}.{key}", _format_scope=_format_scope or (isinstance(key, str) and "format" in key.lower()), ) for key, item in value.items() if not is_legacy_creative_identity_key(key) and not (legacy_tuple and key == "agent_url") } if isinstance(value, list): return [ strip_legacy_creative_identity( item, _path=f"{_path}[{index}]", _format_scope=_format_scope, ) for index, item in enumerate(value) ] if isinstance(value, tuple): return tuple( strip_legacy_creative_identity( item, _path=f"{_path}[{index}]", _format_scope=_format_scope, ) for index, item in enumerate(value) ) return valueRecursively remove legacy creative identity from a serialized value.
This is deliberately a runtime boundary rather than a typing convention. Unknown extension bags are traversed too, so
extra='allow'can never be used to smuggleformat_idorformat_idsthrough a primary model.
Classes
class CanonicalBoundaryModel (**data: Any)-
Expand source code
class CanonicalBoundaryModel(AdCPBaseModel): """Base class enforcing the primary canonical runtime boundary. Every canonical model is a real subclass of the generated wire model it refines, so each one inherits the generated model's fields, its injected ``model_validator``s, and its envelope ancestry. Two concerns that used to be re-attached per class by ``create_model`` are therefore declared once, here, and inherited: * ``_serialize_canonical`` — the wrap serializer that strips legacy creative identity from nested and ``TypeAdapter`` serialization. * ``__pydantic_init_subclass__`` — the one declared field removal. Legacy creative identity must be absent from a canonical model's *declared* fields, which is the single thing inheritance alone cannot express; the rule reads the same :func:`is_legacy_creative_identity_key` predicate that governs the input validator, the schema sanitizer and the serializer, so there is one strip predicate for all four. ``CanonicalBoundaryModel`` is listed LAST among a canonical model's bases. Pydantic merges ``model_config`` across bases left to right, so the right-most base wins; the generated wire model inherits :class:`AdCPBaseModel`'s ``extra`` policy and would otherwise override this class's ``extra="allow"`` and start dropping caller-supplied extension keys. """ model_config = ConfigDict(extra="allow", defer_build=True) __adcp_canonical_creative_model__: ClassVar[bool] = True _serialize_canonical = model_serializer(mode="wrap")(_serialize_canonical_model) @classmethod def __pydantic_init_subclass__(cls, **kwargs: Any) -> None: """Remove inherited legacy creative identity from the declared fields. Each removed name is then bound as a plain class attribute holding ``None`` — which is the removal's own truth, and which the inherited validators need. A generated model can carry an injected validator that READS the removed field: ``list-creatives-response.json``'s ``_validate_format_reference_xor`` evaluates ``(self.format_id is None) == (self.format_kind is None)``. Inheritance is the point of this layer, so that validator now runs on the canonical model, and with the field merely deleted it raised ``AttributeError``. With the name reading ``None`` the XOR reduces to exactly the invariant the canonical model should hold — ``format_kind`` must be set — which is the same thing the canonical declaration states by making it required. Binding happens AFTER class creation, so pydantic never considers the name a field candidate; ``model_fields``, the JSON schema and the wire are all unaffected. Measured scope: one such validator, on one model. """ removed = [name for name in cls.model_fields if is_legacy_creative_identity_key(name)] for name in removed: del cls.model_fields[name] cls.__annotations__.pop(name, None) setattr(cls, name, None) if removed: cls.model_rebuild(force=True) @model_validator(mode="before") @classmethod def _reject_legacy_creative_identity(cls, value: Any) -> Any: found = _legacy_creative_identity_path( value, allow_root_v1_ref=cls.__name__ == "Format", format_scope=cls.__name__ == "Format", ) if found is not None: raise ValueError( f"{found} contains legacy creative identity; use an explicit Legacy* model" ) return value def model_dump(self, **kwargs: Any) -> dict[str, Any]: kwargs.setdefault("serialize_as_any", False) stripped: dict[str, Any] = strip_legacy_creative_identity( super().model_dump(**kwargs), _format_scope=self.__class__.__name__ == "Format", ) return stripped def model_dump_json(self, **kwargs: Any) -> str: kwargs.setdefault("serialize_as_any", False) raw = super().model_dump_json(**kwargs) clean = strip_legacy_creative_identity( json.loads(raw), _format_scope=self.__class__.__name__ == "Format", ) indent = kwargs.get("indent") return json.dumps( clean, ensure_ascii=False, indent=indent, separators=None if indent is not None else (",", ":"), ) @classmethod def model_json_schema(cls, *args: Any, **kwargs: Any) -> dict[str, Any]: return sanitize_canonical_schema(super().model_json_schema(*args, **kwargs)) @classmethod def __get_pydantic_json_schema__( cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler, ) -> dict[str, Any]: """Enforce the boundary for TypeAdapter and containing-model schemas.""" schema = sanitize_canonical_schema(handler(core_schema)) # TypeAdapter assembles shared definitions outside the model's returned # node. Mutate the active generator's definition registry as well so # unreachable generated legacy definitions cannot leak into the final # recursive schema document. generator = cast(_JsonSchemaHandlerWithGenerator, handler).generate_json_schema for key, definition in list(generator.definitions.items()): generator.definitions[key] = sanitize_canonical_schema(definition) return schemaBase class enforcing the primary canonical runtime boundary.
Every canonical model is a real subclass of the generated wire model it refines, so each one inherits the generated model's fields, its injected
model_validators, and its envelope ancestry. Two concerns that used to be re-attached per class bycreate_modelare therefore declared once, here, and inherited:_serialize_canonical— the wrap serializer that strips legacy creative identity from nested andTypeAdapterserialization.__pydantic_init_subclass__— the one declared field removal. Legacy creative identity must be absent from a canonical model's declared fields, which is the single thing inheritance alone cannot express; the rule reads the same :func:is_legacy_creative_identity_key()predicate that governs the input validator, the schema sanitizer and the serializer, so there is one strip predicate for all four.
CanonicalBoundaryModelis listed LAST among a canonical model's bases. Pydantic mergesmodel_configacross bases left to right, so the right-most base wins; the generated wire model inherits :class:AdCPBaseModel'sextrapolicy and would otherwise override this class'sextra="allow"and start dropping caller-supplied extension keys.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- AdCPBaseModel
- pydantic.main.BaseModel
Subclasses
- CreateMediaBuyRequest
- CreateMediaBuyResponse1
- CreateMediaBuyResponse2
- CreateMediaBuyResponse3
- Creative
- CreativeAsset
- CreativeFilters
- CreativeManifest
- CreativeVariant
- DeliveryCreative
- Format
- GetCreativeDeliveryResponse
- GetMediaBuyDeliveryResponse
- GetMediaBuysResponse
- GetProductsRequest
- GetProductsResponse
- ListCreativesRequest
- ListCreativesResponse
- MediaBuy
- MediaBuyPackage
- Package
- PackageRequest
- PackageUpdate
- Placement
- Product
- ProductFilters
- SyncCreativesRequest
- UpdateMediaBuyRequest
- UpdateMediaBuyResponse1
- UpdateMediaBuyResponse2
- UpdateMediaBuyResponse3
- adcp.types.canonical_creative._DeliveryCreativeManifest
- adcp.types.canonical_creative._DeliveryCreativeVariant
Class variables
var model_config
Static methods
def model_json_schema(*args: Any, **kwargs: Any) ‑> dict[str, typing.Any]-
Generates a JSON schema for a model class.
- Args
- -----=
by_alias- Whether to use attribute aliases or not.
ref_template- The reference template.
union_format-
The format to use when combining schemas from unions together. Can be one of:
'any_of': Use theanyOfkeyword to combine schemas (the default).'primitive_type_array': Use thetypekeyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (string,boolean,null,integerornumber) or contains constraints/metadata, falls back toany_of.
schema_generator- To override the logic used to generate the JSON schema, as a subclass of
GenerateJsonSchemawith your desired modifications mode- The mode in which to generate the schema.
Returns -----= The JSON schema for the given model class.
Inherited members
class CreateMediaBuyRequest (**data: Any)-
Expand source code
class CreateMediaBuyRequest(_LegacyCreateMediaBuyRequest, CanonicalBoundaryModel): """Canonical create request; packages are canonical package requests.""" packages: list[PackageRequest] | None = NoneCanonical create request; packages are canonical package requests.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar packages : list[PackageRequest] | None
Inherited members
class CreateMediaBuyResponse1 (**data: Any)-
Expand source code
class CreateMediaBuyResponse1(_LegacyCreateMediaBuyResponse1, CanonicalBoundaryModel): """Canonical create response preserving the 3.x legacy-status normalizer.""" packages: list[Package] # type: ignore[assignment] @model_validator(mode="before") @classmethod def _normalize_legacy_status(cls, data: Any) -> Any: if not isinstance(data, dict): return data raw_status = unwrap_enum_value(data.get("status")) media_buy_status = unwrap_enum_value(data.get("media_buy_status")) if raw_status is None or raw_status == "completed": return {**data, "status": "completed"} if media_buy_status is None and raw_status in MEDIA_BUY_LEGACY_STATUS_VALUES: return {**data, "media_buy_status": raw_status, "status": "completed"} if media_buy_status is not None and raw_status == media_buy_status: return {**data, "status": "completed"} return dataCanonical create response preserving the 3.x legacy-status normalizer.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyResponse1
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar packages : list[Package]
Inherited members
class CreateMediaBuyResponse2 (**data: Any)-
Expand source code
class CreateMediaBuyResponse2(_LegacyCreateMediaBuyResponse2, CanonicalBoundaryModel): """Canonical create-media-buy error arm."""Canonical create-media-buy error arm.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyResponse2
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class CreateMediaBuyResponse3 (**data: Any)-
Expand source code
class CreateMediaBuyResponse3(_LegacyCreateMediaBuyResponse3, CanonicalBoundaryModel): """Canonical create-media-buy submitted arm."""Canonical create-media-buy submitted arm.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreateMediaBuyResponse3
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class Creative (**data: Any)-
Expand source code
class Creative(_CanonicalListedCreative, CanonicalBoundaryModel): """Canonical listed creative; the format kind is required, not optional. A listed creative is a row a seller RETURNS, so the kind is required but never confined: a kind a newer seller emits is retained as-is, which is what ``core/canonical-format-kind.json`` requires of a consumer. """ if TYPE_CHECKING: # the removed field, hidden from the constructor too format_id: _RemovedFormatId = Field(default=None, init=False) format_kind: strCanonical listed creative; the format kind is required, not optional.
A listed creative is a row a seller RETURNS, so the kind is required but never confined: a kind a newer seller emits is retained as-is, which is what
core/canonical-format-kind.jsonrequires of a consumer.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- Creative
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_id : FormatReferenceStructuredObject | Nonevar format_kind : strvar model_config
Inherited members
class CreativeAsset (**data: Any)-
Expand source code
class CreativeAsset(_CanonicalCreativeWire, CanonicalBoundaryModel): """Canonical creative asset; the format kind is required, not optional. The kind is narrowed to required and nothing else: it stays ``str`` and the model refuses no value. A buyer SENDS a creative asset, and the producer-side "sellers MUST NOT mint ad-hoc kinds" rule is the sender's obligation, not something a pinned library can tell from a kind defined after its pin — :func:`is_canonical_format_kind` is how a caller meets it. """ if TYPE_CHECKING: # the removed field, hidden from the constructor too format_id: _RemovedFormatId = Field(default=None, init=False) format_kind: strCanonical creative asset; the format kind is required, not optional.
The kind is narrowed to required and nothing else: it stays
strand the model refuses no value. A buyer SENDS a creative asset, and the producer-side "sellers MUST NOT mint ad-hoc kinds" rule is the sender's obligation, not something a pinned library can tell from a kind defined after its pin — :func:is_canonical_format_kind()is how a caller meets it.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreativeAsset
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_id : FormatReferenceStructuredObject | Nonevar format_kind : strvar model_config
Instance variables
var placement_ids : list[str] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
Inherited members
class CreativeFilters (**data: Any)-
Expand source code
class CreativeFilters(_LegacyCreativeFilters, CanonicalBoundaryModel): """Canonical creative filters; legacy identity selection is unavailable.""" if TYPE_CHECKING: # the removed field, hidden from the constructor too format_ids: _RemovedFormatIds = Field(default=None, init=False)Canonical creative filters; legacy identity selection is unavailable.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreativeFilters
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_ids : list[FormatReferenceStructuredObject] | Nonevar model_config
Inherited members
class CreativeManifest (**data: Any)-
Expand source code
class CreativeManifest(_CanonicalCreativeManifestWire, CanonicalBoundaryModel): """Canonical manifest accepting the SDK's public standalone asset models. The 3.2 aggregate asset-union schema currently generates structurally duplicate Pydantic classes. Convert public ``ImageContent``/``UrlContent`` (and peers) back to their wire dictionaries before the aggregate union validates them. This keeps the public constructors composable without relaxing the on-wire discriminator checks. """ if TYPE_CHECKING: # the removed field, hidden from the constructor too format_id: _RemovedFormatId = Field(default=None, init=False) @model_validator(mode="before") @classmethod def _normalize_standalone_assets(cls, data: Any) -> Any: if not isinstance(data, dict) or not isinstance(data.get("assets"), dict): return data def wire_value(value: Any) -> Any: if isinstance(value, AdCPBaseModel): return value.model_dump(mode="json", exclude_none=True) if isinstance(value, list): return [wire_value(item) for item in value] return value return { **data, "assets": {key: wire_value(value) for key, value in data["assets"].items()}, }Canonical manifest accepting the SDK's public standalone asset models.
The 3.2 aggregate asset-union schema currently generates structurally duplicate Pydantic classes. Convert public
ImageContent/UrlContent(and peers) back to their wire dictionaries before the aggregate union validates them. This keeps the public constructors composable without relaxing the on-wire discriminator checks.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreativeManifest
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class CreativeVariant (**data: Any)-
Expand source code
class CreativeVariant(_LegacyCreativeVariant, CanonicalBoundaryModel): """Canonical creative variant whose manifest is the canonical manifest.""" manifest: CreativeManifest | None = NoneCanonical creative variant whose manifest is the canonical manifest.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CreativeVariant
- DeliveryMetrics
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var manifest : CreativeManifest | Nonevar model_config
Inherited members
class DeliveryCreative (**data: Any)-
Expand source code
class DeliveryCreative(_LegacyDeliveryCreative, CanonicalBoundaryModel): """Canonical served creative; variants are the read-back delivery rows.""" if TYPE_CHECKING: # the removed field, hidden from the constructor too format_id: _RemovedFormatId = Field(default=None, init=False) variants: list[_DeliveryCreativeVariant] = _inherit( # type: ignore[assignment] _LegacyDeliveryCreative, "variants" )Canonical served creative; variants are the read-back delivery rows.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- Creative
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar variants : list[adcp.types.canonical_creative._DeliveryCreativeVariant]
Inherited members
class Format (**data: Any)-
Expand source code
class Format(CanonicalBoundaryModel): """Canonical format declaration exposed as ``adcp.Format``.""" format_option_id: str | None = Field( default=None, description="Stable option identifier within the product or publisher namespace.", ) publisher_domain: str | None = Field( default=None, pattern=r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", ) display_name: str | None = None applies_to_channels: list[MediaChannel] | None = None seller_preference: SellerPreference | None = None canonical_formats_only: bool | None = None experimental: bool | None = None format_shape: str | None = None format_schema: PlatformExtensionReference | None = None format_kind: str params: dict[str, Any] _legacy_format_refs: list[LegacyFormatId] = PrivateAttr(default_factory=list) @model_validator(mode="before") @classmethod def _reject_legacy_conflicts_and_credentials(cls, data: Any) -> Any: if not isinstance(data, dict): return data if data.get("canonical_formats_only") is True and data.get("v1_format_ref"): raise ValueError( "canonical_formats_only=True is mutually exclusive with legacy v1_format_ref" ) for bag_name, bag in ( ("params", data.get("params")), ( "extras", { key: value for key, value in data.items() if key not in cls.model_fields and key != "v1_format_ref" }, ), ): found = _walk_for_credential_keys(bag, path=bag_name) if found is not None: raise ValueError( f"{found!r} matches a credential-shaped key suffix and cannot " "be stored in a canonical format declaration" ) return data def __init__(self, **data: Any) -> None: refs = data.get("v1_format_ref") if "capability_id" in data and "format_option_id" not in data: data["format_option_id"] = data.pop("capability_id") super().__init__(**data) if self.__pydantic_extra__ is not None: self.__pydantic_extra__.pop("v1_format_ref", None) if refs: self._legacy_format_refs = [ LegacyFormatId.model_validate(copy.deepcopy(ref)) for ref in refs ] @property def legacy_format_refs(self) -> tuple[LegacyFormatId, ...]: """Original tuples retained only for an explicit compatibility adapter.""" return tuple(copy.deepcopy(ref) for ref in self._legacy_format_refs) def params_as(self, canonical_type: type[_CanonicalParamsT]) -> _CanonicalParamsT: """Validate the open parameter bag against a typed canonical model.""" return canonical_type.model_validate(self.params) @model_validator(mode="after") def _validate_custom_shape(self) -> Format: if self.format_kind == CanonicalFormatKind.custom.value: if not self.format_shape: raise ValueError("custom formats require format_shape") if self.format_schema is None: raise ValueError("custom formats require format_schema") elif self.format_shape is not None or self.format_schema is not None: raise ValueError("format_shape and format_schema are only valid for custom formats") return selfCanonical format declaration exposed as
Format.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var applies_to_channels : list[MediaChannel] | Nonevar canonical_formats_only : bool | Nonevar display_name : str | Nonevar experimental : bool | Nonevar format_kind : strvar format_option_id : str | Nonevar format_schema : PlatformExtensionReference | Nonevar format_shape : str | Nonevar model_configvar params : dict[str, typing.Any]var publisher_domain : str | Nonevar seller_preference : SellerPreference | None
Instance variables
prop legacy_format_refs : tuple[LegacyFormatId, ...]-
Expand source code
@property def legacy_format_refs(self) -> tuple[LegacyFormatId, ...]: """Original tuples retained only for an explicit compatibility adapter.""" return tuple(copy.deepcopy(ref) for ref in self._legacy_format_refs)Original tuples retained only for an explicit compatibility adapter.
Methods
def model_post_init(self: BaseModel, context: Any, /) ‑> None-
Expand source code
def init_private_attributes(self: BaseModel, context: Any, /) -> None: """This function is meant to behave like a BaseModel method to initialize private attributes. It takes context as an argument since that's what pydantic-core passes when calling it. Args: self: The BaseModel instance. context: The context. """ if getattr(self, '__pydantic_private__', None) is None: pydantic_private = {} for name, private_attr in self.__private_attributes__.items(): # Avoid needlessly creating a new dict for the validated data: if private_attr.default_factory_takes_validated_data: default = private_attr.get_default( call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} ) else: default = private_attr.get_default(call_default_factory=True) if default is not PydanticUndefined: pydantic_private[name] = default object_setattr(self, '__pydantic_private__', pydantic_private)This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
- Args
- -----=
self- The BaseModel instance.
context- The context.
def params_as(self, canonical_type: type[_CanonicalParamsT]) ‑> ~_CanonicalParamsT-
Expand source code
def params_as(self, canonical_type: type[_CanonicalParamsT]) -> _CanonicalParamsT: """Validate the open parameter bag against a typed canonical model.""" return canonical_type.model_validate(self.params)Validate the open parameter bag against a typed canonical model.
class ProductFormatDeclaration (**data: Any)-
Expand source code
class Format(CanonicalBoundaryModel): """Canonical format declaration exposed as ``adcp.Format``.""" format_option_id: str | None = Field( default=None, description="Stable option identifier within the product or publisher namespace.", ) publisher_domain: str | None = Field( default=None, pattern=r"^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$", ) display_name: str | None = None applies_to_channels: list[MediaChannel] | None = None seller_preference: SellerPreference | None = None canonical_formats_only: bool | None = None experimental: bool | None = None format_shape: str | None = None format_schema: PlatformExtensionReference | None = None format_kind: str params: dict[str, Any] _legacy_format_refs: list[LegacyFormatId] = PrivateAttr(default_factory=list) @model_validator(mode="before") @classmethod def _reject_legacy_conflicts_and_credentials(cls, data: Any) -> Any: if not isinstance(data, dict): return data if data.get("canonical_formats_only") is True and data.get("v1_format_ref"): raise ValueError( "canonical_formats_only=True is mutually exclusive with legacy v1_format_ref" ) for bag_name, bag in ( ("params", data.get("params")), ( "extras", { key: value for key, value in data.items() if key not in cls.model_fields and key != "v1_format_ref" }, ), ): found = _walk_for_credential_keys(bag, path=bag_name) if found is not None: raise ValueError( f"{found!r} matches a credential-shaped key suffix and cannot " "be stored in a canonical format declaration" ) return data def __init__(self, **data: Any) -> None: refs = data.get("v1_format_ref") if "capability_id" in data and "format_option_id" not in data: data["format_option_id"] = data.pop("capability_id") super().__init__(**data) if self.__pydantic_extra__ is not None: self.__pydantic_extra__.pop("v1_format_ref", None) if refs: self._legacy_format_refs = [ LegacyFormatId.model_validate(copy.deepcopy(ref)) for ref in refs ] @property def legacy_format_refs(self) -> tuple[LegacyFormatId, ...]: """Original tuples retained only for an explicit compatibility adapter.""" return tuple(copy.deepcopy(ref) for ref in self._legacy_format_refs) def params_as(self, canonical_type: type[_CanonicalParamsT]) -> _CanonicalParamsT: """Validate the open parameter bag against a typed canonical model.""" return canonical_type.model_validate(self.params) @model_validator(mode="after") def _validate_custom_shape(self) -> Format: if self.format_kind == CanonicalFormatKind.custom.value: if not self.format_shape: raise ValueError("custom formats require format_shape") if self.format_schema is None: raise ValueError("custom formats require format_schema") elif self.format_shape is not None or self.format_schema is not None: raise ValueError("format_shape and format_schema are only valid for custom formats") return selfCanonical format declaration exposed as
Format.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var applies_to_channels : list[MediaChannel] | Nonevar canonical_formats_only : bool | Nonevar display_name : str | Nonevar experimental : bool | Nonevar format_kind : strvar format_option_id : str | Nonevar format_schema : PlatformExtensionReference | Nonevar format_shape : str | Nonevar model_configvar params : dict[str, typing.Any]var publisher_domain : str | Nonevar seller_preference : SellerPreference | None
Instance variables
prop legacy_format_refs : tuple[LegacyFormatId, ...]-
Expand source code
@property def legacy_format_refs(self) -> tuple[LegacyFormatId, ...]: """Original tuples retained only for an explicit compatibility adapter.""" return tuple(copy.deepcopy(ref) for ref in self._legacy_format_refs)Original tuples retained only for an explicit compatibility adapter.
Methods
def model_post_init(self: BaseModel, context: Any, /) ‑> None-
Expand source code
def init_private_attributes(self: BaseModel, context: Any, /) -> None: """This function is meant to behave like a BaseModel method to initialize private attributes. It takes context as an argument since that's what pydantic-core passes when calling it. Args: self: The BaseModel instance. context: The context. """ if getattr(self, '__pydantic_private__', None) is None: pydantic_private = {} for name, private_attr in self.__private_attributes__.items(): # Avoid needlessly creating a new dict for the validated data: if private_attr.default_factory_takes_validated_data: default = private_attr.get_default( call_default_factory=True, validated_data={**self.__dict__, **pydantic_private} ) else: default = private_attr.get_default(call_default_factory=True) if default is not PydanticUndefined: pydantic_private[name] = default object_setattr(self, '__pydantic_private__', pydantic_private)This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
- Args
- -----=
self- The BaseModel instance.
context- The context.
def params_as(self, canonical_type: type[_CanonicalParamsT]) ‑> ~_CanonicalParamsT-
Expand source code
def params_as(self, canonical_type: type[_CanonicalParamsT]) -> _CanonicalParamsT: """Validate the open parameter bag against a typed canonical model.""" return canonical_type.model_validate(self.params)Validate the open parameter bag against a typed canonical model.
Inherited members
class GetCreativeDeliveryResponse (**data: Any)-
Expand source code
class GetCreativeDeliveryResponse(_LegacyGetCreativeDeliveryResponse, CanonicalBoundaryModel): """Canonical creative delivery response; rows are the read-back delivery creatives.""" creatives: Sequence[DeliveryCreative]Canonical creative delivery response; rows are the read-back delivery creatives.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetCreativeDeliveryResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var creatives : Sequence[DeliveryCreative]var model_config
Inherited members
class GetMediaBuyDeliveryResponse (**data: Any)-
Expand source code
class GetMediaBuyDeliveryResponse(_LegacyGetMediaBuyDeliveryResponse, CanonicalBoundaryModel): """Canonical media-buy delivery response."""Canonical media-buy delivery response.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetMediaBuyDeliveryResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class GetMediaBuysResponse (**data: Any)-
Expand source code
class GetMediaBuysResponse(_LegacyGetMediaBuysResponse, CanonicalBoundaryModel): """Canonical media-buy listing; rows are canonical media buys.""" media_buys: Sequence[MediaBuy]Canonical media-buy listing; rows are canonical media buys.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetMediaBuysResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var media_buys : Sequence[MediaBuy]var model_config
Inherited members
class GetProductsRequest (**data: Any)-
Expand source code
class GetProductsRequest(_LegacyGetProductsRequest, CanonicalBoundaryModel): """Canonical discovery request with legacy response-field selection rejected.""" filters: ProductFilters | None = None @field_validator("fields") @classmethod def _reject_legacy_fields(cls, value: Any) -> Any: if value and any( is_legacy_creative_identity_key(getattr(item, "value", item)) for item in value ): raise ValueError( "format_id and format_ids are unavailable on the canonical get_products API" ) return valueCanonical discovery request with legacy response-field selection rejected.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetProductsRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var filters : ProductFilters | Nonevar model_config
Inherited members
class GetProductsResponse (**data: Any)-
Expand source code
class GetProductsResponse(_LegacyGetProductsResponse, CanonicalBoundaryModel): """Canonical discovery response; products are canonical products.""" products: list[Product] | None = None # type: ignore[assignment]Canonical discovery response; products are canonical products.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- GetProductsResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar products : list[Product] | None
Inherited members
class ListCreativesRequest (**data: Any)-
Expand source code
class ListCreativesRequest(_LegacyListCreativesRequest, CanonicalBoundaryModel): """Canonical creative read request with legacy field selection rejected.""" filters: CreativeFilters | None = None @field_validator("fields") @classmethod def _reject_legacy_fields(cls, value: Any) -> Any: if value and any( is_legacy_creative_identity_key(getattr(item, "value", item)) for item in value ): raise ValueError( "format_id and format_ids are unavailable on the canonical list_creatives API" ) return valueCanonical creative read request with legacy field selection rejected.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- ListCreativesRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var filters : CreativeFilters | Nonevar model_config
Inherited members
class ListCreativesResponse (**data: Any)-
Expand source code
class ListCreativesResponse(_LegacyListCreativesResponse, CanonicalBoundaryModel): """Canonical creative listing; rows are canonical listed creatives.""" creatives: list[Creative]Canonical creative listing; rows are canonical listed creatives.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- ListCreativesResponse
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var creatives : list[Creative]var model_config
Inherited members
class MediaBuy (**data: Any)-
Expand source code
class MediaBuy(_LegacyMediaBuy, CanonicalBoundaryModel): """Canonical media buy; packages are canonical package rows.""" packages: Sequence[MediaBuyPackage]Canonical media buy; packages are canonical package rows.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- MediaBuy
- IndicatorBearingResourceState
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar packages : Sequence[MediaBuyPackage]
Inherited members
class MediaBuyPackage (**data: Any)-
Expand source code
class MediaBuyPackage(_LegacyMediaBuyPackage, CanonicalBoundaryModel): """Canonical media-buy package row; legacy format identity is absent.""" if TYPE_CHECKING: # the removed fields, hidden from the constructor too format_ids: _RemovedFormatIds = Field(default=None, init=False) format_ids_pending: _RemovedFormatIds = Field(default=None, init=False) format_ids_to_provide: _RemovedFormatIds = Field(default=None, init=False)Canonical media-buy package row; legacy format identity is absent.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- Package
- IndicatorBearingResourceState
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_ids : list[FormatReferenceStructuredObject] | Nonevar format_ids_pending : list[FormatReferenceStructuredObject] | Nonevar format_ids_to_provide : list[FormatReferenceStructuredObject] | Nonevar model_config
Instance variables
var bid_price : float | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
Inherited members
class Package (**data: Any)-
Expand source code
class Package(_LegacyPackage, CanonicalBoundaryModel): """Canonical package; legacy format identity is absent.""" if TYPE_CHECKING: # the removed fields, hidden from the constructor too format_ids: _RemovedFormatIds = Field(default=None, init=False) format_ids_pending: _RemovedFormatIds = Field(default=None, init=False) format_ids_to_provide: _RemovedFormatIds = Field(default=None, init=False)Canonical package; legacy format identity is absent.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- Package
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_ids : list[FormatReferenceStructuredObject] | Nonevar format_ids_pending : list[FormatReferenceStructuredObject] | Nonevar format_ids_to_provide : list[FormatReferenceStructuredObject] | Nonevar model_config
Instance variables
var bid_price : float | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
Inherited members
class PackageRequest (**data: Any)-
Expand source code
class PackageRequest(_LegacyPackageRequest, CanonicalBoundaryModel): """Canonical package request preserving beta.3 selector constraints.""" if TYPE_CHECKING: # the removed field, hidden from the constructor too format_ids: _RemovedFormatIds = Field(default=None, init=False) creatives: list[CreativeAsset] | None = Field(default=None, min_length=1) @model_validator(mode="after") def _validate_format_params(self) -> PackageRequest: if self.params is not None and self.format_kind is None: raise ValueError("params requires format_kind") if self.params is not None and self.format_kind == "image": if ("width" in self.params) != ("height" in self.params): raise ValueError("image params width and height must co-occur") return selfCanonical package request preserving beta.3 selector constraints.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- PackageRequest
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var creatives : list[CreativeAsset] | Nonevar model_configvar targeting_overlay : TargetingOverlayInput | TargetingOverlay | None
Inherited members
class PackageUpdate (**data: Any)-
Expand source code
class PackageUpdate(_LegacyPackageUpdate, CanonicalBoundaryModel): """Canonical package update; creatives are canonical assets.""" creatives: list[CreativeAsset] | None = Field(default=None, min_length=1) # type: ignore[assignment]Canonical package update; creatives are canonical assets.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- PackageUpdate
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var creatives : list[CreativeAsset] | Nonevar model_configvar targeting_overlay : TargetingOverlayInput | TargetingOverlay | None
Inherited members
class Placement (**data: Any)-
Expand source code
class Placement(_LegacyPlacement, CanonicalBoundaryModel): """Canonical placement; ``format_options`` are canonical declarations.""" if TYPE_CHECKING: # the removed field, hidden from the constructor too format_ids: _RemovedFormatIdSequence = Field(default=None, init=False) format_options: list[Format] | None = Field(default=None, min_length=1) # type: ignore[assignment]Canonical placement;
format_optionsare canonical declarations.Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- Placement
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_ids : collections.abc.Sequence[FormatReferenceStructuredObject] | Nonevar format_options : list[Format] | Nonevar model_config
Inherited members
class Product (**data: Any)-
Expand source code
class Product(_LegacyProduct, CanonicalBoundaryModel): """Canonical product; formats, placements and pricing are canonical.""" if TYPE_CHECKING: # the removed field, hidden from the constructor too format_ids: _RemovedFormatIds = Field(default=None, init=False) format_options: list[Format] = Field( # type: ignore[assignment] min_length=1, description="Canonical creative formats accepted by this product." ) placements: list[Placement] | None = Field(default=None, min_length=1) # type: ignore[assignment] pricing_options: list[CanonicalPricingOption] = Field(min_length=1)Canonical product; formats, placements and pricing are canonical.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- Product
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_ids : list[FormatReferenceStructuredObject] | Nonevar format_options : list[Format]var model_configvar placements : list[Placement] | Nonevar pricing_options : list[CpmPricingOption | VcpmPricingOption | CpcPricingOption | CpcvPricingOption | CpvPricingOption | CppPricingOption | CpaPricingOption | RevenueSharePricingOption | FlatRatePricingOption | TimeBasedPricingOption]
Instance variables
var data_provider_signals : list[DataProviderSignalSelector1 | DataProviderSignalSelector2 | DataProviderSignalSelector3] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var outcome_measurement : OutcomeMeasurement | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
Inherited members
class ProductFilters (**data: Any)-
Expand source code
class ProductFilters(_LegacyProductFilters, CanonicalBoundaryModel): """Canonical product filters; legacy identity selection is unavailable.""" if TYPE_CHECKING: # the removed field, hidden from the constructor too format_ids: _RemovedFormatIds = Field(default=None, init=False)Canonical product filters; legacy identity selection is unavailable.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- ProductFilters
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var format_ids : list[FormatReferenceStructuredObject] | Nonevar model_config
Instance variables
var countries : list[Country] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var geo_proximity : list[GeoProximityItem] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var keywords : list[Keyword] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var metros : list[Metro] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var postal_areas : list[PostalArea] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var regions : list[Region] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var required_axe_integrations : list[pydantic.networks.AnyUrl] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var required_geo_targeting : list[RequiredGeoTargetingItem] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
var signal_targeting : list[SignalTargetingItem5 | SignalTargetingItem6 | SignalTargetingItem7] | None-
Expand source code
def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: if obj is None: if self.wrapped_property is not None: return self.wrapped_property.__get__(None, obj_type) raise AttributeError(self.field_name) warnings.warn(self.msg, DeprecationWarning, stacklevel=2) if self.wrapped_property is not None: return self.wrapped_property.__get__(obj, obj_type) return obj.__dict__[self.field_name]Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
- Attributes
- -----=
msg- The deprecation message to be emitted.
wrapped_property- The property instance if the deprecated field is a computed field, or
None. field_name- The name of the field being deprecated.
Inherited members
class SyncCreativesRequest (**data: Any)-
Expand source code
class SyncCreativesRequest(_LegacySyncCreativesRequest, CanonicalBoundaryModel): """Canonical creative sync request; creatives are canonical assets.""" creatives: list[CreativeAsset] = Field(min_length=1) # type: ignore[assignment]Canonical creative sync request; creatives are canonical assets.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- SyncCreativesRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var creatives : list[CreativeAsset]var model_config
Inherited members
class UpdateMediaBuyRequest (**data: Any)-
Expand source code
class UpdateMediaBuyRequest(_LegacyUpdateMediaBuyRequest, CanonicalBoundaryModel): """Canonical update request; both package lists are canonical.""" packages: list[PackageUpdate] | None = None new_packages: list[PackageRequest] | None = Field( # type: ignore[assignment] default=None, min_length=1 )Canonical update request; both package lists are canonical.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyRequest
- AdcpRequest
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_configvar new_packages : list[PackageRequest] | Nonevar packages : list[PackageUpdate] | None
Inherited members
class UpdateMediaBuyResponse1 (**data: Any)-
Expand source code
class UpdateMediaBuyResponse1(_LegacyUpdateMediaBuyResponse1, CanonicalBoundaryModel): """Canonical update response preserving the 3.x legacy-status normalizer.""" affected_packages: Sequence[Package] | None = None @model_validator(mode="before") @classmethod def _normalize_legacy_status(cls, data: Any) -> Any: if not isinstance(data, dict): return data raw_status = unwrap_enum_value(data.get("status")) media_buy_status = unwrap_enum_value(data.get("media_buy_status")) if raw_status is None or raw_status == "completed": return {**data, "status": "completed"} if media_buy_status is None and raw_status in MEDIA_BUY_LEGACY_STATUS_VALUES: return {**data, "media_buy_status": raw_status, "status": "completed"} if media_buy_status is not None and raw_status == media_buy_status: return {**data, "status": "completed"} return dataCanonical update response preserving the 3.x legacy-status normalizer.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyResponse1
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var affected_packages : collections.abc.Sequence[Package] | Nonevar model_config
Inherited members
class UpdateMediaBuyResponse2 (**data: Any)-
Expand source code
class UpdateMediaBuyResponse2(_LegacyUpdateMediaBuyResponse2, CanonicalBoundaryModel): """Canonical update-media-buy error arm."""Canonical update-media-buy error arm.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyResponse2
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members
class UpdateMediaBuyResponse3 (**data: Any)-
Expand source code
class UpdateMediaBuyResponse3(_LegacyUpdateMediaBuyResponse3, CanonicalBoundaryModel): """Canonical update-media-buy submitted arm."""Canonical update-media-buy submitted arm.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- UpdateMediaBuyResponse3
- AdcpResponse
- adcp.types.base._AdcpMessage
- AdcpVersionEnvelope
- ProtocolEnvelope
- CanonicalBoundaryModel
- AdCPBaseModel
- pydantic.main.BaseModel
Class variables
var model_config
Inherited members