Skip to content

Commit

Permalink
Add tests for type hint resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
oxan committed Oct 19, 2023
1 parent c243be7 commit 6332ee2
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
6 changes: 4 additions & 2 deletions rest_framework_dataclasses/typing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ def get_resolved_type_hints(tp: type) -> typing.Dict[str, type]:
Resolving the type hints means converting any stringified type hint into an actual type object. These can come from
either forward references (PEP 484), or postponed evaluation (PEP 563).
"""
# typing.get_type_hints() does the heavy lifting for us, except when using PEP 585 generic types that contain a
# stringified type hint (see https://bugs.python.org/issue41370)
# typing.get_type_hints() does the heavy lifting for us, except:
# - when using PEP 585 generic types that contain a stringified type hint, on Python 3.9 and 3.10. See
# https://bugs.python.org/issue41370
# - when using PEP 695 type aliases
def _resolve_type(context_type: type, resolve_type: typing.Union[str, type]) -> type:
if isinstance(resolve_type, str):
globalsns = sys.modules[context_type.__module__].__dict__
Expand Down
36 changes: 36 additions & 0 deletions tests/test_typing_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import types as types_module
import typing
import unittest
import sys
Expand All @@ -11,6 +12,41 @@ def assertAnyTypeEquivalent(self, tp: type):
# 3.7 and 3.8). It's essentially the same, and we strip the typevar before usage anyway.
self.assertTrue(tp is typing.Any or (isinstance(tp, typing.TypeVar) and len(tp.__constraints__) == 0))

def test_resolve(self):
class Hinted:
a: str
b: 'str'

hints = typing_utils.get_resolved_type_hints(Hinted)
self.assertEqual(hints['a'], str)
self.assertEqual(hints['b'], str)

@unittest.skipIf(sys.version_info < (3, 9, 0), 'Python 3.9 required')
def test_resolve_pep585(self):
class Hinted:
a: list[str]
b: list['str']

hints = typing_utils.get_resolved_type_hints(Hinted)
self.assertEqual(hints['a'], types_module.GenericAlias(list, (str, )))
self.assertEqual(hints['b'], types_module.GenericAlias(list, (str, )))

@unittest.skipif(sys.version_info < (3, 12, 0), 'Python 3.12 required')
def test_resolve_pep695(self):
type Str = str
type StrList = list[str]
type GenericList = list[T]

class Hinted:
a: Str
b: StrList
c: GenericList

hints = typing_utils.get_resolved_type_hints(Hinted)
self.assertEqual(hints['a'], str)
self.assertEqual(hints['a'], list[str])
self.assertEqual(hints['a'], list[T])

def test_iterable(self):
self.assertTrue(typing_utils.is_iterable_type(typing.Iterable[str]))
self.assertTrue(typing_utils.is_iterable_type(typing.Collection[str]))
Expand Down

0 comments on commit 6332ee2

Please sign in to comment.