8000 Fix get_type_hints() on x-module inherited TypedDict in 3.9 and 3.10 … · python/typing_extensions@b56468c · GitHub
[go: up one dir, main page]

Skip to content

Commit b56468c

Browse files
authored
Fix get_type_hints() on x-module inherited TypedDict in 3.9 and 3.10 (#94)
1 parent 8042f3b commit b56468c

File tree

3 files changed

+33
-2
lines changed

3 files changed

+33
-2
lines changed

src/_typed_dict_test_helper.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,15 @@
44
from typing_extensions import TypedDict
55

66

7+
# this class must not be imported into test_typing_extensions.py at top level, otherwise
8+
# the test_get_type_hints_cross_module_subclass test will pass for the wrong reason
9+
class _DoNotImport:
10+
pass
11+
12+
13+
class Foo(TypedDict):
14+
a: _DoNotImport
15+
16+
717
class FooGeneric(TypedDict, Generic[T]):
818
a: Optional[T]

src/test_typing_extensions.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from typing_extensions import clear_overloads, get_overloads, overload
3131
from typing_extensions import NamedTuple
3232
from typing_extensions import override
33-
from _typed_dict_test_helper import FooGeneric
33+
from _typed_dict_test_helper import Foo, FooGeneric
3434

3535
# Flags used to mark tests that only apply after a specific
3636
# version of the typing module.
@@ -41,6 +41,10 @@
4141
# 3.11 makes runtime type checks (_type_check) more lenient.
4242
TYPING_3_11_0 = sys.version_info[:3] >= (3, 11, 0)
4343

44+
# https://github.com/python/cpython/pull/27017 was backported into some 3.9 and 3.10
45+
# versions, but not all
46+
HAS_FORWARD_MODULE = "module" in inspect.signature(typing._type_check).parameters
47+
4448

4549
class BaseTestCase(TestCase):
4650
def assertIsSubclass(self, cls, class_or_tuple, msg=None):
@@ -1774,6 +1778,10 @@ class Point2DGeneric(Generic[T], TypedDict):
17741778
b: T
17751779

17761780

1781+
class Bar(Foo):
1782+
b: int
1783+
1784+
17771785
class BarGeneric(FooGeneric[T], total=False):
17781786
b: int
17791787

@@ -1978,6 +1986,14 @@ class PointDict3D(PointDict2D, total=False):
19781986
assert is_typeddict(PointDict2D) is True
19791987
assert is_typeddict(PointDict3D) is True
19801988

1989+
@skipUnless(HAS_FORWARD_MODULE, "ForwardRef.__forward_module__ was added in 3.9")
1990+
def test_get_type_hints_cross_module_subclass(self):
1991+
self.assertNotIn("_DoNotImport", globals())
1992+
self.assertEqual(
1993+
{k: v.__name__ for k, v in get_type_hints(Bar).items()},
1994+
{'a': "_DoNotImport", 'b': "int"}
1995+
)
1996+
19811997
def test_get_type_hints_generic(self):
19821998
self.assertEqual(
19831999
get_type_hints(BarGeneric),

src/typing_extensions.py

Lines changed: 6 additions & 1 deletion
< 4E39 /tr>
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import collections
33
import collections.abc
44
import functools
5+
import inspect
56
import operator
67
import sys
78
import types as _types
@@ -728,6 +729,8 @@ def _typeddict_new(*args, total=True, **kwargs):
728729
_typeddict_new.__text_signature__ = ('($cls, _typename, _fields=None,'
729730
' /, *, total=True, **kwargs)')
730731

732+
_TAKES_MODULE = "module" in inspect.signature(typing._type_check).parameters
733+
731734
class _TypedDictMeta(type):
732735
def __init__(cls, name, bases, ns, total=True):
733736
super().__init__(name, bases, ns)
@@ -753,8 +756,10 @@ def __new__(cls, name, bases, ns, total=True):
753756
annotations = {}
754757
own_annotations = ns.get('__annotations__', {})
755758
msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type"
759+
kwds = {"module": tp_dict.__module__} if _TAKES_MODULE else {}
756760
own_annotations = {
757-
n: typing._type_check(tp, msg) for n, tp in own_annotations.items()
761+
n: typing._type_check(tp, msg, **kwds)
762+
for n, tp in own_annotations.items()
758763
}
759764
required_keys = set()
760765
optional_keys = set()

0 commit comments

Comments
 (0)
0