@@ -2039,15 +2039,17 @@ def _signature_get_user_defined_method(cls, method_name):
20392039 named ``method_name`` and returns it only if it is a
20402040 pure python function.
20412041 """
2042- try :
2043- meth = getattr (cls , method_name )
2044- except AttributeError :
2045- return
2042+ if method_name == '__new__' :
2043+ meth = getattr (cls , method_name , None )
20462044 else :
2047- if not isinstance (meth , _NonUserDefinedCallables ):
2048- # Once '__signature__' will be added to 'C'-level
2049- # callables, this check won't be necessary
2050- return meth
2045+ meth = getattr_static (cls , method_name , None )
2046+ if meth is None or isinstance (meth , _NonUserDefinedCallables ):
2047+ # Once '__signature__' will be added to 'C'-level
2048+ # callables, this check won't be necessary
2049+ return None
2050+ if method_name != '__new__' :
2051+ meth = _descriptor_get (meth , cls )
2052+ return meth
20512053
20522054
20532055def _signature_get_partial (wrapped_sig , partial , extra_args = ()):
@@ -2492,6 +2494,15 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
24922494 __validate_parameters__ = is_duck_function )
24932495
24942496
2497+ def _descriptor_get (descriptor , obj ):
2498+ if isclass (descriptor ):
2499+ return descriptor
2500+ get = getattr (type (descriptor ), '__get__' , _sentinel )
2501+ if get is _sentinel :
2502+ return descriptor
2503+ return get (descriptor , obj , type (obj ))
2504+
2505+
24952506def _signature_from_callable (obj , * ,
24962507 follow_wrapper_chains = True ,
24972508 skip_bound_arg = True ,
@@ -2600,96 +2611,72 @@ def _signature_from_callable(obj, *,
26002611 wrapped_sig = _get_signature_of (obj .func )
26012612 return _signature_get_partial (wrapped_sig , obj )
26022613
2603- sig = None
26042614 if isinstance (obj , type ):
26052615 # obj is a class or a metaclass
26062616
26072617 # First, let's see if it has an overloaded __call__ defined
26082618 # in its metaclass
26092619 call = _signature_get_user_defined_method (type (obj ), '__call__' )
26102620 if call is not None :
2611- sig = _get_signature_of (call )
2612- else :
2613- factory_method = None
2614- new = _signature_get_user_defined_method (obj , '__new__' )
2615- init = _signature_get_user_defined_method (obj , '__init__' )
2616-
2617- # Go through the MRO and see if any class has user-defined
2618- # pure Python __new__ or __init__ method
2619- for base in obj .__mro__ :
2620- # Now we check if the 'obj' class has an own '__new__' method
2621- if new is not None and '__new__' in base .__dict__ :
2622- factory_method = new
2623- break
2624- # or an own '__init__' method
2625- elif init is not None and '__init__' in base .__dict__ :
2626- factory_method = init
2627- break
2621+ return _get_signature_of (call )
26282622
2629- if factory_method is not None :
2630- sig = _get_signature_of (factory_method )
2631-
2632- if sig is None :
2633- # At this point we know, that `obj` is a class, with no user-
2634- # defined '__init__', '__new__', or class-level '__call__'
2635-
2636- for base in obj .__mro__ [:- 1 ]:
2637- # Since '__text_signature__' is implemented as a
2638- # descriptor that extracts text signature from the
2639- # class docstring, if 'obj' is derived from a builtin
2640- # class, its own '__text_signature__' may be 'None'.
2641- # Therefore, we go through the MRO (except the last
2642- # class in there, which is 'object') to find the first
2643- # class with non-empty text signature.
2644- try :
2645- text_sig = base .__text_signature__
2646- except AttributeError :
2647- pass
2648- else :
2649- if text_sig :
2650- # If 'base' class has a __text_signature__ attribute:
2651- # return a signature based on it
2652- return _signature_fromstr (sigcls , base , text_sig )
2653-
2654- # No '__text_signature__' was found for the 'obj' class.
2655- # Last option is to check if its '__init__' is
2656- # object.__init__ or type.__init__.
2657- if type not in obj .__mro__ :
2658- # We have a class (not metaclass), but no user-defined
2659- # __init__ or __new__ for it
2660- if (obj .__init__ is object .__init__ and
2661- obj .__new__ is object .__new__ ):
2662- # Return a signature of 'object' builtin.
2663- return sigcls .from_callable (object )
2664- else :
2665- raise ValueError (
2666- 'no signature found for builtin type {!r}' .format (obj ))
2623+ new = _signature_get_user_defined_method (obj , '__new__' )
2624+ init = _signature_get_user_defined_method (obj , '__init__' )
26672625
2668- elif not isinstance (obj , _NonUserDefinedCallables ):
2669- # An object with __call__
2670- # We also check that the 'obj' is not an instance of
2671- # types.WrapperDescriptorType or types.MethodWrapperType to avoid
2672- # infinite recursion (and even potential segfault)
2673- call = _signature_get_user_defined_method (type (obj ), '__call__' )
2674- if call is not None :
2626+ # Go through the MRO and see if any class has user-defined
2627+ # pure Python __new__ or __init__ method
2628+ for base in obj .__mro__ :
2629+ # Now we check if the 'obj' class has an own '__new__' method
2630+ if new is not None and '__new__' in base .__dict__ :
2631+ sig = _get_signature_of (new )
2632+ if skip_bound_arg :
2633+ sig = _signature_bound_method (sig )
2634+ return sig
2635+ # or an own '__init__' method
2636+ elif init is not None and '__init__' in base .__dict__ :
2637+ return _get_signature_of (init )
2638+
2639+ # At this point we know, that `obj` is a class, with no user-
2640+ # defined '__init__', '__new__', or class-level '__call__'
2641+
2642+ for base in obj .__mro__ [:- 1 ]:
2643+ # Since '__text_signature__' is implemented as a
2644+ # descriptor that extracts text signature from the
2645+ # class docstring, if 'obj' is derived from a builtin
2646+ # class, its own '__text_signature__' may be 'None'.
2647+ # Therefore, we go through the MRO (except the last
2648+ # class in there, which is 'object') to find the first
2649+ # class with non-empty text signature.
26752650 try :
2676- sig = _get_signature_of (call )
2677- except ValueError as ex :
2678- msg = 'no signature found for {!r}' .format (obj )
2679- raise ValueError (msg ) from ex
2680-
2681- if sig is not None :
2682- # For classes and objects we skip the first parameter of their
2683- # __call__, __new__, or __init__ methods
2684- if skip_bound_arg :
2685- return _signature_bound_method (sig )
2686- else :
2687- return sig
2651+ text_sig = base .__text_signature__
2652+ except AttributeError :
2653+ pass
2654+ else :
2655+ if text_sig :
2656+ # If 'base' class has a __text_signature__ attribute:
2657+ # return a signature based on it
2658+ return _signature_fromstr (sigcls , base , text_sig )
2659+
2660+ # No '__text_signature__' was found for the 'obj' class.
2661+ # Last option is to check if its '__init__' is
2662+ # object.__init__ or type.__init__.
2663+ if type not in obj .__mro__ :
2664+ # We have a class (not metaclass), but no user-defined
2665+ # __init__ or __new__ for it
2666+ if (obj .__init__ is object .__init__ and
2667+ obj .__new__ is object .__new__ ):
2668+ # Return a signature of 'object' builtin.
2669+ return sigcls .from_callable (object )
2670+ else :
2671+ raise ValueError (
2672+ 'no signature found for builtin type {!r}' .format (obj ))
26882673
2689- if isinstance (obj , types .BuiltinFunctionType ):
2690- # Raise a nicer error message for builtins
2691- msg = 'no signature found for builtin function {!r}' .format (obj )
2692- raise ValueError (msg )
2674+ else :
2675+ # An object with __call__
2676+ call = getattr_static (type (obj ), '__call__' , None )
2677+ if call is not None :
2678+ call = _descriptor_get (call , obj )
2679+ return _get_signature_of (call )
26932680
26942681 raise ValueError ('callable {!r} is not supported by signature' .format (obj ))
26952682
0 commit comments