Skip to content

Commit d50a805

Browse files
committed
Fixes for Python 3.14.
1 parent 6c1af33 commit d50a805

File tree

5 files changed

+37
-11
lines changed

5 files changed

+37
-11
lines changed

.github/workflows/python-test.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ jobs:
5252
runs-on: ubuntu-latest
5353
strategy:
5454
matrix:
55-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
55+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
5656
pydantic-version: ["1.10.*", "2.*"]
57+
exclude:
58+
- python-version: "3.14"
59+
pydantic-version: "1.10.*"
5760

5861
services:
5962
postgres:

django_pydantic_field/compat/django.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,12 @@ def serialize(self):
297297

298298
AnnotatedAlias = te._AnnotatedAlias
299299

300-
if sys.version_info >= (3, 9):
300+
if sys.version_info >= (3, 14):
301301
GenericAlias = types.GenericAlias
302-
GenericTypes: ty.Tuple[ty.Any, ...] = (
302+
GenericTypes: ty.Tuple[ty.Any, ...] = (GenericAlias, type(ty.List[int]), type(ty.List), ty.Union)
303+
elif sys.version_info >= (3, 9):
304+
GenericAlias = types.GenericAlias
305+
GenericTypes = (
303306
GenericAlias,
304307
type(ty.List[int]),
305308
type(ty.List),
@@ -325,6 +328,7 @@ def serialize(self):
325328

326329
MigrationWriter.register_serializer(ty.ForwardRef, TypingSerializer)
327330
MigrationWriter.register_serializer(type(ty.Union), TypingSerializer) # type: ignore
331+
MigrationWriter.register_serializer(ty._SpecialForm, TypingSerializer) # type: ignore
328332

329333

330334
if sys.version_info >= (3, 10):

django_pydantic_field/v2/utils.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,22 @@
99
if ty.TYPE_CHECKING:
1010
from collections.abc import Mapping
1111

12+
get_annotations: ty.Callable[[ty.Any], dict[str, ty.Any]]
1213

13-
def get_annotated_type(obj, field, default=None) -> ty.Any:
14-
try:
14+
try:
15+
from annotationlib import get_annotations # Python >= 3.14
16+
except ImportError:
17+
18+
def get_annotations(obj: ty.Any) -> dict[str, ty.Any]:
1519
if isinstance(obj, type):
16-
annotations = obj.__dict__["__annotations__"]
20+
return obj.__dict__["__annotations__"]
1721
else:
18-
annotations = obj.__annotations__
22+
return obj.__annotations__
23+
24+
25+
def get_annotated_type(obj, field, default=None) -> ty.Any:
26+
try:
27+
annotations = get_annotations(obj)
1928

2029
return annotations[field]
2130
except (AttributeError, KeyError):

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ classifiers = [
4141
"Programming Language :: Python :: 3.11",
4242
"Programming Language :: Python :: 3.12",
4343
"Programming Language :: Python :: 3.13",
44+
"Programming Language :: Python :: 3.14",
4445
]
4546

4647
requires-python = ">=3.8"
@@ -61,8 +62,8 @@ dev = [
6162
"pre-commit",
6263
"pytest~=7.4",
6364
"djangorestframework>=3.11,<4",
64-
"django-stubs[compatible-mypy]~=4.2",
65-
"djangorestframework-stubs[compatible-mypy]~=3.14",
65+
"django-stubs[compatible-mypy]~=5.2.3",
66+
"djangorestframework-stubs[compatible-mypy]~=3.16.3",
6667
"pytest-django>=4.5,<6",
6768
]
6869
test = [

tests/test_migration_serializers.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66
import pytest
77

88
import django_pydantic_field
9+
910
try:
1011
from django_pydantic_field.compat.django import GenericContainer
1112
except ImportError:
1213
from django_pydantic_field._migration_serializers import GenericContainer # noqa
1314

15+
try:
16+
import annotationlib
17+
except ImportError:
18+
annotationlib = None
19+
1420
if sys.version_info < (3, 9):
1521
test_types = [
1622
str,
@@ -26,6 +32,7 @@
2632
str,
2733
list,
2834
list[str],
35+
t.Literal["foo"],
2936
t.Union[t.Literal["foo"], list[str]],
3037
list[t.Union[int, bool]],
3138
tuple[list[t.Literal[1]], t.Union[str, t.Literal["foo"]]],
@@ -42,6 +49,8 @@ def test_wrap_unwrap_idempotent(raw_type):
4249
@pytest.mark.parametrize("raw_type", test_types)
4350
def test_serialize_eval_idempotent(raw_type):
4451
raw_type = GenericContainer.wrap(raw_type)
45-
expression, _ = MigrationWriter.serialize(GenericContainer.wrap(raw_type))
46-
imports = dict(typing=t, typing_extensions=te, django_pydantic_field=django_pydantic_field)
52+
expression, _ = MigrationWriter.serialize(raw_type)
53+
imports = dict(
54+
typing=t, typing_extensions=te, django_pydantic_field=django_pydantic_field, annotationlib=annotationlib
55+
)
4756
assert eval(expression, imports) == raw_type

0 commit comments

Comments
 (0)