@@ -2003,15 +2003,17 @@ def _signature_get_user_defined_method(cls, method_name):
2003
2003
named ``method_name`` and returns it only if it is a
2004
2004
pure python function.
2005
2005
"""
2006
- try :
2007
- meth = getattr (cls , method_name )
2008
- except AttributeError :
2009
- return
2006
+ if method_name == '__new__' :
2007
+ meth = getattr (cls , method_name , None )
2010
2008
else :
2011
- if not isinstance (meth , _NonUserDefinedCallables ):
2012
- # Once '__signature__' will be added to 'C'-level
2013
- # callables, this check won't be necessary
2014
- return meth
2009
+ meth = getattr_static (cls , method_name , None )
2010
+ if meth is None or isinstance (meth , _NonUserDefinedCallables ):
2011
+ # Once '__signature__' will be added to 'C'-level
2012
+ # callables, this check won't be necessary
2013
+ return None
2014
+ if method_name != '__new__' :
2015
+ meth = _descriptor_get (meth , cls )
2016
+ return meth
2015
2017
2016
2018
2017
2019
def _signature_get_partial (wrapped_sig , partial , extra_args = ()):
@@ -2456,6 +2458,15 @@ def _signature_from_function(cls, func, skip_bound_arg=True,
2456
2458
__validate_parameters__ = is_duck_function )
2457
2459
2458
2460
2461
+ def _descriptor_get (descriptor , obj ):
2462
+ if isclass (descriptor ):
2463
+ return descriptor
2464
+ get = getattr (type (descriptor ), '__get__' , _sentinel )
2465
+ if get is _sentinel :
2466
+ return descriptor
2467
+ return get (descriptor , obj , type (obj ))
2468
+
2469
+
2459
2470
def _signature_from_callable (obj , * ,
2460
2471
follow_wrapper_chains = True ,
2461
2472
skip_bound_arg = True ,
@@ -2564,96 +2575,72 @@ def _signature_from_callable(obj, *,
2564
2575
wrapped_sig = _get_signature_of (obj .func )
2565
2576
return _signature_get_partial (wrapped_sig , obj )
2566
2577
2567
- sig = None
2568
2578
if isinstance (obj , type ):
2569
2579
# obj is a class or a metaclass
2570
2580
2571
2581
# First, let's see if it has an overloaded __call__ defined
2572
2582
# in its metaclass
2573
2583
call = _signature_get_user_defined_method (type (obj ), '__call__' )
2574
2584
if call is not None :
2575
- sig = _get_signature_of (call )
2576
- else :
2577
- factory_method = None
2578
- new = _signature_get_user_defined_method (obj , '__new__' )
2579
- init = _signature_get_user_defined_method (obj , '__init__' )
2580
-
2581
- # Go through the MRO and see if any class has user-defined
2582
- # pure Python __new__ or __init__ method
2583
- for base in obj .__mro__ :
2584
- # Now we check if the 'obj' class has an own '__new__' method
2585
- if new is not None and '__new__' in base .__dict__ :
2586
- factory_method = new
2587
- break
2588
- # or an own '__init__' method
2589
- elif init is not None and '__init__' in base .__dict__ :
2590
- factory_method = init
2591
- break
2585
+ return _get_signature_of (call )
2592
2586
2593
- if factory_method is not None :
2594
- sig = _get_signature_of (factory_method )
2595
-
2596
- if sig is None :
2597
- # At this point we know, that `obj` is a class, with no user-
2598
- # defined '__init__', '__new__', or class-level '__call__'
2599
-
2600
- for base in obj .__mro__ [:- 1 ]:
2601
- # Since '__text_signature__' is implemented as a
2602
- # descriptor that extracts text signature from the
2603
- # class docstring, if 'obj' is derived from a builtin
2604
- # class, its own '__text_signature__' may be 'None'.
2605
- # Therefore, we go through the MRO (except the last
2606
- # class in there, which is 'object') to find the first
2607
- # class with non-empty text signature.
2608
- try :
2609
- text_sig = base .__text_signature__
2610
- except AttributeError :
2611
- pass
2612
- else :
2613
- if text_sig :
2614
- # If 'base' class has a __text_signature__ attribute:
2615
- # return a signature based on it
2616
- return _signature_fromstr (sigcls , base , text_sig )
2617
-
2618
- # No '__text_signature__' was found for the 'obj' class.
2619
- # Last option is to check if its '__init__' is
2620
- # object.__init__ or type.__init__.
2621
- if type not in obj .__mro__ :
2622
- # We have a class (not metaclass), but no user-defined
2623
- # __init__ or __new__ for it
2624
- if (obj .__init__ is object .__init__ and
2625
- obj .__new__ is object .__new__ ):
2626
- # Return a signature of 'object' builtin.
2627
- return sigcls .from_callable (object )
2628
- else :
2629
- raise ValueError (
2630
- 'no signature found for builtin type {!r}' .format (obj ))
2587
+ new = _signature_get_user_defined_method (obj , '__new__' )
2588
+ init = _signature_get_user_defined_method (obj , '__init__' )
2631
2589
2632
- elif not isinstance (obj , _NonUserDefinedCallables ):
2633
- # An object with __call__
2634
- # We also check that the 'obj' is not an instance of
2635
- # types.WrapperDescriptorType or types.MethodWrapperType to avoid
2636
- # infinite recursion (and even potential segfault)
2637
- call = _signature_get_user_defined_method (type (obj ), '__call__' )
2638
- if call is not None :
2590
+ # Go through the MRO and see if any class has user-defined
2591
+ # pure Python __new__ or __init__ method
2592
+ for base in obj .__mro__ :
2593
+ # Now we check if the 'obj' class has an own '__new__' method
2594
+ if new is not None and '__new__' in base .__dict__ :
2595
+ sig = _get_signature_of (new )
2596
+ if skip_bound_arg :
2597
+ sig = _signature_bound_method (sig )
2598
+ return sig
2599
+ # or an own '__init__' method
2600
+ elif init is not None and '__init__' in base .__dict__ :
2601
+ return _get_signature_of (init )
2602
+
2603
+ # At this point we know, that `obj` is a class, with no user-
2604
+ # defined '__init__', '__new__', or class-level '__call__'
2605
+
2606
+ for base in obj .__mro__ [:- 1 ]:
2607
+ # Since '__text_signature__' is implemented as a
2608
+ # descriptor that extracts text signature from the
2609
+ # class docstring, if 'obj' is derived from a builtin
2610
+ # class, its own '__text_signature__' may be 'None'.
2611
+ # Therefore, we go through the MRO (except the last
2612
+ # class in there, which is 'object') to find the first
2613
+ # class with non-empty text signature.
2639
2614
try :
2640
- sig = _get_signature_of (call )
2641
- except ValueError as ex :
2642
- msg = 'no signature found for {!r}' .format (obj )
2643
- raise ValueError (msg ) from ex
2644
-
2645
- if sig is not None :
2646
- # For classes and objects we skip the first parameter of their
2647
- # __call__, __new__, or __init__ methods
2648
- if skip_bound_arg :
2649
- return _signature_bound_method (sig )
2650
- else :
2651
- return sig
2615
+ text_sig = base .__text_signature__
2616
+ except AttributeError :
2617
+ pass
2618
+ else :
2619
+ if text_sig :
2620
+ # If 'base' class has a __text_signature__ attribute:
2621
+ # return a signature based on it
2622
+ return _signature_fromstr (sigcls , base , text_sig )
2623
+
2624
+ # No '__text_signature__' was found for the 'obj' class.
2625
+ # Last option is to check if its '__init__' is
2626
+ # object.__init__ or type.__init__.
2627
+ if type not in obj .__mro__ :
2628
+ # We have a class (not metaclass), but no user-defined
2629
+ # __init__ or __new__ for it
2630
+ if (obj .__init__ is object .__init__ and
2631
+ obj .__new__ is object .__new__ ):
2632
+ # Return a signature of 'object' builtin.
2633
+ return sigcls .from_callable (object )
2634
+ else :
2635
+ raise ValueError (
2636
+ 'no signature found for builtin type {!r}' .format (obj ))
2652
2637
2653
- if isinstance (obj , types .BuiltinFunctionType ):
2654
- # Raise a nicer error message for builtins
2655
- msg = 'no signature found for builtin function {!r}' .format (obj )
2656
- raise ValueError (msg )
2638
+ else :
2639
+ # An object with __call__
2640
+ call = getattr_static (type (obj ), '__call__' , None )
2641
+ if call is not None :
2642
+ call = _descriptor_get (call , obj )
2643
+ return _get_signature_of (call )
2657
2644
2658
2645
raise ValueError ('callable {!r} is not supported by signature' .format (obj ))
2659
2646
0 commit comments