Skip to content

Instantly share code, notes, and snippets.

@ethanhs
Created April 25, 2018 03:35
Show Gist options
  • Save ethanhs/3306e8767eda080efefdeb0f3a7a91dc to your computer and use it in GitHub Desktop.
Save ethanhs/3306e8767eda080efefdeb0f3a7a91dc to your computer and use it in GitHub Desktop.
`functools.singledispatchmethod` for use before 3.8
from functools import singledispatch, update_wrapper
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment