Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
b746a04
feat(types)!: emit scalar schema roots as plain scalar subclasses
KonstantinMirin Oct 2, 2026
ad22318
chore(types): regenerate models for the scalar root rewrite
KonstantinMirin Oct 2, 2026
7332a63
fix(types): stop the SDK reading .root on its own scalar schemas
KonstantinMirin Oct 2, 2026
2facf32
test(types): cover the scalar root contract
KonstantinMirin Oct 2, 2026
8847ae9
feat(types)!: emit a composing schema root as what it composes
KonstantinMirin Oct 3, 2026
3ef739e
chore(types): regenerate models for the composing-root rewrite
KonstantinMirin Oct 3, 2026
67ea1fe
fix: stop the SDK reading .root on its own composing roots
KonstantinMirin Oct 3, 2026
5c643a9
test(types): cover the composing-root contract
KonstantinMirin Oct 3, 2026
844c81f
chore(types): rebuild SCHEMA_DELTAS.md from the base-to-HEAD comparison
KonstantinMirin Oct 3, 2026
d7b140a
Merge remote-tracking branch 'upstream/main' into fix/scalar-str-codegen
KonstantinMirin Oct 3, 2026
574b66c
fix(codegen)!: enforce root-level anyOf/oneOf required groups
KonstantinMirin Oct 2, 2026
1d345af
fix(codegen)!: resolve structural pointer refs to the type they select
KonstantinMirin Oct 2, 2026
2d0fe47
Merge upstream/main (v8.0.0-20) into fix/rootmodel-objects-discrimina…
KonstantinMirin Oct 3, 2026
c014547
fix(validation)!: make the generated models agree with the bundled sc…
KonstantinMirin Oct 3, 2026
4ecdf56
Merge remote-tracking branch 'upstream/main' into fix/scalar-str-codegen
KonstantinMirin Oct 3, 2026
5b1c6f2
Merge upstream/main (63bfadb4e) into fix/rootmodel-objects-discrimina…
KonstantinMirin Oct 3, 2026
5f9e422
Merge upstream/main (63bfadb4e) into fix/input-model-field-types
KonstantinMirin Oct 3, 2026
13f48ef
Merge upstream/main (63bfadb4e) into fix/pydantic-schema-parity
KonstantinMirin Oct 3, 2026
5a5efc8
Merge upstream/main (63bfadb4e) into fix/scalar-str-codegen
KonstantinMirin Oct 3, 2026
e7c849f
Merge upstream/main (63bfadb4e) into fix/root-required-groups
KonstantinMirin Oct 3, 2026
4ec78ed
Merge remote-tracking branch 'origin/main' into land/1286
bokelley Oct 4, 2026
db0ad23
Merge branch 'land/1286' into land/1353
bokelley Oct 4, 2026
15fb8c0
chore(types): regenerate on top of the scalar-root rewrite (#1286)
bokelley Oct 4, 2026
22007d1
docs(types): rebuild SCHEMA_DELTAS.md as the main-to-head comparison
bokelley Oct 4, 2026
32fc136
Merge branch 'land/1353' into land/1371
bokelley Oct 4, 2026
d57c8ab
fix(codegen): leave class-shaped pointer selections to the generator;…
bokelley Oct 4, 2026
e93f9bc
docs(types): rebuild SCHEMA_DELTAS.md as the main-to-head comparison
bokelley Oct 4, 2026
45a0c52
Merge branch 'land/1371' into land/1375
bokelley Oct 4, 2026
531131d
fix(types): make scalar roots strict like their fields; repair the Pr…
bokelley Oct 4, 2026
a059297
docs(types): rebuild SCHEMA_DELTAS.md as the main-to-head comparison
bokelley Oct 4, 2026
d9ea7b9
test(types): age_restriction stays a shared object pointer, so it car…
bokelley Oct 4, 2026
5131105
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
c1eb684
fix(codegen): extend parenthesized pydantic imports when adding model…
bokelley Oct 4, 2026
74f16f0
fix(types): carry a generated class's own validators into its canonic…
bokelley Oct 4, 2026
25e53a2
docs(types): consolidated 9.0 generated-types migration guide
bokelley Oct 4, 2026
d84c783
fix(types): build the union-root TypeAdapters on first use, not at im…
bokelley Oct 4, 2026
3a2619b
fix(validation): build the uri format checker's adapter on first use
bokelley Oct 4, 2026
d6a17f9
Merge remote-tracking branch 'origin/main' into land/1353
bokelley Oct 4, 2026
6acdd2d
Merge remote-tracking branch 'origin/main' into land/1375
bokelley Oct 4, 2026
12b5067
Merge branch 'land/1353' into land/1375
bokelley Oct 4, 2026
fcef6f6
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
b227fc7
Merge remote-tracking branch 'origin/main' into land/1286
bokelley Oct 4, 2026
5c9c1ee
Merge branch 'land/1286' into land/1353
bokelley Oct 4, 2026
56e68ce
test(types): unwrap Annotated union roots in the hierarchy ratchet
bokelley Oct 4, 2026
7bbf5cb
Merge branch 'land/1353' into land/1371
bokelley Oct 4, 2026
951329f
Merge branch 'land/1371' into land/1375
bokelley Oct 4, 2026
3400a2b
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
9a1a8fb
Merge remote-tracking branch 'origin/main' into land/1353
bokelley Oct 4, 2026
e0c1b08
Merge remote-tracking branch 'origin/main' into land/1353
bokelley Oct 4, 2026
2d25652
docs(types): rebuild SCHEMA_DELTAS.md as the main-to-head comparison
bokelley Oct 4, 2026
e076b0a
Merge branch 'land/1353' into land/1371
bokelley Oct 4, 2026
ca8c1af
fix(codegen): keep a composing root wrapped when another module's fie…
bokelley Oct 4, 2026
d86457d
Merge branch 'land/1353' into land/1371
bokelley Oct 4, 2026
dde689d
chore(types): regenerate on the #1353 review fix
bokelley Oct 4, 2026
683362e
Merge branch 'land/1371' into land/1375
bokelley Oct 4, 2026
419de5f
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
bd086af
docs(types): rebuild SCHEMA_DELTAS.md as the main-to-head comparison
bokelley Oct 4, 2026
f15917e
Merge remote-tracking branch 'origin/main' into land/1371
bokelley Oct 4, 2026
6e91ce8
Merge branch 'land/1371' into land/1375
bokelley Oct 4, 2026
f5ecd38
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
257a9fb
fix(codegen): add model_validator to creative_manifest's import idemp…
bokelley Oct 4, 2026
d490e4a
chore(types): refresh the collision allowlist
bokelley Oct 4, 2026
07166ce
Merge branch 'land/1371' into land/1375
bokelley Oct 4, 2026
1a61872
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
feb5151
Merge remote-tracking branch 'origin/main' into land/1375
bokelley Oct 4, 2026
c4c9c34
docs(types): rebuild SCHEMA_DELTAS.md as the main-to-head comparison
bokelley Oct 4, 2026
b5374d2
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
127b6ca
test(conformance): synthesize patterns on Python 3.10 too
bokelley Oct 4, 2026
069f39d
Merge branch 'land/1375' into land/1368
bokelley Oct 4, 2026
73eb9b3
Merge remote-tracking branch 'origin/main' into land/1368
bokelley Oct 4, 2026
32152d7
docs(types): rebuild SCHEMA_DELTAS.md as the main-to-head comparison
bokelley Oct 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions SCHEMA_DELTAS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# Generated-types delta

## Field changes

- `core/wholesale_feed_event.py`
- **classes added**: Range
_No field-shape changes detected._
6 changes: 6 additions & 0 deletions docs/extending-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -892,3 +892,9 @@ Version modules import lazily and construct only requested bases. Run
`make validate-generated` checks both the runtime annotations and stubs for
staleness. The generator does not read current generated-model annotations,
so the scalar rewrite in #1286 cannot change these pinned nested types.

## Migrating to 9.0

The 9.0 generator changes — scalar roots, composing roots, pointer refs,
strict scalars and root required groups — are collected with before/after
examples in [the 9.0 types migration guide](types-9-migration.md).
137 changes: 137 additions & 0 deletions docs/types-9-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Generated types in 9.0: migration guide

Release 9.0 lands a batch of code-generator changes that make `adcp.types`
agree with the AdCP JSON Schemas it is generated from. Each one is a breaking
change on its own; this page collects them so a migration can be done in one
pass. The pull requests are linked for the full rationale and measurements.

| Change | PR | What breaks |
| --- | --- | --- |
| Scalar schema roots are plain `str`/`int`/`float` subclasses | #1286 | `issubclass(X, RootModel)`, `X.model_validate`/`model_dump`/`model_json_schema` on 224 scalar types |
| A composing schema root is emitted as what it composes | #1353 | `.root` on 114 union/single-model roots; `TypeName.model_validate` on a union root |
| Structural pointer refs resolve to the type they select | #1371 | 47 per-position `RootModel` wrapper names under `adcp.types._generated` |
| Generated models validate `boolean`/`integer`/`number` strictly | #1375 | Payloads that relied on `"yes"`, `"1"`, `1` coercion |
| Root-level `anyOf`/`oneOf` required groups are enforced | #1368 | Documents that omit every required group of 42 request/response models, on generated and canonical names alike |

Nothing is removed from `adcp` or `adcp.types`: every name importable before
is importable after, and the ten additions (`Issue`, `AdcpVersionEnvelope`,
seven `*Details` error models and `FormatReferenceStructuredObject` under
`adcp.types.legacy`) come with #1367. Identity changes on the public surface
are of exactly the kinds the table names and are pinned by
`tests/fixtures/public_api_snapshot.json`.

## 1. Scalar roots are the scalar (#1286)

A schema whose root is a scalar — `core/property-tag.json` is
`{"type": "string", "pattern": "^[a-z0-9_]+$"}` — generates a `str`, `int` or
`float` subclass instead of `RootModel[str]`.

```python
# before
tag = PropertyTag(root="sports")
code = country.root
PropertyTag.model_validate("sports")

# after
tag = PropertyTag("sports") # tag == "sports", hash(tag) == hash("sports")
code = country # it already is a str
TypeAdapter(PropertyTag).validate_python("sports")
```

`.root` and `X(root=...)` keep working behind a `DeprecationWarning`.
`issubclass(X, RootModel)` is `False` and the `model_*` classmethods are gone,
because the type is no longer a Pydantic model: use `TypeAdapter(X)`.

Integer and number roots validate the way their fields do under #1375:
strictly, with a float carrying no fractional part narrowed to `int`.

## 2. Composing roots are what they compose (#1353)

A root that is a union of models becomes an `Annotated[A | B, Field(...)]`
alias carrying the schema's discriminator; a root that is a single model
becomes a subclass of that model.

```python
# before
event = WholesaleFeedEvent.model_validate(payload)
inner = request.start_time.root

# after
event = TypeAdapter(WholesaleFeedEvent).validate_python(payload) # honours the discriminator
inner = request.start_time
```

A single-model root such as `CheckGovernanceRequest` keeps
`model_validate(...)` and can now be subclassed with `extra="forbid"`.

## 3. Pointer refs resolve to the selected type (#1371)

A `$ref` into another schema's `properties`/`items` no longer mints a
single-arm `RootModel` wrapper per referencing site. Request-side overlays
read like response-side ones:

```python
# before: TargetingOverlayInput.geo_countries was GeoCountries (a wrapper); len() raised
# after
for country in overlay.geo_countries:
code: str = country
```

The removed names were reachable only under `adcp.types._generated`, which is
documented as internal; the per-name replacement table is in #1371. A pointer
to an object or enum property still resolves to the one shared class
(`targeting.AgeRestriction`, `ProductResponseField`).

## 4. Strict scalars (#1375)

`type: boolean`, `integer` and `number` fields refuse what the bundled JSON
Schema refuses:

```python
ListAccountsRequest.model_validate({"sandbox": "yes"}) # before: sandbox=True; after: ValidationError
Budget.model_validate({"amount": "100"}) # ValidationError; send 100 or 100.0
Count.model_validate({"value": 1.0}) # still accepted, narrowed to 1
```

The bundled schema validator additionally checks `format: uri` and
`format: hostname`, so a malformed URL in a response fails response validation.

## 5. Root required groups (#1368)

42 models enforce the root-level `anyOf`/`oneOf` their schema declares.
`CreateMediaBuyRequest` needs packages, a budget, or a proposal; a document
with none raises `ValidationError` naming the groups. The rule reaches the
canonical names in `adcp.types` too: `_canonical_clone` carries every validator
a generated class declares on itself, so `adcp.CreateMediaBuyRequest` and the
generated class agree.

```python
CreateMediaBuyRequest.model_validate({**unconditional_fields})
# ValidationError: CreateMediaBuyRequest requires at least one of these field groups:
# packages | total_budget+proposal_id | ...
```

Presence is what counts: an explicit `null` satisfies a group, a default the
caller never sent does not.

## Also in this batch (not breaking)

* `adcp.types.domains.<domain>[.<schema>]` and `adcp.types.error_details`
(#1367) give every generated class a public path, and the public API
snapshot records what each name resolves to.
* `scripts/generate_types.py --check` runs in CI, grades every post-generation
fix against `scripts/post_generation_manifest.json`, and the generator's
input order is total, so a regeneration is byte-identical on every
filesystem (#1374).
* `canonical_creative.pyi` is derived from the runtime models (#1366): every
field the canonical models carry is declared, and the synthesized
constructors demand exactly the fields the runtime demands. A program that
type-checked against the old stub while constructing `CreateMediaBuyRequest`
without `brand`, `start_time`, `end_time` or `idempotency_key` now fails
mypy, as it always failed at runtime. Enum-typed parameters keep accepting
the wire string.
* A format reference's `agent_url` is carried as the wire string, validated
as a URL (#1384). `ref.agent_url` is a `str`, not an `AnyUrl`, so
`migrated_…` option IDs derived from a model match those derived from the
wire mapping.
* `adcp.__all__` and `adcp.types.__all__` name each export once (#1380).
Loading
Loading