Skip to content

Commit

Permalink
Fix Cython doesn't support generic types (PEP560)
Browse files Browse the repository at this point in the history
Watch cython issue #2753
Previous implementation can be used after cython 3.0 release
  • Loading branch information
aleksul committed Jan 19, 2022
1 parent e79be40 commit 35ba1f8
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
11 changes: 7 additions & 4 deletions pydantic/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ def convert_generics(tp: Type[Any]) -> Type[Any]:
return tp

else:
from typing import _UnionGenericAlias # type: ignore

from typing_extensions import _AnnotatedAlias

def convert_generics(tp: Type[Any]) -> Type[Any]:
"""Recursively searches for `str` type hints and replaces them with ForwardRef.
Expand All @@ -181,7 +184,7 @@ def convert_generics(tp: Type[Any]) -> Type[Any]:

# typing.Annotated needs special treatment
if origin is Annotated:
return Annotated[(convert_generics(args[0]), *args[1:])]
return _AnnotatedAlias(convert_generics(args[0]), args[1:])

# recursively replace `str` isntances inside of `GenericAlias` with `ForwardRef(arg)`
converted = tuple(
Expand All @@ -192,10 +195,10 @@ def convert_generics(tp: Type[Any]) -> Type[Any]:
if converted == args:
return tp
elif isinstance(tp, TypingGenericAlias):
return origin[converted]
return TypingGenericAlias(origin, converted)
elif isinstance(tp, TypesUnionType):
# recreate types.UnionType (PEP604) with typing.Union
return Union[converted] # type: ignore
# recreate types.UnionType (PEP604, Python >= 3.10)
return _UnionGenericAlias(origin, converted)
else:
try:
setattr(tp, '__args__', converted)
Expand Down
5 changes: 5 additions & 0 deletions tests/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from typing import Callable as TypingCallable, Dict, ForwardRef, List, NamedTuple, Union

import pytest
from typing_extensions import Annotated

from pydantic import Field
from pydantic.typing import Literal, convert_generics, is_namedtuple, is_none_type, is_typeddict

try:
Expand Down Expand Up @@ -86,6 +88,9 @@ def test_convert_generics():
assert convert_generics(dict['Hero', list['Team']]) == dict[ForwardRef('Hero'), list[ForwardRef('Team')]]
assert convert_generics(dict['Hero', List['Team']]) == dict[ForwardRef('Hero'), List[ForwardRef('Team')]]
assert convert_generics(Dict['Hero', list['Team']]) == Dict[ForwardRef('Hero'), list[ForwardRef('Team')]]
assert str(convert_generics(Annotated[list['Hero'], Field(min_length=2)])) == str(
Annotated[list[ForwardRef('Hero')], Field(min_length=2)]
)


@pytest.mark.skipif(sys.version_info < (3, 10), reason='PEP604 unions only supported for python 3.10 and above')
Expand Down

0 comments on commit 35ba1f8

Please sign in to comment.