Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

functools.partial is not usable #2

Merged
merged 4 commits into from
Mar 12, 2014
Merged

functools.partial is not usable #2

merged 4 commits into from
Mar 12, 2014

Conversation

coldfix
Copy link
Owner

@coldfix coldfix commented Mar 12, 2014

In most cases, the signature of a functools.partial can not be used by ASTorator: arguments with default values are

  • present in the signature - even if they were bound as positional arguments (which cannot be reinserted at call time)
  • at the original position! - even if there are more positional parameters behind them (which means that default values will be bound to the wrong parameters in the decorated function)
  • bound position arguments effectively become keyword-only arguments. This is (1) a concept which is not natively supported in python2 and (2) not reflected in the value of param.kind, so it can't be handled by python3 code either.

Example:

>>> from functools import partial
>>> from inspect import signature
>>> def func(a, b):
...     pass
>>> for k,v in signature(partial(func, a=1)).parameters.items():
...     print('%s: %s=%s' % (v.kind, v.name, v.default) )
POSITIONAL_OR_KEYWORD: a=1
POSITIONAL_OR_KEYWORD: b=<class 'inspect._empty'>

@coldfix
Copy link
Owner Author

coldfix commented Feb 12, 2014

The position could be fixed by comparing comparing param.default is param.empty.

I see no way to fix the presence of the parameter from the signature alone.

The keyword-only argument issue makes a fix improbable.

@coldfix
Copy link
Owner Author

coldfix commented Feb 12, 2014

The first bullet point is actually a lie:

>>> from functools import partial
>>> from inspect import signature

>>> def func(a, b):
...     pass

>>> for k,v in signature(partial(func, 1)).parameters.items():
...     print('%s: %s=%s' % (v.kind, v.name, v.default) )
POSITIONAL_OR_KEYWORD: b=<class 'inspect._empty'>

@coldfix
Copy link
Owner Author

coldfix commented Feb 15, 2014

Just noticed:
Partial keyword arguments can be determined from the signature: The corresponding parameter will have param._partial_kwarg=True.

This should make it possibe to create keyword only versions on python3.
I don't know if there is any good solution on python2, since can be unbound keyword-only parameters.

@coldfix
Copy link
Owner Author

coldfix commented Mar 5, 2014

I think, a valid solution is to make all functools.partial objects behave like black_magic.decorator.partial objects with the same bindings, i.e. remove the bound parameters and move the positionial-or-keyword parameters to the left.

@coldfix
Copy link
Owner Author

coldfix commented Mar 12, 2014

Note, not merging this yet, since functools.partial doesn't work with black_magic.decorator.partial yet. This will probably be very messy to implement.

coldfix added a commit that referenced this pull request Mar 12, 2014
functools.partial is not usable
@coldfix coldfix merged commit 859bf6a into master Mar 12, 2014
@coldfix coldfix deleted the functools.partial branch March 12, 2014 20:28
@coveralls
Copy link

Coverage Status

Coverage remained the same when pulling a31ce30 on functools.partial into dea304a on master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants