]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-141560: Add annotation_format parameter to getfullargspec (#149457)
authorJelle Zijlstra <jelle.zijlstra@gmail.com>
Wed, 6 May 2026 19:00:56 +0000 (12:00 -0700)
committerGitHub <noreply@github.com>
Wed, 6 May 2026 19:00:56 +0000 (12:00 -0700)
Doc/library/inspect.rst
Lib/inspect.py
Lib/test/test_inspect/test_inspect.py
Misc/NEWS.d/next/Library/2026-05-06-05-56-59.gh-issue-141560.wlSQaW.rst [new file with mode: 0644]

index 4825ac11ae2ee37694d8c2c1a533c614826c1a91..d8f9f98589c5840ef1b9b0f507f033f5d6ad9339 100644 (file)
@@ -1189,7 +1189,7 @@ Classes and functions
    times.
 
 
-.. function:: getfullargspec(func)
+.. function:: getfullargspec(func, *, annotation_format=Format.VALUE)
 
    Get the names and default values of a Python function's parameters.  A
    :term:`named tuple` is returned:
@@ -1219,6 +1219,14 @@ Classes and functions
    APIs. This function is retained primarily for use in code that needs to
    maintain compatibility with the Python 2 ``inspect`` module API.
 
+   A member of the
+   :class:`annotationlib.Format` enum can be passed to the
+   *annotation_format* parameter to control the format of the returned
+   annotations. For example, use
+   ``annotation_format=annotationlib.Format.STRING`` to return annotations in string
+   format. Note that with the default ``VALUE`` format, creation of some argspecs
+   may raise an exception.
+
    .. versionchanged:: 3.4
       This function is now based on :func:`signature`, but still ignores
       ``__wrapped__`` attributes and includes the already bound first
@@ -1236,6 +1244,9 @@ Classes and functions
       order of keyword-only parameters as of version 3.7, although in practice
       this order had always been preserved in Python 3.
 
+   .. versionchanged:: next
+      The *annotation_format* parameter was added.
+
 
 .. function:: getargvalues(frame)
 
index b1bbdd4c365e3d678fedf566da93b914fa53506f..a96b3dc954ef0ca850b17ca158ea79255460cfc5 100644 (file)
@@ -1254,11 +1254,10 @@ def getargs(co):
 FullArgSpec = namedtuple('FullArgSpec',
     'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations')
 
-def getfullargspec(func):
+def getfullargspec(func, *, annotation_format=Format.VALUE):
     """Get the names and default values of a callable object's parameters.
 
-    A tuple of seven things is returned:
-    (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations).
+    A FullArgSpec namedtuple is returned, which has the following attributes:
     'args' is a list of the parameter names.
     'varargs' and 'varkw' are the names of the * and ** parameters or None.
     'defaults' is an n-tuple of the default values of the last n parameters.
@@ -1266,6 +1265,9 @@ def getfullargspec(func):
     'kwonlydefaults' is a dictionary mapping names from kwonlyargs to defaults.
     'annotations' is a dictionary mapping parameter names to annotations.
 
+    The *annotation_format* parameter controls the format of the annotations.
+    See the annotationlib documentation for details.
+
     Notable differences from inspect.signature():
       - the "self" parameter is always reported, even for bound methods
       - wrapper chains defined by __wrapped__ *not* unwrapped automatically
@@ -1291,7 +1293,8 @@ def getfullargspec(func):
                                        follow_wrapper_chains=False,
                                        skip_bound_arg=False,
                                        sigcls=Signature,
-                                       eval_str=False)
+                                       eval_str=False,
+                                       annotation_format=annotation_format)
     except Exception as ex:
         # Most of the times 'signature' will raise ValueError.
         # But, it can also raise AttributeError, and, maybe something
index efe9d27e3407ff1243f0b7e37c4d7c1dfa68ec8f..9028d42c617fb4baa6b525d7b8da603c1e05eed9 100644 (file)
@@ -1355,9 +1355,10 @@ class TestClassesAndFunctions(unittest.TestCase):
                                     varkw_e=None, defaults_e=None,
                                     posonlyargs_e=[], kwonlyargs_e=[],
                                     kwonlydefaults_e=None,
-                                    ann_e={}):
+                                    ann_e={},
+                                    annotation_format=Format.VALUE):
         args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = \
-            inspect.getfullargspec(routine)
+            inspect.getfullargspec(routine, annotation_format=annotation_format)
         self.assertEqual(args, args_e)
         self.assertEqual(varargs, varargs_e)
         self.assertEqual(varkw, varkw_e)
@@ -1390,6 +1391,19 @@ class TestClassesAndFunctions(unittest.TestCase):
                                      kwonlyargs_e=['e', 'f'],
                                      kwonlydefaults_e={'e': 4, 'f': 5})
 
+    def get_getfullargspec_with_undefined_names_in_annotations(self):
+        def my_func(a: undefined_name):
+            pass
+
+        with self.assertRaises(NameError):
+            inspect.getfullargspec(my_func)
+
+        self.assertFullArgSpecEquals(my_func, ['a'], ann_e={'a': 'undefined_name'},
+                                     annotation_format=Format.STRING)
+
+        arg_spec = inspect.getfullargspec(my_func, annotation_format=Format.FORWARDREF)
+        self.assertIsInstance(arg_spec.annotations['a'], ForwardRef)
+
     def test_argspec_api_ignores_wrapped(self):
         # Issue 20684: low level introspection API must ignore __wrapped__
         @functools.wraps(mod.spam)
diff --git a/Misc/NEWS.d/next/Library/2026-05-06-05-56-59.gh-issue-141560.wlSQaW.rst b/Misc/NEWS.d/next/Library/2026-05-06-05-56-59.gh-issue-141560.wlSQaW.rst
new file mode 100644 (file)
index 0000000..7e5432b
--- /dev/null
@@ -0,0 +1 @@
+Add an *annotation_format* parameter to :func:`inspect.getfullargspec`.