Picking the appropriate arguments for forwards
¶
If automatic signature reporting (sigtools.signature
) doesn’t work for your use case and you still
want to specify how a function’s *args, **kwargs
is being used, you may
either use sigtools.specifiers.forger_function
and sigtools.support.s
to override its signature completely, or you can use the forwards_to_*
functions from sigtools.specifiers
.
For forwards_to_*
decorators, you only need to specify what function
*args, **kwargs
are forwarded to and what other arguments are passed in.
Here’s a primer with common examples on how to use them.
Picking the appropriate forwards_to_*
decorator¶
Several forwards_to_*
decorators exist. You must pick one depending on what
you are forwarding your parameters to:
forwards_to_function
When forwarding to a plain function:
def inner(a, b, c): ... @specifiers.forwards_to_function(inner) def outer(*args, **kwargs): inner(*args, **kwargs)
Provide the inner function as the first argument to
forwards_to_function
.forwards_to_method
When forwarding to an attribute of the current object, usually to a method:
class Spam: def inner(self, a, b, c): ... @specifiers.forwards_to_method('inner') def outer(self, *args, **kwargs): self.inner(*args, **kwargs)
Provide the inner function’s name to
forwards_to_method
.You can also specify a “deep” attribute:
'attribute.method'
should be specified if a call is made like this:self.attribute.method(*args, **kwargs)
forwards_to_super
When forwarding to the superclass’s method of the same name:
class Spam: def method(self): pass class Ham(Spam): @specifiers.forwards_to_super() def method(self, *args, ham, **kwargs): super().method(*args, **kwargs)
This only works when using the short form of
super()
introduced in Python 3.3. If you are targetting earlier versions, useapply_forwards_to_super
on the class, while specifying which methods need to receive the decorator.
For the following examples, we will be using the
forwards_to_function
decorator, although these will work with
other forwards_to_*
decorators.
*args
and **kwargs
are forwarded directly if present¶
You do not need to signal anything about the wrapper function’s parameters:
@specifiers.forwards_to_function(wrapped)
def outer(arg, *args, **kwargs):
inner(*args, **kwargs)
This holds true even if you omit one of *args
and **kwargs
:
@specifiers.forwards_to_function(wrapped)
def outer(**kwargs):
inner(**kwargs)
Passing positional arguments to the wrapped function¶
Indicate the number of arguments you are passing to the wrapped function:
@specifiers.forwards_to_function(wrapped, 1)
def outer(*args, **kwargs):
inner('abc', *args, **kwargs)
This applies even if the argument comes from the wrapper:
@specifiers.forwards_to_function(wrapped, 1)
def outer(arg, *args, **kwargs):
inner(arg, *args, **kwargs)
Passing named arguments to from the wrapper¶
Pass the names of the arguments after num_args
:
@specifiers.forwards_to_function(wrapped, 0, 'arg')
def outer(*args, **kwargs):
inner(*args, arg='abc', **kwargs)
Once again, the same goes for if that argument comes from the outer function’s:
@specifiers.forwards_to_function(wrapped, 0, 'arg')
def outer(*args, arg, **kwargs): # py 3
inner(*args, arg=arg, **kwargs)
If you combine positional and named arguments, follow the previous advice as well:
@specifiers.forwards_to_function(wrapped, 2, 'alpha', 'beta')
def outer(two, *args, beta, **kwargs):
inner(one, two=two, *args, alpha='abc', beta=beta, **kwargs)
When the outer function uses *args
or **kwargs
but doesn’t forward them to the inner function¶
Pass use_varargs=False
if your outer function has an *args
-like
parameter but doesn’t use it on the inner function directly:
@specifiers.forwards_to_function(wrapped, use_varargs=False)
def outer(*args, **kwargs):
inner(**kwargs)
Pass use_varkwargs=False
if you outer function has a **kwargs
-like
parameter but doesn’t use it on the inner function directly:
@specifiers.forwards_to_function(wrapped, use_varkwargs=False)
def outer(*args, **kwargs):
inner(*args)
When the outer function passes an arbitrary *args
or **kwargs
to the inner function¶
Pass hide_args=True
if your outer function uses an arbitrary *args
when
calling the inner function (whether one exists or not in the outer function):
@specifiers.forwards_to_function(wrapped, hide_args=True)
def outer(**kwargs):
args = other_function(...)
inner(*args, **kwargs)
If you know exactly how many items args
will have, specify the amount of
items in args
instead, as in Passing positional arguments to the wrapped function.
Conversely, pass hide_kwargs=True
if your outer function uses an arbitrary
*kwargs
when calling the inner function (whether one exists or not in the
outer function):
@specifiers.forwards_to_function(wrapped, hide_args=True)
def outer(*args):
kwargs = other_function(...)
inner(*args, **kwargs)
If you know exactly which keys kwargs
will potentially have, specify all
possible named keys it might have, as in Passing named arguments to from the wrapper.
Note
Neither are needed if the outer function hasn’t got an *args
nor
**kwargs
parameter
Summary¶
Finally, here’s an overview of all parameters from forwards_to_*
functions
- sigtools.specifiers.forwards_to_function(wrapped, num_args=0, *named_args, emulate=None, hide_args=False, hide_kwargs=False, use_varargs=True, use_varkwargs=True, partial=False)[source]
- num_args
The number of arguments you pass by position, excluding
*args
.- *named_args
The names of the arguments you pass by name, excluding
**kwargs
.- use_varargs=
Tells if the wrapper’s
*args
is being passed to the wrapped function.- use_varkwargs=
Tells if the wrapper’s
**kwargs
is being passed to the wrapped function.- hide_args=
Tells if the wrapped function is given an
*args
parameter (other than the wrapper function’s) in such a way that all positional parameters are consumed.- hide_varargs=
Tells if the wrapped function is given a
**kargs
parameter (other than the wrapper function’s) in such a way that all keyword parameters are consumed.