|
19 | 19 | # import weakref # Deferred to single_dispatch() |
20 | 20 | from operator import itemgetter |
21 | 21 | from reprlib import recursive_repr |
22 | | -from types import GenericAlias, MethodType, MappingProxyType, UnionType |
| 22 | +from types import FunctionType, GenericAlias, MethodType, MappingProxyType, UnionType |
23 | 23 | from _thread import RLock |
24 | 24 |
|
25 | 25 | ################################################################################ |
@@ -1060,6 +1060,11 @@ def __init__(self, unbound, obj, cls): |
1060 | 1060 | # Set instance attributes which cannot be handled in __getattr__() |
1061 | 1061 | # because they conflict with type descriptors. |
1062 | 1062 | func = unbound.func |
| 1063 | + |
| 1064 | + # Dispatch on the second argument if a generic method turns into |
| 1065 | + # a bound method on instance-level access. See GH-143535. |
| 1066 | + self._dispatch_arg_index = 1 if obj is None and isinstance(func, FunctionType) else 0 |
| 1067 | + |
1063 | 1068 | try: |
1064 | 1069 | self.__module__ = func.__module__ |
1065 | 1070 | except AttributeError: |
@@ -1088,9 +1093,22 @@ def __call__(self, /, *args, **kwargs): |
1088 | 1093 | 'singledispatchmethod method') |
1089 | 1094 | raise TypeError(f'{funcname} requires at least ' |
1090 | 1095 | '1 positional argument') |
1091 | | - method = self._dispatch(args[0].__class__) |
| 1096 | + method = self._dispatch(args[self._dispatch_arg_index].__class__) |
| 1097 | + |
1092 | 1098 | if hasattr(method, "__get__"): |
| 1099 | + # If the method is a descriptor, it might be necessary |
| 1100 | + # to drop the first argument before calling |
| 1101 | + # as it can be no longer expected after descriptor access. |
| 1102 | + skip_bound_arg = False |
| 1103 | + if isinstance(method, staticmethod): |
| 1104 | + skip_bound_arg = self._dispatch_arg_index == 1 |
| 1105 | + |
1093 | 1106 | method = method.__get__(self._obj, self._cls) |
| 1107 | + if isinstance(method, MethodType): |
| 1108 | + skip_bound_arg = self._dispatch_arg_index == 1 |
| 1109 | + |
| 1110 | + if skip_bound_arg: |
| 1111 | + return method(*args[1:], **kwargs) |
1094 | 1112 | return method(*args, **kwargs) |
1095 | 1113 |
|
1096 | 1114 | def __getattr__(self, name): |
|
0 commit comments