This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: help(instance_of_builtin_class.method) does not display self
Type: behavior Stage: resolved
Components: Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: larry Nosy List: larry, terry.reedy, yselivanov, zach.ware
Priority: deferred blocker Keywords:

Created on 2014-01-24 14:06 by larry, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (7)
msg209078 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2014-01-24 14:06
For an object O that are bound to something (either a class or an instance), help(O) traditionally shows the bound argument.  For this code:

    class C:
        def foo(self, a):  pass

    c = C()

help(c.foo) would show the signature as "(self, a)", even though self has been bound.

My recent changes to Python's type system (#20189), to add inspect.Signature support for builtins, broke this.  The previous behavior should be restored.
msg209108 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-01-24 19:33
What matters to other programs is what the inspect functions return, not what help() does or does not do to the returned string before displaying it. So I see the issue as the discrepancy in this.

class C:
    def foo(self, a):  pass
c = C()

import inspect
print('garg - C.foo ', inspect.formatargspec(*inspect.getfullargspec(C.foo)))
print('garg - c.foo', inspect.formatargspec(*inspect.getfullargspec(c.foo)))
print('sig - C.foo ', str(inspect.signature(C.foo)))
print('sig - c.foo', str(inspect.signature(c.foo)))
>>> 
garg - C.foo  (self, a)
garg - c.foo (self, a)
sig - C.foo  (self, a)
sig - c.foo (a)

Idle calltips attempt to remind the user what they must and might enter after '('. For this, the sig output correct and the garg output is buggy. Idle currently works around the garg bug by selectively deleting the first param name with
        if (isinstance(ob, (type, types.MethodType)) or
                isinstance(ob_call, types.MethodType)):
            argspec = _first_param.sub("", argspec)

If signatures for bound builtins are similarly buggy, by including 'self' when it should be omitted, calltips would need a means to detect when to omit. Perhaps
>>> type([].append)
<class 'builtin_function_or_method'>
will work, but the name implies otherwise. In any case, I would prefer that inspect.signature give correct results instead of being made bug-compatible with .getfullargspec. In other words, it should include the 'delete self' code that is correct for the implementation. Then I could omit the yet-to-be-written expanded workaround.

I regard this help output as buggy.

>>> help(c.foo)
Help on method foo in module __main__:
foo(self, a) method of __main__.C instance

It identifies foo as a bound method, but gives the wrong signature for a bound method. So in my view, your changes fix a bug rather than breaking correct behavior.
msg209119 - (view) Author: Zachary Ware (zach.ware) * (Python committer) Date: 2014-01-24 20:55
I don't think there's any danger of changing inspect.Signature's behavior here; it's doing the right thing.  What we're concerned with here is just making sure that the output of 'help(some_kind_of_method)' is equivalent to the output of 'help(some_kind_of_method_in_C)', which should just mean changes to pydoc.

pydoc currently shows the 'self' parameter because before trying to find the signature, it replaces the object it is looking at with that object's __func__ attribute (see Lib/pydoc.py:1315).  To get rid of that behavior for Python-implemented methods is as simple as removing that line.

Is that the route we want to go, though?  It makes sense and it does make Python and C methods (mostly) match so I'd be happy with it, but it does change the help output for every Python-implemented method.

There is still the issue that the help output for C-implemented methods don't say anything about whether they're bound or not, but that issue is just a sibling to this one.
msg209126 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2014-01-24 21:54
Huh.  So inspect.getfullargspec is the code ignoring whether or not a function is bound.

Well, help(x) should be consistent, whether x is a bound builtin class instance or a bound Python class instance.  Right now it isn't; it displays the "self" for the Python one but not for the builtin one.
msg209138 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2014-01-25 00:29
I fully agree that help(bound method) should be consistent. I just feel that it should be consistently correct ;-).

Help(ob) is intended for interactive use (Guido has said, but feel free to ask again), and indeed, is an optional interactive feature, and not a built-in. So I believe we are free to change the output to something better (as with Exception messages). For some things (classes), it prints out too much and Guido would like a bit less printed.
msg209589 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2014-01-28 21:32
FWIW, I solved the first arg consistency for inspect.getfullargspec in #17481. The latest patch always shows the first argument (self) for both python-defined and C-defined methods.
msg213715 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2014-03-16 05:17
Fixed in b2ee3fe195e2.
History
Date User Action Args
2022-04-11 14:57:57adminsetgithub: 64578
2014-03-16 05:17:01larrysetstatus: open -> closed
resolution: fixed
messages: + msg213715

stage: needs patch -> resolved
2014-01-28 21:32:59yselivanovsetnosy: + yselivanov
messages: + msg209589
2014-01-25 04:54:36zach.waresetmessages: - msg209145
2014-01-25 04:54:33zach.waresetmessages: - msg209144
2014-01-25 04:54:31zach.waresetmessages: - msg209143
2014-01-25 04:24:36larrysetmessages: + msg209145
2014-01-25 04:24:02zach.waresetmessages: + msg209144
2014-01-25 04:18:49larrysetmessages: + msg209143
2014-01-25 04:06:07larrysettitle: help(bound_builtin_class) does not display self -> help(instance_of_builtin_class.method) does not display self
2014-01-25 00:29:01terry.reedysetmessages: + msg209138
2014-01-24 21:54:08larrysetmessages: + msg209126
2014-01-24 20:55:34zach.waresetmessages: + msg209119
2014-01-24 19:33:01terry.reedysetnosy: + terry.reedy
messages: + msg209108
2014-01-24 14:06:42larrycreate