Skip to content

Commit 46ad5a3

Browse files
feat(types): support Python 3.14 in versioned model construction (#1379)
`versioned.py` built its annotation unions by calling `Union.__getitem__(tuple(...))`. Python 3.14 makes that a descriptor requiring a `typing.Union` instance, so handing it a tuple raises: TypeError: descriptor '__getitem__' requires a 'typing.Union' object but received a 'tuple' `make_versioned_base` and the two annotation-union helpers all called it that way, so every versioned model fails to build on 3.14. The SDK's classifiers stop at 3.13 and CI covers 3.10-3.13, so this adds a version rather than repairing a supported one. Build the unions with the `|` operator instead, which is the spelling the project's own lint rules ask for and is equivalent on every supported version: `functools.reduce(operator.or_, ...)` where the arms come from a variable-length sequence, and `annotation | None` for the one site that only ever added `NoneType`. `|` applies the same dedup, nested-union flattening and `Optional` collapsing as `Union[...]`, so the constructed annotations are unchanged — verified equal across class, `Any`, `types.GenericAlias`, `Literal`, `NoneType` and pre-unioned inputs. `typing.Union` is no longer referenced and leaves the imports. Clears 10 of the 12 tests that fail on 3.14 and pass on 3.12: all eight in tests/test_version_scoped_models.py and both tests/test_account_reference_request_fields.py::test_versioned_*.
1 parent a083a19 commit 46ad5a3

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

‎src/adcp/types/versioned.py‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
import copy
1717
import importlib
1818
import re
19-
from functools import cache
19+
from functools import cache, reduce
20+
from operator import or_
2021
from types import GenericAlias
21-
from typing import Any, ClassVar, Literal, Union
22+
from typing import Any, ClassVar, Literal
2223

2324
from jsonschema.validators import validator_for
2425
from pydantic import (
@@ -175,7 +176,7 @@ def _fallback_annotation(
175176
if len(annotations) == 1:
176177
return annotations[0]
177178
if annotations:
178-
return Union.__getitem__(tuple(annotations))
179+
return reduce(or_, annotations)
179180
all_of = schema.get("allOf")
180181
if isinstance(all_of, list):
181182
annotations = [
@@ -191,7 +192,7 @@ def _fallback_annotation(
191192
annotations = [
192193
_fallback_annotation({**schema, "type": item}, document, seen) for item in schema_type
193194
]
194-
return Union.__getitem__(tuple(dict.fromkeys(annotations)))
195+
return reduce(or_, dict.fromkeys(annotations))
195196
if schema_type == "array":
196197
item_type = _fallback_annotation(schema.get("items", {}), document, seen)
197198
return GenericAlias(list, item_type)
@@ -483,7 +484,7 @@ class SellerListCreativesRequest(ListCreatives31):
483484
_fallback_annotation(field_schema, schema),
484485
)
485486
if name not in guaranteed_fields:
486-
annotation = Union.__getitem__((annotation, type(None)))
487+
annotation = annotation | None
487488
description = field_schema.get("description") if isinstance(field_schema, dict) else None
488489
if isinstance(field_schema, dict) and "default" in field_schema:
489490
default = Field(

0 commit comments

Comments
 (0)