aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/ann_module.py7
-rw-r--r--Lib/test/test_typing.py15
-rw-r--r--Lib/typing.py6
-rw-r--r--Misc/NEWS.d/next/Library/2019-11-21-11-39-17.bpo-37838.lRFcEC.rst1
4 files changed, 28 insertions, 1 deletions
diff --git a/Lib/test/ann_module.py b/Lib/test/ann_module.py
index 9e6b87dac40..0567d6de1b6 100644
--- a/Lib/test/ann_module.py
+++ b/Lib/test/ann_module.py
@@ -6,6 +6,7 @@ Empty lines above are for good reason (testing for correct line numbers)
"""
from typing import Optional
+from functools import wraps
__annotations__[1] = 2
@@ -51,3 +52,9 @@ def foo(x: int = 10):
def bar(y: List[str]):
x: str = 'yes'
bar()
+
+def dec(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ return func(*args, **kwargs)
+ return wrapper
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 49417efe511..ccd617c1fdf 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -2778,6 +2778,16 @@ except StopIteration as e:
gth = get_type_hints
+class ForRefExample:
+ @ann_module.dec
+ def func(self: 'ForRefExample'):
+ pass
+
+ @ann_module.dec
+ @ann_module.dec
+ def nested(self: 'ForRefExample'):
+ pass
+
class GetTypeHintTests(BaseTestCase):
def test_get_type_hints_from_various_objects(self):
@@ -2876,6 +2886,11 @@ class GetTypeHintTests(BaseTestCase):
'x': ClassVar[Optional[B]]})
self.assertEqual(gth(G), {'lst': ClassVar[List[T]]})
+ def test_get_type_hints_wrapped_decoratored_func(self):
+ expects = {'self': ForRefExample}
+ self.assertEqual(gth(ForRefExample.func), expects)
+ self.assertEqual(gth(ForRefExample.nested), expects)
+
class GetUtilitiesTestCase(TestCase):
def test_get_origin(self):
diff --git a/Lib/typing.py b/Lib/typing.py
index 27be37a369a..5523ee01e1f 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1234,7 +1234,11 @@ def get_type_hints(obj, globalns=None, localns=None):
if isinstance(obj, types.ModuleType):
globalns = obj.__dict__
else:
- globalns = getattr(obj, '__globals__', {})
+ nsobj = obj
+ # Find globalns for the unwrapped object.
+ while hasattr(nsobj, '__wrapped__'):
+ nsobj = nsobj.__wrapped__
+ globalns = getattr(nsobj, '__globals__', {})
if localns is None:
localns = globalns
elif localns is None:
diff --git a/Misc/NEWS.d/next/Library/2019-11-21-11-39-17.bpo-37838.lRFcEC.rst b/Misc/NEWS.d/next/Library/2019-11-21-11-39-17.bpo-37838.lRFcEC.rst
new file mode 100644
index 00000000000..96d804addeb
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2019-11-21-11-39-17.bpo-37838.lRFcEC.rst
@@ -0,0 +1 @@
+:meth:`typing.get_type_hints` properly handles functions decorated with :meth:`functools.wraps`.