[Python-Dev] Updated PEP 362 (Function Signature Object)

Nick Coghlan ncoghlan at gmail.com
Thu Jun 7 08:56:56 CEST 2012


On Thu, Jun 7, 2012 at 11:16 AM, Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> On 2012-06-06, at 9:00 PM, Nick Coghlan wrote:
> So, the idea for the 'signature(obj)' function is to first check if
> 'obj' has '__signature__' attribute set, if yes - return it, if no -
> create a new one (but don't cache).

I'd say return a copy in the first case to be safe against accidental
modification. If someone actually wants in-place modification, they
can access __signature__ directly.

> I have a question about fixing 'functools.wraps()' - I'm not sure
> we need to.  I see two solutions to the problem:
>
> I) We fix 'functools.wraps' to do:
>
>   'wrapper.__signature__ = signature(wrapped)'
>
> II) We modify 'signature(obj)' function to do the following steps:
>
>   1. check if obj has '__signature__' attribute. If yes - return it.
>
>   2. check if obj has '__wrapped__' attribute.  If yes:
>   obj = obj.__wrapped__; goto 1.
>
>   3. Calculate new signature for obj and return it.
>
> I think that the second (II) approach is better, as we don't
> implicitly cache anything, and we don't calculate Signatures
> on each 'functools.wraps' call.

Oh, nice, I like it. Then the wrapped function only gets its own
signature attribute if it's actually being changed by one of the
wrappers and my example would become:

   def shared_vars(*shared_args):
       """Decorator factory that defines shared variables that are
passed to every invocation of the function"""
       def decorator(f):
           @functools.wraps(f)
           def wrapper(*args, **kwds):
               full_args = shared_args + args
               return f(*full_args, **kwds)
           # Override signature
           sig = wrapper.__signature__ = inspect.signature(f)
           for __ in shared_args:
               sig.popitem()

   @shared_vars({})
   def example(_state, arg1, arg2, arg3):
       # _state is for private communication between "shared_vars"
and the function
       # callers can't set it, and never see it (unless they dig into
example.__wrapped__)

Bonus: without implicit signature copying in functools, you can stick
with the plan of exposing everything via the inspect module.

We should still look into making whatever tweaks are needed to let
inspect.signature correctly handle functools.partial objects, though.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-Dev mailing list