-
Notifications
You must be signed in to change notification settings - Fork 1
Description
There is something with FuncFactory that might be unintuitive to the novice here:
that a FuncFactory can be called with anything between none to all of the
parameters given by it's signature, regardless of whether the argument appears to
be required (because the signature shows it as not having a default).
from i2 import FuncFactory
def foo(x, y, z=2):
return x + y * z
f = FuncFactory(foo)
Sig(f)
# <Sig (x, y, z=2)>We see that x and y are required arguments of f, and yet, I can call f like this:
t = f()
tt = f(x=1)
ttt = f(y=2)What's unintuitive is that most callables can only be called if all their required arguments
(i.e. those that don't have defaults) are given.
But in the case of a FuncFactory instance it is not so because it is meant to
be a factory where any thing between all and none of the arguments of the
wrapped function can be given (having the effect of making a version of the
wrapped function where that subset of specified argument have be given default
values).
One solution maybe to all non-defaulted values show up (in signature) as NotSet sentinel
so that these arguments don't appear to be "required".
This signature would just appear a FuncFactory instance, but not in the partial object it creates when called.
Related issue: rm_params with allow_removal_of_non_defaulted_params doesn't exactly work
Proposal code:
In the init of FuncFactory:
...
shown_factory_sig = actual_factory_sig.ch_defaults(
**{name: NotSet for name in actual_factory_sig.required_names}
)
shown_factory_sig = shown_factory_sig[self.include]
self.__signature__ = shown_factory_sig
...and in _process_args_and_kwargs:
def _process_args_and_kwargs(self, args, kwargs):
_kwargs = self.factory_sig.kwargs_from_args_and_kwargs(
args, kwargs, allow_partial=True, ignore_kind=True
)
_kwargs = {k: v for k, v in _kwargs.items() if v is not NotSet} # <-- New part!
__args, __kwargs = self.func_sig.args_and_kwargs_from_kwargs(
_kwargs, allow_partial=True, ignore_kind=False
)
return __args, __kwargswhere
from i2 import mk_sentinel
def _not_set_repr(self):
return 'NotSet'
NotSet = mk_sentinel('NotSet', repr_=_not_set_repr)