"""This is version 0.7 of Philip J. Eby's simplegeneric module (http://pypi.python.org/pypi/simplegeneric), patched to work with Python 3, which doesn't support old-style classes. """ #Name: simplegeneric #Version: 0.7 #Summary: Simple generic functions (similar to Python's own len(), pickle.dump(), etc.) #Home-page: http://pypi.python.org/pypi/simplegeneric #Author: Phillip J. Eby #Author-email: peak@eby-sarna.com #License: PSF or ZPL __all__ = ["generic"] try: from types import ClassType, InstanceType except ImportError: classtypes = type else: classtypes = type, ClassType def generic(func): """Create a simple generic function""" _sentinel = object() def _by_class(*args, **kw): cls = args[0].__class__ for t in type(cls.__name__, (cls,object), {}).__mro__: f = _gbt(t, _sentinel) if f is not _sentinel: return f(*args, **kw) else: return func(*args, **kw) _by_type = {object: func} try: _by_type[InstanceType] = _by_class except NameError: # Python 3 pass _gbt = _by_type.get def when_type(*types): """Decorator to add a method that will be called for the given types""" for t in types: if not isinstance(t, classtypes): raise TypeError( "%r is not a type or class" % (t,) ) def decorate(f): for t in types: if _by_type.setdefault(t,f) is not f: raise TypeError( "%r already has method for type %r" % (func, t) ) return f return decorate _by_object = {} _gbo = _by_object.get def when_object(*obs): """Decorator to add a method to be called for the given object(s)""" def decorate(f): for o in obs: if _by_object.setdefault(id(o), (o,f))[1] is not f: raise TypeError( "%r already has method for object %r" % (func, o) ) return f return decorate def dispatch(*args, **kw): f = _gbo(id(args[0]), _sentinel) if f is _sentinel: for t in type(args[0]).__mro__: f = _gbt(t, _sentinel) if f is not _sentinel: return f(*args, **kw) else: return func(*args, **kw) else: return f[1](*args, **kw) dispatch.__name__ = func.__name__ dispatch.__dict__ = func.__dict__.copy() dispatch.__doc__ = func.__doc__ dispatch.__module__ = func.__module__ dispatch.when_type = when_type dispatch.when_object = when_object dispatch.default = func dispatch.has_object = lambda o: id(o) in _by_object dispatch.has_type = lambda t: t in _by_type return dispatch def test_suite(): import doctest return doctest.DocFileSuite( 'README.txt', optionflags=doctest.ELLIPSIS|doctest.REPORT_ONLY_FIRST_FAILURE, )