@@ -2039,15 +2039,17 @@ def _signature_get_user_defined_method(cls, method_name):
2039
2039
named ``method_name`` and returns it only if it is a
2040
2040
pure python function.
2041
2041
"""
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 )
2046
2044
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
2051
2053
2052
2054
2053
2055
def _signature_get_partial (wrapped_sig , partial , extra_args = ()):
@@ -2492,6 +2494,15 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
2492
2494
__validate_parameters__ = is_duck_function )
2493
2495
2494
2496
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
+
2495
2506
def _signature_from_callable (obj , * ,
2496
2507
follow_wrapper_chains = True ,
2497
2508
skip_bound_arg = True ,
@@ -2600,96 +2611,72 @@ def _signature_from_callable(obj, *,
2600
2611
wrapped_sig = _get_signature_of (obj .func )
2601
2612
return _signature_get_partial (wrapped_sig , obj )
2602
2613
2603
- sig = None
2604
2614
if isinstance (obj , type ):
2605
2615
# obj is a class or a metaclass
2606
2616
2607
2617
# First, let's see if it has an overloaded __call__ defined
2608
2618
# in its metaclass
2609
2619
call = _signature_get_user_defined_method (type (obj ), '__call__' )
2610
2620
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 )
2628
2622
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__' )
2667
2625
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.
2675
2650
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 ))
2688
2673
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 )
2693
2680
2694
2681
raise ValueError ('callable {!r} is not supported by signature' .format (obj ))
2695
2682
0 commit comments