Module adcp.canonical_formats.dialect
Negotiated creative dialect selection for AdCP 3.x.
Functions
def canonical_creatives_capability(capabilities: Any) ‑> bool | None-
Expand source code
def canonical_creatives_capability(capabilities: Any) -> bool | None: """Read ``media_buy.features.canonical_creatives`` without guessing.""" root = _as_mapping(capabilities) if root is None: return None media_buy = _as_mapping(root.get("media_buy")) features = _as_mapping(media_buy.get("features")) if media_buy else None value = features.get("canonical_creatives") if features else None return value if isinstance(value, bool) else NoneRead
media_buy.features.canonical_creativeswithout guessing. def resolve_creative_dialect(adcp_version: str,
*,
capabilities: Any = None,
request: Any = None,
legacy_projection_available: bool = False) ‑> CreativeDialect-
Expand source code
def resolve_creative_dialect( adcp_version: str, *, capabilities: Any = None, request: Any = None, legacy_projection_available: bool = False, ) -> CreativeDialect: """Apply the normative 3.0/3.1/3.2 canonical-creatives matrix. AdCP 3.1 is deliberately evidence-driven. Contradictory or absent evidence fails closed, except when the caller has already established an unambiguous legacy projection route. """ normalized = normalize_to_release_precision(adcp_version) release = normalized.split("-", 1)[0] major, minor = (int(part) for part in release.split(".", 1)) if major != 3: raise CreativeDialectError( f"canonical creative negotiation only supports AdCP 3.x, got {adcp_version!r}" ) capability = canonical_creatives_capability(capabilities) if minor == 0: return CreativeDialect.LEGACY if minor >= 2: if capability is False: raise CreativeDialectError( "AdCP 3.2+ requires canonical creatives, but the seller advertised " "canonical_creatives=false" ) return CreativeDialect.CANONICAL if capability is True: return CreativeDialect.CANONICAL if capability is False: return CreativeDialect.LEGACY canonical, legacy = _schema_evidence(request) # During the 3.1 transition a sender may dual-emit legacy format IDs next # to canonical option references. Canonical evidence is authoritative; # the legacy fields are compatibility data rather than a contradiction. if canonical: return CreativeDialect.CANONICAL if legacy and not canonical: return CreativeDialect.LEGACY if legacy_projection_available: return CreativeDialect.LEGACY raise CreativeDialectError( "AdCP 3.1 does not establish a creative dialect: advertise " "media_buy.features.canonical_creatives or provide unambiguous " "request-local schema evidence" )Apply the normative 3.0/3.1/3.2 canonical-creatives matrix.
AdCP 3.1 is deliberately evidence-driven. Contradictory or absent evidence fails closed, except when the caller has already established an unambiguous legacy projection route.
Classes
class CreativeDialect (*args, **kwds)-
Expand source code
class CreativeDialect(str, Enum): """Creative identity shape expected at a protocol boundary.""" LEGACY = "legacy" CANONICAL = "canonical"Creative identity shape expected at a protocol boundary.
Ancestors
- builtins.str
- enum.Enum
Class variables
var CANONICALvar LEGACY
class CreativeDialectError (*args, **kwargs)-
Expand source code
class CreativeDialectError(ValueError): """Raised when negotiation cannot select a safe creative dialect."""Raised when negotiation cannot select a safe creative dialect.
Ancestors
- builtins.ValueError
- builtins.Exception
- builtins.BaseException