https://github.com/python/cpython/commit/dc441efbd00b8dd2f26d014fb67895d381a8f602
commit: dc441efbd00b8dd2f26d014fb67895d381a8f602
branch: 3.14
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: JelleZijlstra <jelle.zijls...@gmail.com>
date: 2025-05-26T08:22:14Z
summary:

[3.14] gh-132493: Remove __annotations__ usage in 
inspect._signature_is_functionlike (GH-133415) (#133796)

gh-132493: Remove __annotations__ usage in inspect._signature_is_functionlike 
(GH-133415)

This check is potentially problematic because it could force evaluation of
annotations unnecessarily. This doesn't trigger for builtin objects (functions,
classes, or modules) with annotations, but it could trigger for third-party 
objects.

The check was not particularly useful anyway, because it succeeds if 
``__annotations__``
is a dict or None, so the only thing this did was guard against objects that 
have an
``__annotations__`` attribute that is of some other type. That doesn't seem 
particularly
useful, so I just removed the check.
(cherry picked from commit cb6596c6aa30c8c3213c8746d5590e6e2757a6c1)

Co-authored-by: Jelle Zijlstra <jelle.zijls...@gmail.com>

files:
A Misc/NEWS.d/next/Library/2025-05-04-17-04-55.gh-issue-132493.huirKi.rst
M Lib/inspect.py
M Lib/test/test_inspect/test_inspect.py

diff --git a/Lib/inspect.py b/Lib/inspect.py
index 52c9bb05b31f37..183e67fabf966e 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -2074,13 +2074,11 @@ def _signature_is_functionlike(obj):
     code = getattr(obj, '__code__', None)
     defaults = getattr(obj, '__defaults__', _void) # Important to use _void ...
     kwdefaults = getattr(obj, '__kwdefaults__', _void) # ... and not None here
-    annotations = getattr(obj, '__annotations__', None)
 
     return (isinstance(code, types.CodeType) and
             isinstance(name, str) and
             (defaults is None or isinstance(defaults, tuple)) and
-            (kwdefaults is None or isinstance(kwdefaults, dict)) and
-            (isinstance(annotations, (dict)) or annotations is None) )
+            (kwdefaults is None or isinstance(kwdefaults, dict)))
 
 
 def _signature_strip_non_python_syntax(signature):
diff --git a/Lib/test/test_inspect/test_inspect.py 
b/Lib/test/test_inspect/test_inspect.py
index 57dc7a24af94b8..44f7a54bbf1c1e 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -4997,6 +4997,37 @@ def test_signature_annotation_format(self):
                 with self.assertRaisesRegex(NameError, "undefined"):
                     signature_func(ida.f)
 
+    def test_signature_deferred_annotations(self):
+        def f(x: undef):
+            pass
+
+        class C:
+            x: undef
+
+            def __init__(self, x: undef):
+                self.x = x
+
+        sig = inspect.signature(f, annotation_format=Format.FORWARDREF)
+        self.assertEqual(list(sig.parameters), ['x'])
+        sig = inspect.signature(C, annotation_format=Format.FORWARDREF)
+        self.assertEqual(list(sig.parameters), ['x'])
+
+        class CallableWrapper:
+            def __init__(self, func):
+                self.func = func
+                self.__annotate__ = func.__annotate__
+
+            def __call__(self, *args, **kwargs):
+                return self.func(*args, **kwargs)
+
+            @property
+            def __annotations__(self):
+                return self.__annotate__(Format.VALUE)
+
+        cw = CallableWrapper(f)
+        sig = inspect.signature(cw, annotation_format=Format.FORWARDREF)
+        self.assertEqual(list(sig.parameters), ['args', 'kwargs'])
+
     def test_signature_none_annotation(self):
         class funclike:
             # Has to be callable, and have correct
diff --git 
a/Misc/NEWS.d/next/Library/2025-05-04-17-04-55.gh-issue-132493.huirKi.rst 
b/Misc/NEWS.d/next/Library/2025-05-04-17-04-55.gh-issue-132493.huirKi.rst
new file mode 100644
index 00000000000000..ad06ee6b7a2757
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-05-04-17-04-55.gh-issue-132493.huirKi.rst
@@ -0,0 +1,2 @@
+Avoid accessing ``__annotations__`` unnecessarily in
+:func:`inspect.signature`.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to