Skip to content

Commit 32910f3

Browse files
committed
Tests and fixes for staticmethod
1 parent c50d344 commit 32910f3

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

Lib/functools.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -888,15 +888,15 @@ def _find_impl(cls, registry):
888888
match = t
889889
return registry.get(match)
890890

891-
def _get_dispatch_param(func, *, _dispatchmethod=False):
891+
def _get_dispatch_param(func, *, _insideclass=False):
892892
"""Finds the first positional and user-specified parameter in a callable
893893
or descriptor.
894894
895895
Used by singledispatch for registration by type annotation of the parameter.
896896
"""
897897
# Fast path for typical callables and descriptors.
898898
# idx is 0 when singledispatch() and 1 when singledispatchmethod()
899-
idx = _dispatchmethod
899+
idx = _insideclass
900900
if isinstance(func, staticmethod):
901901
idx = 0
902902
func = func.__func__
@@ -965,7 +965,7 @@ def _is_valid_dispatch_type(cls):
965965
return (isinstance(cls, UnionType) and
966966
all(isinstance(arg, type) for arg in cls.__args__))
967967

968-
def register(cls, func=None, _dispatchmethod=False):
968+
def register(cls, func=None, _insideclass=False):
969969
"""generic_func.register(cls, func) -> func
970970
971971
Registers a new implementation for the given *cls* on a *generic_func*.
@@ -990,7 +990,7 @@ def register(cls, func=None, _dispatchmethod=False):
990990
)
991991
func = cls
992992

993-
argname = _get_dispatch_param(func, _dispatchmethod=_dispatchmethod)
993+
argname = _get_dispatch_param(func, _insideclass=_insideclass)
994994
if argname is None:
995995
raise TypeError(
996996
f"Invalid first argument to `register()`: {func!r} "
@@ -1069,12 +1069,12 @@ def __init__(self, func):
10691069
self.dispatcher = singledispatch(func)
10701070
self.func = func
10711071

1072-
def register(self, cls, method=None):
1072+
def register(self, cls, method=None, _insideclass=True):
10731073
"""generic_method.register(cls, func) -> func
10741074
10751075
Registers a new implementation for the given *cls* on a *generic_method*.
10761076
"""
1077-
return self.dispatcher.register(cls, func=method, _dispatchmethod=True)
1077+
return self.dispatcher.register(cls, func=method, _insideclass=_insideclass)
10781078

10791079
def __get__(self, obj, cls=None):
10801080
return _singledispatchmethod_get(self, obj, cls)
@@ -1149,7 +1149,7 @@ def __wrapped__(self):
11491149

11501150
@property
11511151
def register(self):
1152-
return self._unbound.register
1152+
return partial(self._unbound.register, _insideclass=False)
11531153

11541154

11551155
################################################################################

Lib/test/test_functools.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2993,18 +2993,33 @@ def _(arg: int):
29932993
return isinstance(arg, int)
29942994
@t.register
29952995
@staticmethod
2996-
def _(arg: str):
2996+
def _(arg: str, /):
29972997
return isinstance(arg, str)
29982998
@t.register
29992999
@wrapper_decorator
30003000
@staticmethod
3001-
def _(arg: bytes):
3001+
def _(arg: bytes) -> bool:
30023002
return isinstance(arg, bytes)
3003+
@wrapper_decorator
3004+
@staticmethod
3005+
def outer1(arg: complex):
3006+
return isinstance(arg, complex)
3007+
@wrapper_decorator
3008+
@staticmethod
3009+
def outer2(arg: bool):
3010+
return isinstance(arg, bool)
3011+
3012+
A.t.register(staticmethod(A.outer1))
30033013
a = A()
3014+
a.t.register(staticmethod(a.outer2))
30043015

30053016
self.assertTrue(A.t(0))
30063017
self.assertTrue(A.t(''))
30073018
self.assertEqual(A.t(0.0), 0.0)
3019+
self.assertTrue(A.t(0j))
3020+
self.assertTrue(a.t(42j))
3021+
self.assertTrue(A.t(True))
3022+
self.assertTrue(a.t(False))
30083023

30093024
def test_classmethod_type_ann_register(self):
30103025
def wrapper_decorator(func):

0 commit comments

Comments
 (0)