Skip to content

Commit 3df23b5

Browse files
[3.10] bpo-44468: Never skip base classes in typing.get_type_hints(), even with invalid .__module__. (GH-26862) (GH-26920)
(cherry picked from commit 7569c0fe91dfcf562dee8c29798ecda74d738aa8) Co-authored-by: will-ca <[email protected]> Automerge-Triggered-By: GH:gvanrossum
1 parent 6cd369c commit 3df23b5

File tree

3 files changed

+21
-11
lines changed

3 files changed

+21
-11
lines changed

Lib/test/test_typing.py

+18-7
Original file line numberDiff line numberDiff line change
@@ -2276,13 +2276,6 @@ def test_no_isinstance(self):
22762276
with self.assertRaises(TypeError):
22772277
issubclass(int, ClassVar)
22782278

2279-
def test_bad_module(self):
2280-
# bpo-41515
2281-
class BadModule:
2282-
pass
2283-
BadModule.__module__ = 'bad' # Something not in sys.modules
2284-
self.assertEqual(get_type_hints(BadModule), {})
2285-
22862279
class FinalTests(BaseTestCase):
22872280

22882281
def test_basics(self):
@@ -3032,6 +3025,24 @@ class Foo:
30323025
# This previously raised an error under PEP 563.
30333026
self.assertEqual(get_type_hints(Foo), {'x': str})
30343027

3028+
def test_get_type_hints_bad_module(self):
3029+
# bpo-41515
3030+
class BadModule:
3031+
pass
3032+
BadModule.__module__ = 'bad' # Something not in sys.modules
3033+
self.assertNotIn('bad', sys.modules)
3034+
self.assertEqual(get_type_hints(BadModule), {})
3035+
3036+
def test_get_type_hints_annotated_bad_module(self):
3037+
# See https://bugs.python.org/issue44468
3038+
class BadBase:
3039+
foo: tuple
3040+
class BadType(BadBase):
3041+
bar: list
3042+
BadType.__module__ = BadBase.__module__ = 'bad'
3043+
self.assertNotIn('bad', sys.modules)
3044+
self.assertEqual(get_type_hints(BadType), {'foo': tuple, 'bar': list})
3045+
30353046

30363047
class GetUtilitiesTestCase(TestCase):
30373048
def test_get_origin(self):

Lib/typing.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -1700,10 +1700,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False):
17001700
hints = {}
17011701
for base in reversed(obj.__mro__):
17021702
if globalns is None:
1703-
try:
1704-
base_globals = sys.modules[base.__module__].__dict__
1705-
except KeyError:
1706-
continue
1703+
base_globals = getattr(sys.modules.get(base.__module__, None), '__dict__', {})
17071704
else:
17081705
base_globals = globalns
17091706
ann = base.__dict__.get('__annotations__', {})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`typing.get_type_hints` now finds annotations in classes and base classes
2+
with unexpected ``__module__``. Previously, it skipped those MRO elements.

0 commit comments

Comments
 (0)