mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
bpo-19903: IDLE: Calltips changed to use inspect.signature (#2822)
Idlelib.calltips.get_argspec now uses inspect.signature instead of inspect.getfullargspec, like help() does. This improves the signature in the call tip in a few different cases, including builtins converted to provide a signature. A message is added if the object is not callable, has an invalid signature, or if it has positional-only parameters. Patch by Louie Lu.
This commit is contained in:
parent
3ca9f50f96
commit
3b0f620c1a
3 changed files with 62 additions and 26 deletions
|
@ -123,6 +123,8 @@ _MAX_LINES = 5 # enough for bytes
|
|||
_INDENT = ' '*4 # for wrapped signatures
|
||||
_first_param = re.compile(r'(?<=\()\w*\,?\s*')
|
||||
_default_callable_argspec = "See source or doc"
|
||||
_invalid_method = "invalid method signature"
|
||||
_argument_positional = "\n['/' marks preceding arguments as positional-only]\n"
|
||||
|
||||
|
||||
def get_argspec(ob):
|
||||
|
@ -134,25 +136,30 @@ def get_argspec(ob):
|
|||
empty line or _MAX_LINES. For builtins, this typically includes
|
||||
the arguments in addition to the return value.
|
||||
'''
|
||||
argspec = ""
|
||||
argspec = default = ""
|
||||
try:
|
||||
ob_call = ob.__call__
|
||||
except BaseException:
|
||||
return argspec
|
||||
if isinstance(ob, type):
|
||||
fob = ob.__init__
|
||||
elif isinstance(ob_call, types.MethodType):
|
||||
fob = ob_call
|
||||
else:
|
||||
fob = ob
|
||||
if isinstance(fob, (types.FunctionType, types.MethodType)):
|
||||
argspec = inspect.formatargspec(*inspect.getfullargspec(fob))
|
||||
if (isinstance(ob, (type, types.MethodType)) or
|
||||
isinstance(ob_call, types.MethodType)):
|
||||
argspec = _first_param.sub("", argspec)
|
||||
return default
|
||||
|
||||
fob = ob_call if isinstance(ob_call, types.MethodType) else ob
|
||||
|
||||
try:
|
||||
argspec = str(inspect.signature(fob))
|
||||
except ValueError as err:
|
||||
msg = str(err)
|
||||
if msg.startswith(_invalid_method):
|
||||
return _invalid_method
|
||||
|
||||
if '/' in argspec:
|
||||
"""Using AC's positional argument should add the explain"""
|
||||
argspec += _argument_positional
|
||||
if isinstance(fob, type) and argspec == '()':
|
||||
"""fob with no argument, use default callable argspec"""
|
||||
argspec = _default_callable_argspec
|
||||
|
||||
lines = (textwrap.wrap(argspec, _MAX_COLS, subsequent_indent=_INDENT)
|
||||
if len(argspec) > _MAX_COLS else [argspec] if argspec else [])
|
||||
if len(argspec) > _MAX_COLS else [argspec] if argspec else [])
|
||||
|
||||
if isinstance(ob_call, types.MethodType):
|
||||
doc = ob_call.__doc__
|
||||
|
@ -171,6 +178,7 @@ def get_argspec(ob):
|
|||
argspec = _default_callable_argspec
|
||||
return argspec
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from unittest import main
|
||||
main('idlelib.idle_test.test_calltips', verbosity=2)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue