@@ -934,7 +934,7 @@ def getargspec(func):
934934 'args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations' )
935935
936936def getfullargspec (func ):
937- """Get the names and default values of a function 's arguments.
937+ """Get the names and default values of a callable object 's arguments.
938938
939939 A tuple of seven things is returned:
940940 (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults annotations).
@@ -948,13 +948,90 @@ def getfullargspec(func):
948948 The first four items in the tuple correspond to getargspec().
949949 """
950950
951+ builtin_method_param = None
952+
951953 if ismethod (func ):
954+ # There is a notable difference in behaviour between getfullargspec
955+ # and Signature: the former always returns 'self' parameter for bound
956+ # methods, whereas the Signature always shows the actual calling
957+ # signature of the passed object.
958+ #
959+ # To simulate this behaviour, we "unbind" bound methods, to trick
960+ # inspect.signature to always return their first parameter ("self",
961+ # usually)
952962 func = func .__func__
953- if not isfunction (func ):
954- raise TypeError ('{!r} is not a Python function' .format (func ))
955- args , varargs , kwonlyargs , varkw = _getfullargs (func .__code__ )
956- return FullArgSpec (args , varargs , varkw , func .__defaults__ ,
957- kwonlyargs , func .__kwdefaults__ , func .__annotations__ )
963+
964+ elif isbuiltin (func ):
965+ # We have a builtin function or method. For that, we check the
966+ # special '__text_signature__' attribute, provided by the
967+ # Argument Clinic. If it's a method, we'll need to make sure
968+ # that its first parameter (usually "self") is always returned
969+ # (see the previous comment).
970+ text_signature = getattr (func , '__text_signature__' , None )
971+ if text_signature and text_signature .startswith ('($' ):
972+ builtin_method_param = _signature_get_bound_param (text_signature )
973+
974+ try :
975+ sig = signature (func )
976+ except Exception as ex :
977+ # Most of the times 'signature' will raise ValueError.
978+ # But, it can also raise AttributeError, and, maybe something
979+ # else. So to be fully backwards compatible, we catch all
980+ # possible exceptions here, and reraise a TypeError.
981+ raise TypeError ('unsupported callable' ) from ex
982+
983+ args = []
984+ varargs = None
985+ varkw = None
986+ kwonlyargs = []
987+ defaults = ()
988+ annotations = {}
989+ defaults = ()
990+ kwdefaults = {}
991+
992+ if sig .return_annotation is not sig .empty :
993+ annotations ['return' ] = sig .return_annotation
994+
995+ for param in sig .parameters .values ():
996+ kind = param .kind
997+ name = param .name
998+
999+ if kind is _POSITIONAL_ONLY :
1000+ args .append (name )
1001+ elif kind is _POSITIONAL_OR_KEYWORD :
1002+ args .append (name )
1003+ if param .default is not param .empty :
1004+ defaults += (param .default ,)
1005+ elif kind is _VAR_POSITIONAL :
1006+ varargs = name
1007+ elif kind is _KEYWORD_ONLY :
1008+ kwonlyargs .append (name )
1009+ if param .default is not param .empty :
1010+ kwdefaults [name ] = param .default
1011+ elif kind is _VAR_KEYWORD :
1012+ varkw = name
1013+
1014+ if param .annotation is not param .empty :
1015+ annotations [name ] = param .annotation
1016+
1017+ if not kwdefaults :
1018+ # compatibility with 'func.__kwdefaults__'
1019+ kwdefaults = None
1020+
1021+ if not defaults :
1022+ # compatibility with 'func.__defaults__'
1023+ defaults = None
1024+
1025+ if builtin_method_param and (not args or args [0 ] != builtin_method_param ):
1026+ # `func` is a method, and we always need to return its
1027+ # first parameter -- usually "self" (to be backwards
1028+ # compatible with the previous implementation of
1029+ # getfullargspec)
1030+ args .insert (0 , builtin_method_param )
1031+
1032+ return FullArgSpec (args , varargs , varkw , defaults ,
1033+ kwonlyargs , kwdefaults , annotations )
1034+
9581035
9591036ArgInfo = namedtuple ('ArgInfo' , 'args varargs keywords locals' )
9601037
@@ -1524,6 +1601,28 @@ def _signature_is_builtin(obj):
15241601 obj in (type , object ))
15251602
15261603
1604+ def _signature_get_bound_param (spec ):
1605+ # Internal helper to get first parameter name from a
1606+ # __text_signature__ of a builtin method, which should
1607+ # be in the following format: '($param1, ...)'.
1608+ # Assumptions are that the first argument won't have
1609+ # a default value or an annotation.
1610+
1611+ assert spec .startswith ('($' )
1612+
1613+ pos = spec .find (',' )
1614+ if pos == - 1 :
1615+ pos = spec .find (')' )
1616+
1617+ cpos = spec .find (':' )
1618+ assert cpos == - 1 or cpos > pos
1619+
1620+ cpos = spec .find ('=' )
1621+ assert cpos == - 1 or cpos > pos
1622+
1623+ return spec [2 :pos ]
1624+
1625+
15271626def signature (obj ):
15281627 '''Get a signature object for the passed callable.'''
15291628
0 commit comments