Issue 24190: Add inspect.BoundArguments.apply_defaults() method.

This commit is contained in:
Yury Selivanov 2015-05-16 13:45:09 -04:00
parent 1392f71c39
commit b907a513c8
5 changed files with 91 additions and 21 deletions

View File

@ -667,27 +667,8 @@ function.
Arguments for which :meth:`Signature.bind` or
:meth:`Signature.bind_partial` relied on a default value are skipped.
However, if needed, it is easy to include them.
::
>>> def foo(a, b=10):
... pass
>>> sig = signature(foo)
>>> ba = sig.bind(5)
>>> ba.args, ba.kwargs
((5,), {})
>>> for param in sig.parameters.values():
... if (param.name not in ba.arguments
... and param.default is not param.empty):
... ba.arguments[param.name] = param.default
>>> ba.args, ba.kwargs
((5, 10), {})
However, if needed, use :meth:`BoundArguments.apply_defaults` to add
them.
.. attribute:: BoundArguments.args
@ -703,6 +684,24 @@ function.
A reference to the parent :class:`Signature` object.
.. method:: BoundArguments.apply_defaults()
Set default values for missing arguments.
For variable-positional arguments (``*args``) the default is an
empty tuple.
For variable-keyword arguments (``**kwargs``) the default is an
empty dict.
::
>>> def foo(a, b='ham', *args): pass
>>> ba = inspect.signature(foo).bind('spam')
>>> ba.apply_defaults()
>>> ba.arguments
OrderedDict([('a', 'spam'), ('b', 'ham'), ('args', ())])
The :attr:`args` and :attr:`kwargs` properties can be used to invoke
functions::

View File

@ -400,6 +400,9 @@ inspect
picklable and hashable. (Contributed by Yury Selivanov in :issue:`20726`
and :issue:`20334`.)
* New method :meth:`inspect.BoundArguments.apply_defaults`. (Contributed
by Yury Selivanov in :issue:`24190`.)
* New class method :meth:`inspect.Signature.from_callable`, which makes
subclassing of :class:`~inspect.Signature` easier. (Contributed
by Yury Selivanov and Eric Snow in :issue:`17373`.)

View File

@ -2443,6 +2443,36 @@ class BoundArguments:
return kwargs
def apply_defaults(self):
"""Set default values for missing arguments.
For variable-positional arguments (*args) the default is an
empty tuple.
For variable-keyword arguments (**kwargs) the default is an
empty dict.
"""
arguments = self.arguments
if not arguments:
return
new_arguments = []
for name, param in self._signature.parameters.items():
try:
new_arguments.append((name, arguments[name]))
except KeyError:
if param.default is not _empty:
val = param.default
elif param.kind is _VAR_POSITIONAL:
val = ()
elif param.kind is _VAR_KEYWORD:
val = {}
else:
# This BoundArguments was likely produced by
# Signature.bind_partial().
continue
new_arguments.append((name, val))
self.arguments = OrderedDict(new_arguments)
def __eq__(self, other):
return (self is other or
(issubclass(other.__class__, BoundArguments) and

View File

@ -3153,6 +3153,41 @@ class TestBoundArguments(unittest.TestCase):
ba = sig.bind(20, 30, z={})
self.assertRegex(repr(ba), r'<BoundArguments \(a=20,.*\}\}\)>')
def test_signature_bound_arguments_apply_defaults(self):
def foo(a, b=1, *args, c:1={}, **kw): pass
sig = inspect.signature(foo)
ba = sig.bind(20)
ba.apply_defaults()
self.assertEqual(
list(ba.arguments.items()),
[('a', 20), ('b', 1), ('args', ()), ('c', {}), ('kw', {})])
# Make sure that we preserve the order:
# i.e. 'c' should be *before* 'kw'.
ba = sig.bind(10, 20, 30, d=1)
ba.apply_defaults()
self.assertEqual(
list(ba.arguments.items()),
[('a', 10), ('b', 20), ('args', (30,)), ('c', {}), ('kw', {'d':1})])
# Make sure that BoundArguments produced by bind_partial()
# are supported.
def foo(a, b): pass
sig = inspect.signature(foo)
ba = sig.bind_partial(20)
ba.apply_defaults()
self.assertEqual(
list(ba.arguments.items()),
[('a', 20)])
# Test no args
def foo(): pass
sig = inspect.signature(foo)
ba = sig.bind()
ba.apply_defaults()
self.assertEqual(list(ba.arguments.items()), [])
class TestSignaturePrivateHelpers(unittest.TestCase):
def test_signature_get_bound_param(self):

View File

@ -131,6 +131,9 @@ Library
- Issue 22547: Implement informative __repr__ for inspect.BoundArguments.
Contributed by Yury Selivanov.
- Issue 24190: Implement inspect.BoundArgument.apply_defaults() method.
Contributed by Yury Selivanov.
Tests
-----