return annotation. To retrieve a Signature object, use the :func:`signature`
function.
-.. function:: signature(callable)
+.. function:: signature(callable, \*, follow_wrapped=True)
Return a :class:`Signature` object for the given ``callable``::
Raises :exc:`ValueError` if no signature can be provided, and
:exc:`TypeError` if that type of object is not supported.
+ .. versionadded:: 3.5
+ ``follow_wrapped`` parameter. Pass ``False`` to get a signature of
+ ``callable`` specifically (``callable.__wrapped__`` will not be used to
+ unwrap decorated callables.)
+
.. note::
Some callables may not be introspectable in certain implementations of
>>> str(new_sig)
"(a, b) -> 'new return anno'"
- .. classmethod:: Signature.from_callable(obj)
+ .. classmethod:: Signature.from_callable(obj, \*, follow_wrapped=True)
Return a :class:`Signature` (or its subclass) object for a given callable
- ``obj``. This method simplifies subclassing of :class:`Signature`:
+ ``obj``. Pass ``follow_wrapped=False`` to get a signature of ``obj``
+ without unwrapping its ``__wrapped__`` chain.
- ::
+ This method simplifies subclassing of :class:`Signature`::
class MySignature(Signature):
pass
subclassing of :class:`~inspect.Signature` easier. (Contributed
by Yury Selivanov and Eric Snow in :issue:`17373`.)
+* New argument ``follow_wrapped`` for :func:`inspect.signature`.
+ (Contributed by Yury Selivanov in :issue:`20691`.)
+
ipaddress
---------
return _signature_from_builtin(cls, func)
@classmethod
- def from_callable(cls, obj):
+ def from_callable(cls, obj, *, follow_wrapped=True):
"""Constructs Signature for the given callable object."""
- return _signature_from_callable(obj, sigcls=cls)
+ return _signature_from_callable(obj, sigcls=cls,
+ follow_wrapper_chains=follow_wrapped)
@property
def parameters(self):
return rendered
-def signature(obj):
+def signature(obj, *, follow_wrapped=True):
"""Get a signature object for the passed callable."""
- return Signature.from_callable(obj)
+ return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
def _main():
class TestSignatureObject(unittest.TestCase):
@staticmethod
- def signature(func):
- sig = inspect.signature(func)
+ def signature(func, **kw):
+ sig = inspect.signature(func, **kw)
return (tuple((param.name,
(... if param.default is param.empty else param.default),
(... if param.annotation is param.empty
self.assertEqual(inspect.signature(func),
inspect.signature(decorated_func))
+ def wrapper_like(*args, **kwargs) -> int: pass
+ self.assertEqual(inspect.signature(decorated_func,
+ follow_wrapped=False),
+ inspect.signature(wrapper_like))
+
@cpython_only
def test_signature_on_builtins_no_signature(self):
import _testcapi
('b', ..., ..., "positional_or_keyword")),
...))
+ self.assertEqual(self.signature(Foo.bar, follow_wrapped=False),
+ ((('args', ..., ..., "var_positional"),
+ ('kwargs', ..., ..., "var_keyword")),
+ ...)) # functools.wraps will copy __annotations__
+ # from "func" to "wrapper", hence no
+ # return_annotation
+
# Test that we handle method wrappers correctly
def decorator(func):
@functools.wraps(func)
- Issue 24190: Implement inspect.BoundArgument.apply_defaults() method.
Contributed by Yury Selivanov.
+- Issue 20691: Add 'follow_wrapped' argument to
+ inspect.Signature.from_callable() and inspect.signature().
+ Contributed by Yury Selivanov.
+
Tests
-----