@@ -1945,15 +1945,17 @@ def _signature_get_user_defined_method(cls, method_name):
19451945 named ``method_name`` and returns it only if it is a
19461946 pure python function.
19471947 """
1948- try :
1949- meth = getattr (cls , method_name )
1950- except AttributeError :
1951- return
1948+ if method_name == '__new__' :
1949+ meth = getattr (cls , method_name , None )
19521950 else :
1953- if not isinstance (meth , _NonUserDefinedCallables ):
1954- # Once '__signature__' will be added to 'C'-level
1955- # callables, this check won't be necessary
1956- return meth
1951+ meth = getattr_static (cls , method_name , None )
1952+ if meth is None or isinstance (meth , _NonUserDefinedCallables ):
1953+ # Once '__signature__' will be added to 'C'-level
1954+ # callables, this check won't be necessary
1955+ return None
1956+ if method_name != '__new__' :
1957+ meth = _descriptor_get (meth , cls )
1958+ return meth
19571959
19581960
19591961def _signature_get_partial (wrapped_sig , partial , extra_args = ()):
@@ -2421,6 +2423,15 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
24212423 __validate_parameters__ = is_duck_function )
24222424
24232425
2426+ def _descriptor_get (descriptor , obj ):
2427+ if isclass (descriptor ):
2428+ return descriptor
2429+ get = getattr (type (descriptor ), '__get__' , _sentinel )
2430+ if get is _sentinel :
2431+ return descriptor
2432+ return get (descriptor , obj , type (obj ))
2433+
2434+
24242435def _signature_from_callable (obj , * ,
24252436 follow_wrapper_chains = True ,
24262437 skip_bound_arg = True ,
@@ -2521,96 +2532,72 @@ def _signature_from_callable(obj, *,
25212532 wrapped_sig = _get_signature_of (obj .func )
25222533 return _signature_get_partial (wrapped_sig , obj )
25232534
2524- sig = None
25252535 if isinstance (obj , type ):
25262536 # obj is a class or a metaclass
25272537
25282538 # First, let's see if it has an overloaded __call__ defined
25292539 # in its metaclass
25302540 call = _signature_get_user_defined_method (type (obj ), '__call__' )
25312541 if call is not None :
2532- sig = _get_signature_of (call )
2533- else :
2534- factory_method = None
2535- new = _signature_get_user_defined_method (obj , '__new__' )
2536- init = _signature_get_user_defined_method (obj , '__init__' )
2537-
2538- # Go through the MRO and see if any class has user-defined
2539- # pure Python __new__ or __init__ method
2540- for base in obj .__mro__ :
2541- # Now we check if the 'obj' class has an own '__new__' method
2542- if new is not None and '__new__' in base .__dict__ :
2543- factory_method = new
2544- break
2545- # or an own '__init__' method
2546- elif init is not None and '__init__' in base .__dict__ :
2547- factory_method = init
2548- break
2542+ return _get_signature_of (call )
25492543
2550- if factory_method is not None :
2551- sig = _get_signature_of (factory_method )
2552-
2553- if sig is None :
2554- # At this point we know, that `obj` is a class, with no user-
2555- # defined '__init__', '__new__', or class-level '__call__'
2556-
2557- for base in obj .__mro__ [:- 1 ]:
2558- # Since '__text_signature__' is implemented as a
2559- # descriptor that extracts text signature from the
2560- # class docstring, if 'obj' is derived from a builtin
2561- # class, its own '__text_signature__' may be 'None'.
2562- # Therefore, we go through the MRO (except the last
2563- # class in there, which is 'object') to find the first
2564- # class with non-empty text signature.
2565- try :
2566- text_sig = base .__text_signature__
2567- except AttributeError :
2568- pass
2569- else :
2570- if text_sig :
2571- # If 'base' class has a __text_signature__ attribute:
2572- # return a signature based on it
2573- return _signature_fromstr (sigcls , base , text_sig )
2574-
2575- # No '__text_signature__' was found for the 'obj' class.
2576- # Last option is to check if its '__init__' is
2577- # object.__init__ or type.__init__.
2578- if type not in obj .__mro__ :
2579- # We have a class (not metaclass), but no user-defined
2580- # __init__ or __new__ for it
2581- if (obj .__init__ is object .__init__ and
2582- obj .__new__ is object .__new__ ):
2583- # Return a signature of 'object' builtin.
2584- return sigcls .from_callable (object )
2585- else :
2586- raise ValueError (
2587- 'no signature found for builtin type {!r}' .format (obj ))
2544+ new = _signature_get_user_defined_method (obj , '__new__' )
2545+ init = _signature_get_user_defined_method (obj , '__init__' )
25882546
2589- elif not isinstance (obj , _NonUserDefinedCallables ):
2590- # An object with __call__
2591- # We also check that the 'obj' is not an instance of
2592- # types.WrapperDescriptorType or types.MethodWrapperType to avoid
2593- # infinite recursion (and even potential segfault)
2594- call = _signature_get_user_defined_method (type (obj ), '__call__' )
2595- if call is not None :
2547+ # Go through the MRO and see if any class has user-defined
2548+ # pure Python __new__ or __init__ method
2549+ for base in obj .__mro__ :
2550+ # Now we check if the 'obj' class has an own '__new__' method
2551+ if new is not None and '__new__' in base .__dict__ :
2552+ sig = _get_signature_of (new )
2553+ if skip_bound_arg :
2554+ sig = _signature_bound_method (sig )
2555+ return sig
2556+ # or an own '__init__' method
2557+ elif init is not None and '__init__' in base .__dict__ :
2558+ return _get_signature_of (init )
2559+
2560+ # At this point we know, that `obj` is a class, with no user-
2561+ # defined '__init__', '__new__', or class-level '__call__'
2562+
2563+ for base in obj .__mro__ [:- 1 ]:
2564+ # Since '__text_signature__' is implemented as a
2565+ # descriptor that extracts text signature from the
2566+ # class docstring, if 'obj' is derived from a builtin
2567+ # class, its own '__text_signature__' may be 'None'.
2568+ # Therefore, we go through the MRO (except the last
2569+ # class in there, which is 'object') to find the first
2570+ # class with non-empty text signature.
25962571 try :
2597- sig = _get_signature_of (call )
2598- except ValueError as ex :
2599- msg = 'no signature found for {!r}' .format (obj )
2600- raise ValueError (msg ) from ex
2601-
2602- if sig is not None :
2603- # For classes and objects we skip the first parameter of their
2604- # __call__, __new__, or __init__ methods
2605- if skip_bound_arg :
2606- return _signature_bound_method (sig )
2607- else :
2608- return sig
2572+ text_sig = base .__text_signature__
2573+ except AttributeError :
2574+ pass
2575+ else :
2576+ if text_sig :
2577+ # If 'base' class has a __text_signature__ attribute:
2578+ # return a signature based on it
2579+ return _signature_fromstr (sigcls , base , text_sig )
2580+
2581+ # No '__text_signature__' was found for the 'obj' class.
2582+ # Last option is to check if its '__init__' is
2583+ # object.__init__ or type.__init__.
2584+ if type not in obj .__mro__ :
2585+ # We have a class (not metaclass), but no user-defined
2586+ # __init__ or __new__ for it
2587+ if (obj .__init__ is object .__init__ and
2588+ obj .__new__ is object .__new__ ):
2589+ # Return a signature of 'object' builtin.
2590+ return sigcls .from_callable (object )
2591+ else :
2592+ raise ValueError (
2593+ 'no signature found for builtin type {!r}' .format (obj ))
26092594
2610- if isinstance (obj , types .BuiltinFunctionType ):
2611- # Raise a nicer error message for builtins
2612- msg = 'no signature found for builtin function {!r}' .format (obj )
2613- raise ValueError (msg )
2595+ else :
2596+ # An object with __call__
2597+ call = getattr_static (type (obj ), '__call__' , None )
2598+ if call is not None :
2599+ call = _descriptor_get (call , obj )
2600+ return _get_signature_of (call )
26142601
26152602 raise ValueError ('callable {!r} is not supported by signature' .format (obj ))
26162603
0 commit comments