[Python-Dev] Updated PEP 362 (Function Signature Object)
Nick Coghlan
ncoghlan at gmail.com
Wed Jun 6 08:48:31 CEST 2012
On Wed, Jun 6, 2012 at 12:51 PM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> As for moving Signature object to `functools`, we had this discussion with Brett, and here is what he suggested:
>
> Functools contains code that transforms what a function
> does while inspect is about introspection. These objects are
> all about introspection and not about transforming what a
> function does.
I actually disagree with that characterisation of the new feature, as:
1. __signature__ introduces the possibility for a function (or any
object, really) to say "this is my *real* signature, even if the lower
level details appear to be more permissive than that"
2. Signature.bind introduces the ability to split the "bind arguments
to parameters" operation from the "call object" operation
Those two use cases are about function manipulation rather than pure
introspection, making functools an appropriate home.
>> - "functools.update_wrapper" be enhanced to set "wrapper.__signature__
>> = signature(wrapped)"
>
> Big +1 on this one. If you give me a green light on this, I'll add this change along with the unit tests to the patch.
And this is actually the real reason I'm proposing functools as the
home for the new feature. I think this change would a great
enhancement to functools.wraps, but I also think making functools
depend on the inspect module would be a crazy thing to do :)
However, looking at the code, I think the split that makes sense is
for a lower level functools.signature to *only* support real function
objects (i.e. not even method objects).
At the inspect layer, inspect.signature could then support retrieving
a signature for an arbitrary callable roughly as follows:
def signature(f):
try:
# Real functions are handled directly by functools
return functools.signature(f)
except TypeError:
pass
# Not a function object, handle other kinds of callable
if isclass(f):
# Figure out a Signature based on f.__new__ and f.__init__
# Complain if the signatures are contradictory
# Account for the permissive behaviour of object.__new__
and object.__init__
return class_signature
if ismethod(f):
f = f.__func__
elif not isfunction(f):
try:
f = f.__call__
except AttributeError:
pass
return signature(f) # Use recursion for the initial
implementation sketch
That code is almost certainly wrong, but it should be enough to give
the general idea. The short version is:
1. Provide a functools.signature that expects ordinary function
objects (or objects with a __signature__ attribute)
2. Provide an inspect.signature that also handles other kinds of callable
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Dev
mailing list