@@ -116,7 +116,7 @@ def __init__(
116116 self .stub_desc = stub_desc or str (getattr (stub_object , "type" , stub_object ))
117117
118118 if runtime_desc is None :
119- runtime_sig = safe_inspect_signature (runtime_object , object_path )
119+ runtime_sig = safe_inspect_signature (runtime_object )
120120 if runtime_sig is None :
121121 self .runtime_desc = _truncate (repr (runtime_object ), 100 )
122122 else :
@@ -837,6 +837,7 @@ def from_overloadedfuncdef(stub: nodes.OverloadedFuncDef) -> Signature[nodes.Arg
837837 or arg .pos_only
838838 or assume_positional_only
839839 or arg .variable .name .strip ("_" ) == "self"
840+ or (index == 0 and arg .variable .name .strip ("_" ) == "cls" )
840841 else arg .variable .name
841842 )
842843 all_args .setdefault (name , []).append ((arg , index ))
@@ -907,6 +908,7 @@ def _verify_signature(
907908 and not stub_arg .pos_only
908909 and not stub_arg .variable .name .startswith ("__" )
909910 and stub_arg .variable .name .strip ("_" ) != "self"
911+ and stub_arg .variable .name .strip ("_" ) != "cls"
910912 and not is_dunder (function_name , exclude_special = True ) # noisy for dunder methods
911913 ):
912914 yield (
@@ -917,6 +919,7 @@ def _verify_signature(
917919 runtime_arg .kind != inspect .Parameter .POSITIONAL_ONLY
918920 and (stub_arg .pos_only or stub_arg .variable .name .startswith ("__" ))
919921 and stub_arg .variable .name .strip ("_" ) != "self"
922+ and stub_arg .variable .name .strip ("_" ) != "cls"
920923 and not is_dunder (function_name , exclude_special = True ) # noisy for dunder methods
921924 ):
922925 yield (
@@ -1036,7 +1039,7 @@ def verify_funcitem(
10361039 for message in _verify_static_class_methods (stub , runtime , static_runtime , object_path ):
10371040 yield Error (object_path , "is inconsistent, " + message , stub , runtime )
10381041
1039- signature = safe_inspect_signature (runtime , object_path )
1042+ signature = safe_inspect_signature (runtime )
10401043 runtime_is_coroutine = inspect .iscoroutinefunction (runtime )
10411044
10421045 if signature :
@@ -1164,7 +1167,7 @@ def verify_overloadedfuncdef(
11641167 # TODO: Should call _verify_final_method here,
11651168 # but overloaded final methods in stubs cause a stubtest crash: see #14950
11661169
1167- signature = safe_inspect_signature (runtime , object_path )
1170+ signature = safe_inspect_signature (runtime )
11681171 if not signature :
11691172 return
11701173
@@ -1526,9 +1529,7 @@ def is_read_only_property(runtime: object) -> bool:
15261529 return isinstance (runtime , property ) and runtime .fset is None
15271530
15281531
1529- def safe_inspect_signature (
1530- runtime : Any , object_path : list [str ] | None = None
1531- ) -> inspect .Signature | None :
1532+ def safe_inspect_signature (runtime : Any ) -> inspect .Signature | None :
15321533 if (
15331534 hasattr (runtime , "__name__" )
15341535 and runtime .__name__ == "__init__"
@@ -1539,38 +1540,48 @@ def safe_inspect_signature(
15391540 and runtime .__objclass__ .__text_signature__ is not None
15401541 ):
15411542 # This is an __init__ method with the generic C-class signature.
1542- # In this case, the underlying class usually has a better signature,
1543+ # In this case, the underlying class often has a better signature,
15431544 # which we can convert into an __init__ signature by adding in the
15441545 # self parameter.
1545- runtime_objclass = None
1546- if runtime .__objclass__ is object :
1547- # When __objclass__ is object, use the object_path to look up
1548- # the actual class that this __init__ method came from.
1549- if object_path :
1550- module_name = "." .join (object_path [:- 2 ])
1551- module = silent_import_module (module_name )
1552- if module :
1553- runtime_objclass = getattr (module , object_path [- 2 ], None )
1554- if not (
1555- runtime_objclass is not None
1556- and hasattr (runtime_objclass , "__text_signature__" )
1557- and runtime_objclass .__text_signature__ is not None
1558- ):
1559- runtime_objclass = None
1560- else :
1561- runtime_objclass = runtime .__objclass__
1546+ try :
1547+ s = inspect .signature (runtime .__objclass__ )
1548+
1549+ parameter_kind = inspect .Parameter .POSITIONAL_OR_KEYWORD
1550+ if s .parameters :
1551+ first_parameter = next (iter (s .parameters .values ()))
1552+ if first_parameter .kind == inspect .Parameter .POSITIONAL_ONLY :
1553+ parameter_kind = inspect .Parameter .POSITIONAL_ONLY
1554+ return s .replace (
1555+ parameters = [inspect .Parameter ("self" , parameter_kind ), * s .parameters .values ()]
1556+ )
1557+ except Exception :
1558+ pass
15621559
1563- if runtime_objclass is not None :
1564- try :
1565- s = inspect .signature (runtime_objclass )
1566- return s .replace (
1567- parameters = [
1568- inspect .Parameter ("self" , inspect .Parameter .POSITIONAL_OR_KEYWORD ),
1569- * s .parameters .values (),
1570- ]
1571- )
1572- except Exception :
1573- pass
1560+ if (
1561+ hasattr (runtime , "__name__" )
1562+ and runtime .__name__ == "__new__"
1563+ and hasattr (runtime , "__text_signature__" )
1564+ and runtime .__text_signature__ == "($type, *args, **kwargs)"
1565+ and hasattr (runtime , "__self__" )
1566+ and hasattr (runtime .__self__ , "__text_signature__" )
1567+ and runtime .__self__ .__text_signature__ is not None
1568+ ):
1569+ # This is a __new__ method with the generic C-class signature.
1570+ # In this case, the underlying class often has a better signature,
1571+ # which we can convert into a __new__ signature by adding in the
1572+ # cls parameter.
1573+ try :
1574+ s = inspect .signature (runtime .__self__ )
1575+ parameter_kind = inspect .Parameter .POSITIONAL_OR_KEYWORD
1576+ if s .parameters :
1577+ first_parameter = next (iter (s .parameters .values ()))
1578+ if first_parameter .kind == inspect .Parameter .POSITIONAL_ONLY :
1579+ parameter_kind = inspect .Parameter .POSITIONAL_ONLY
1580+ return s .replace (
1581+ parameters = [inspect .Parameter ("cls" , parameter_kind ), * s .parameters .values ()]
1582+ )
1583+ except Exception :
1584+ pass
15741585
15751586 try :
15761587 try :
0 commit comments