Author petr.viktorin
Recipients petr.viktorin
Date 2015-05-27.15:33:36
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1432740816.68.0.329507187443.issue24298@psf.upfronthosting.co.za>
In-reply-to
Content
When obtaining the signature of a bound method, inspect.signature, by default, omits the "self" argument to the method, since it is already specified in the bound method.  However, if you create a wrapper around a bound method with functools.update_wrapper() or @functools.wraps, calling inspect.signature on the wrapper will return a signature which includes the "self" argument.

Reproducer:

    import inspect
    import functools

    class Foo(object):
        def bar(self, testarg):
            pass

    f = Foo()

    @functools.wraps(f.bar)
    def baz(*args):
        f.bar(*args)


    assert inspect.signature(baz) == inspect.signature(f.bar)

The program will fail with an assertion error. Examining inspect.signature(baz) shows:

    >>> print(inspect.signature(baz))
    (self, testarg)
    >>> print(inspect.signature(f.bar))
    (testarg)

Looking at the code in inspect.py:

The handling of bound methods appears at the top of inspect._signature_internal().  Since baz is not itself a bound method, it doesn't trigger this case.  Instead inspect.unwrap is called, returning f.bar.

inspect._signature_is_functionlike(f.bar) returns True, causing Signature.from_function to be called.  Unlike the direct bound method case, this includes the bound method's "self" argument.
History
Date User Action Args
2015-05-27 15:33:36petr.viktorinsetrecipients: + petr.viktorin
2015-05-27 15:33:36petr.viktorinsetmessageid: <1432740816.68.0.329507187443.issue24298@psf.upfronthosting.co.za>
2015-05-27 15:33:36petr.viktorinlinkissue24298 messages
2015-05-27 15:33:36petr.viktorincreate