@@ -949,9 +949,9 @@ def getfullargspec(func):
949949 The first four items in the tuple correspond to getargspec().
950950 """
951951
952- builtin_method_param = None
953-
954- if ismethod ( func ):
952+ try :
953+ # Re: `skip_bound_arg=False`
954+ #
955955 # There is a notable difference in behaviour between getfullargspec
956956 # and Signature: the former always returns 'self' parameter for bound
957957 # methods, whereas the Signature always shows the actual calling
@@ -960,20 +960,15 @@ def getfullargspec(func):
960960 # To simulate this behaviour, we "unbind" bound methods, to trick
961961 # inspect.signature to always return their first parameter ("self",
962962 # usually)
963- func = func .__func__
964963
965- elif isbuiltin (func ):
966- # We have a builtin function or method. For that, we check the
967- # special '__text_signature__' attribute, provided by the
968- # Argument Clinic. If it's a method, we'll need to make sure
969- # that its first parameter (usually "self") is always returned
970- # (see the previous comment).
971- text_signature = getattr (func , '__text_signature__' , None )
972- if text_signature and text_signature .startswith ('($' ):
973- builtin_method_param = _signature_get_bound_param (text_signature )
964+ # Re: `follow_wrapper_chains=False`
965+ #
966+ # getfullargspec() historically ignored __wrapped__ attributes,
967+ # so we ensure that remains the case in 3.3+
974968
975- try :
976- sig = signature (func )
969+ sig = _signature_internal (func ,
970+ follow_wrapper_chains = False ,
971+ skip_bound_arg = False )
977972 except Exception as ex :
978973 # Most of the times 'signature' will raise ValueError.
979974 # But, it can also raise AttributeError, and, maybe something
@@ -1023,13 +1018,6 @@ def getfullargspec(func):
10231018 # compatibility with 'func.__defaults__'
10241019 defaults = None
10251020
1026- if builtin_method_param and (not args or args [0 ] != builtin_method_param ):
1027- # `func` is a method, and we always need to return its
1028- # first parameter -- usually "self" (to be backwards
1029- # compatible with the previous implementation of
1030- # getfullargspec)
1031- args .insert (0 , builtin_method_param )
1032-
10331021 return FullArgSpec (args , varargs , varkw , defaults ,
10341022 kwonlyargs , kwdefaults , annotations )
10351023
@@ -1719,7 +1707,7 @@ def _signature_strip_non_python_syntax(signature):
17191707 return clean_signature , self_parameter , last_positional_only
17201708
17211709
1722- def _signature_fromstr (cls , obj , s ):
1710+ def _signature_fromstr (cls , obj , s , skip_bound_arg = True ):
17231711 # Internal helper to parse content of '__text_signature__'
17241712 # and return a Signature based on it
17251713 Parameter = cls ._parameter_cls
@@ -1840,7 +1828,7 @@ def p(name_node, default_node, default=empty):
18401828
18411829 if self_parameter is not None :
18421830 assert parameters
1843- if getattr (obj , '__self__' , None ):
1831+ if getattr (obj , '__self__' , None ) and skip_bound_arg :
18441832 # strip off self, it's already been bound
18451833 parameters .pop (0 )
18461834 else :
@@ -1851,20 +1839,39 @@ def p(name_node, default_node, default=empty):
18511839 return cls (parameters , return_annotation = cls .empty )
18521840
18531841
1854- def signature (obj ):
1855- '''Get a signature object for the passed callable.'''
1842+ def _signature_from_builtin (cls , func , skip_bound_arg = True ):
1843+ # Internal helper function to get signature for
1844+ # builtin callables
1845+ if not _signature_is_builtin (func ):
1846+ raise TypeError ("{!r} is not a Python builtin "
1847+ "function" .format (func ))
1848+
1849+ s = getattr (func , "__text_signature__" , None )
1850+ if not s :
1851+ raise ValueError ("no signature found for builtin {!r}" .format (func ))
1852+
1853+ return _signature_fromstr (cls , func , s , skip_bound_arg )
1854+
1855+
1856+ def _signature_internal (obj , follow_wrapper_chains = True , skip_bound_arg = True ):
18561857
18571858 if not callable (obj ):
18581859 raise TypeError ('{!r} is not a callable object' .format (obj ))
18591860
18601861 if isinstance (obj , types .MethodType ):
18611862 # In this case we skip the first parameter of the underlying
18621863 # function (usually `self` or `cls`).
1863- sig = signature (obj .__func__ )
1864- return _signature_bound_method (sig )
1864+ sig = _signature_internal (obj .__func__ ,
1865+ follow_wrapper_chains ,
1866+ skip_bound_arg )
1867+ if skip_bound_arg :
1868+ return _signature_bound_method (sig )
1869+ else :
1870+ return sig
18651871
18661872 # Was this function wrapped by a decorator?
1867- obj = unwrap (obj , stop = (lambda f : hasattr (f , "__signature__" )))
1873+ if follow_wrapper_chains :
1874+ obj = unwrap (obj , stop = (lambda f : hasattr (f , "__signature__" )))
18681875
18691876 try :
18701877 sig = obj .__signature__
@@ -1887,7 +1894,9 @@ def signature(obj):
18871894 # (usually `self`, or `cls`) will not be passed
18881895 # automatically (as for boundmethods)
18891896
1890- wrapped_sig = signature (partialmethod .func )
1897+ wrapped_sig = _signature_internal (partialmethod .func ,
1898+ follow_wrapper_chains ,
1899+ skip_bound_arg )
18911900 sig = _signature_get_partial (wrapped_sig , partialmethod , (None ,))
18921901
18931902 first_wrapped_param = tuple (wrapped_sig .parameters .values ())[0 ]
@@ -1896,15 +1905,18 @@ def signature(obj):
18961905 return sig .replace (parameters = new_params )
18971906
18981907 if _signature_is_builtin (obj ):
1899- return Signature .from_builtin (obj )
1908+ return _signature_from_builtin (Signature , obj ,
1909+ skip_bound_arg = skip_bound_arg )
19001910
19011911 if isfunction (obj ) or _signature_is_functionlike (obj ):
19021912 # If it's a pure Python function, or an object that is duck type
19031913 # of a Python function (Cython functions, for instance), then:
19041914 return Signature .from_function (obj )
19051915
19061916 if isinstance (obj , functools .partial ):
1907- wrapped_sig = signature (obj .func )
1917+ wrapped_sig = _signature_internal (obj .func ,
1918+ follow_wrapper_chains ,
1919+ skip_bound_arg )
19081920 return _signature_get_partial (wrapped_sig , obj )
19091921
19101922 sig = None
@@ -1915,17 +1927,23 @@ def signature(obj):
19151927 # in its metaclass
19161928 call = _signature_get_user_defined_method (type (obj ), '__call__' )
19171929 if call is not None :
1918- sig = signature (call )
1930+ sig = _signature_internal (call ,
1931+ follow_wrapper_chains ,
1932+ skip_bound_arg )
19191933 else :
19201934 # Now we check if the 'obj' class has a '__new__' method
19211935 new = _signature_get_user_defined_method (obj , '__new__' )
19221936 if new is not None :
1923- sig = signature (new )
1937+ sig = _signature_internal (new ,
1938+ follow_wrapper_chains ,
1939+ skip_bound_arg )
19241940 else :
19251941 # Finally, we should have at least __init__ implemented
19261942 init = _signature_get_user_defined_method (obj , '__init__' )
19271943 if init is not None :
1928- sig = signature (init )
1944+ sig = _signature_internal (init ,
1945+ follow_wrapper_chains ,
1946+ skip_bound_arg )
19291947
19301948 if sig is None :
19311949 # At this point we know, that `obj` is a class, with no user-
@@ -1967,15 +1985,20 @@ def signature(obj):
19671985 call = _signature_get_user_defined_method (type (obj ), '__call__' )
19681986 if call is not None :
19691987 try :
1970- sig = signature (call )
1988+ sig = _signature_internal (call ,
1989+ follow_wrapper_chains ,
1990+ skip_bound_arg )
19711991 except ValueError as ex :
19721992 msg = 'no signature found for {!r}' .format (obj )
19731993 raise ValueError (msg ) from ex
19741994
19751995 if sig is not None :
19761996 # For classes and objects we skip the first parameter of their
19771997 # __call__, __new__, or __init__ methods
1978- return _signature_bound_method (sig )
1998+ if skip_bound_arg :
1999+ return _signature_bound_method (sig )
2000+ else :
2001+ return sig
19792002
19802003 if isinstance (obj , types .BuiltinFunctionType ):
19812004 # Raise a nicer error message for builtins
@@ -1984,6 +2007,10 @@ def signature(obj):
19842007
19852008 raise ValueError ('callable {!r} is not supported by signature' .format (obj ))
19862009
2010+ def signature (obj ):
2011+ '''Get a signature object for the passed callable.'''
2012+ return _signature_internal (obj )
2013+
19872014
19882015class _void :
19892016 '''A private marker - used in Parameter & Signature'''
@@ -2417,15 +2444,7 @@ def from_function(cls, func):
24172444
24182445 @classmethod
24192446 def from_builtin (cls , func ):
2420- if not _signature_is_builtin (func ):
2421- raise TypeError ("{!r} is not a Python builtin "
2422- "function" .format (func ))
2423-
2424- s = getattr (func , "__text_signature__" , None )
2425- if not s :
2426- raise ValueError ("no signature found for builtin {!r}" .format (func ))
2427-
2428- return _signature_fromstr (cls , func , s )
2447+ return _signature_from_builtin (cls , func )
24292448
24302449 @property
24312450 def parameters (self ):
0 commit comments