diff options
Diffstat (limited to 'Lib/functools.py')
-rw-r--r-- | Lib/functools.py | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/Lib/functools.py b/Lib/functools.py index c8b79c2..d5f4393 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -11,7 +11,7 @@ __all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial', - 'partialmethod', 'singledispatch'] + 'partialmethod', 'singledispatch', 'singledispatchmethod'] try: from _functools import reduce @@ -826,3 +826,40 @@ def singledispatch(func): wrapper._clear_cache = dispatch_cache.clear update_wrapper(wrapper, func) return wrapper + + +# Descriptor version +class singledispatchmethod: + """Single-dispatch generic method descriptor. + + Supports wrapping existing descriptors and handles non-descriptor + callables as instance methods. + """ + + def __init__(self, func): + if not callable(func) and not hasattr(func, "__get__"): + raise TypeError(f"{func!r} is not callable or a descriptor") + + self.dispatcher = singledispatch(func) + self.func = func + + def register(self, cls, method=None): + """generic_method.register(cls, func) -> func + + Registers a new implementation for the given *cls* on a *generic_method*. + """ + return self.dispatcher.register(cls, func=method) + + def __get__(self, obj, cls): + def _method(*args, **kwargs): + method = self.dispatcher.dispatch(args[0].__class__) + return method.__get__(obj, cls)(*args, **kwargs) + + _method.__isabstractmethod__ = self.__isabstractmethod__ + _method.register = self.register + update_wrapper(_method, self.func) + return _method + + @property + def __isabstractmethod__(self): + return getattr(self.func, '__isabstractmethod__', False) |