Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Doc/library/inspect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -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)

Expand Down
11 changes: 7 additions & 4 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1254,18 +1254,20 @@ 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.
'kwonlyargs' is a list of keyword-only parameter names.
'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
Expand All @@ -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
Expand Down
18 changes: 16 additions & 2 deletions Lib/test/test_inspect/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,9 +1355,10 @@ def assertFullArgSpecEquals(self, routine, args_e, varargs_e=None,
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)
Expand Down Expand Up @@ -1390,6 +1391,19 @@ def test_getfullargspec(self):
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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add an *annotation_format* parameter to :func:`inspect.getfullargspec`.
Loading