BROKEN: Moved everything
[gc-dialer] / src / util / overloading.py
diff --git a/src/util/overloading.py b/src/util/overloading.py
deleted file mode 100644 (file)
index 89cb738..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-#!/usr/bin/env python
-import new
-
-# Make the environment more like Python 3.0
-__metaclass__ = type
-from itertools import izip as zip
-import textwrap
-import inspect
-
-
-__all__ = [
-       "AnyType",
-       "overloaded"
-]
-
-
-AnyType = object
-
-
-class overloaded:
-       """
-       Dynamically overloaded functions.
-
-       This is an implementation of (dynamically, or run-time) overloaded
-       functions; also known as generic functions or multi-methods.
-
-       The dispatch algorithm uses the types of all argument for dispatch,
-       similar to (compile-time) overloaded functions or methods in C++ and
-       Java.
-
-       Most of the complexity in the algorithm comes from the need to support
-       subclasses in call signatures.  For example, if an function is
-       registered for a signature (T1, T2), then a call with a signature (S1,
-       S2) is acceptable, assuming that S1 is a subclass of T1, S2 a subclass
-       of T2, and there are no other more specific matches (see below).
-
-       If there are multiple matches and one of those doesn't *dominate* all
-       others, the match is deemed ambiguous and an exception is raised.  A
-       subtlety here: if, after removing the dominated matches, there are
-       still multiple matches left, but they all map to the same function,
-       then the match is not deemed ambiguous and that function is used.
-       Read the method find_func() below for details.
-
-       @note Python 2.5 is required due to the use of predicates any() and all().
-       @note only supports positional arguments
-
-       @author http://www.artima.com/weblogs/viewpost.jsp?thread=155514
-
-       >>> import misc
-       >>> misc.validate_decorator (overloaded)
-       >>>
-       >>>
-       >>>
-       >>>
-       >>> #################
-       >>> #Basics, with reusing names and without
-       >>> @overloaded
-       ... def foo(x):
-       ...     "prints x"
-       ...     print x
-       ...
-       >>> @foo.register(int)
-       ... def foo(x):
-       ...     "prints the hex representation of x"
-       ...     print hex(x)
-       ...
-       >>> from types import DictType
-       >>> @foo.register(DictType)
-       ... def foo_dict(x):
-       ...     "prints the keys of x"
-       ...     print [k for k in x.iterkeys()]
-       ...
-       >>> #combines all of the doc strings to help keep track of the specializations
-       >>> foo.__doc__  # doctest: +ELLIPSIS
-       "prints x\\n\\n...overloading.foo (<type 'int'>):\\n\\tprints the hex representation of x\\n\\n...overloading.foo_dict (<type 'dict'>):\\n\\tprints the keys of x"
-       >>> foo ("text")
-       text
-       >>> foo (10) #calling the specialized foo
-       0xa
-       >>> foo ({3:5, 6:7}) #calling the specialization foo_dict
-       [3, 6]
-       >>> foo_dict ({3:5, 6:7}) #with using a unique name, you still have the option of calling the function directly
-       [3, 6]
-       >>>
-       >>>
-       >>>
-       >>>
-       >>> #################
-       >>> #Multiple arguments, accessing the default, and function finding
-       >>> @overloaded
-       ... def two_arg (x, y):
-       ...     print x,y
-       ...
-       >>> @two_arg.register(int, int)
-       ... def two_arg_int_int (x, y):
-       ...     print hex(x), hex(y)
-       ...
-       >>> @two_arg.register(float, int)
-       ... def two_arg_float_int (x, y):
-       ...     print x, hex(y)
-       ...
-       >>> @two_arg.register(int, float)
-       ... def two_arg_int_float (x, y):
-       ...     print hex(x), y
-       ...
-       >>> two_arg.__doc__ # doctest: +ELLIPSIS
-       "...overloading.two_arg_int_int (<type 'int'>, <type 'int'>):\\n\\n...overloading.two_arg_float_int (<type 'float'>, <type 'int'>):\\n\\n...overloading.two_arg_int_float (<type 'int'>, <type 'float'>):"
-       >>> two_arg(9, 10)
-       0x9 0xa
-       >>> two_arg(9.0, 10)
-       9.0 0xa
-       >>> two_arg(15, 16.0)
-       0xf 16.0
-       >>> two_arg.default_func(9, 10)
-       9 10
-       >>> two_arg.find_func ((int, float)) == two_arg_int_float
-       True
-       >>> (int, float) in two_arg
-       True
-       >>> (str, int) in two_arg
-       False
-       >>>
-       >>>
-       >>>
-       >>> #################
-       >>> #wildcard
-       >>> @two_arg.register(AnyType, str)
-       ... def two_arg_any_str (x, y):
-       ...     print x, y.lower()
-       ...
-       >>> two_arg("Hello", "World")
-       Hello world
-       >>> two_arg(500, "World")
-       500 world
-       """
-
-       def __init__(self, default_func):
-               # Decorator to declare new overloaded function.
-               self.registry = {}
-               self.cache = {}
-               self.default_func = default_func
-               self.__name__ = self.default_func.__name__
-               self.__doc__ = self.default_func.__doc__
-               self.__dict__.update (self.default_func.__dict__)
-
-       def __get__(self, obj, type=None):
-               if obj is None:
-                       return self
-               return new.instancemethod(self, obj)
-
-       def register(self, *types):
-               """
-               Decorator to register an implementation for a specific set of types.
-
-               .register(t1, t2)(f) is equivalent to .register_func((t1, t2), f).
-               """
-
-               def helper(func):
-                       self.register_func(types, func)
-
-                       originalDoc = self.__doc__ if self.__doc__ is not None else ""
-                       typeNames = ", ".join ([str(type) for type in types])
-                       typeNames = "".join ([func.__module__+".", func.__name__, " (", typeNames, "):"])
-                       overloadedDoc = ""
-                       if func.__doc__ is not None:
-                               overloadedDoc = textwrap.fill (func.__doc__, width=60, initial_indent="\t", subsequent_indent="\t")
-                       self.__doc__ = "\n".join ([originalDoc, "", typeNames, overloadedDoc]).strip()
-
-                       new_func = func
-
-                       #Masking the function, so we want to take on its traits
-                       if func.__name__ == self.__name__:
-                               self.__dict__.update (func.__dict__)
-                               new_func = self
-                       return new_func
-
-               return helper
-
-       def register_func(self, types, func):
-               """Helper to register an implementation."""
-               self.registry[tuple(types)] = func
-               self.cache = {} # Clear the cache (later we can optimize this).
-
-       def __call__(self, *args):
-               """Call the overloaded function."""
-               types = tuple(map(type, args))
-               func = self.cache.get(types)
-               if func is None:
-                       self.cache[types] = func = self.find_func(types)
-               return func(*args)
-
-       def __contains__ (self, types):
-               return self.find_func(types) is not self.default_func
-
-       def find_func(self, types):
-               """Find the appropriate overloaded function; don't call it.
-
-               @note This won't work for old-style classes or classes without __mro__
-               """
-               func = self.registry.get(types)
-               if func is not None:
-                       # Easy case -- direct hit in registry.
-                       return func
-
-               # Phillip Eby suggests to use issubclass() instead of __mro__.
-               # There are advantages and disadvantages.
-
-               # I can't help myself -- this is going to be intense functional code.
-               # Find all possible candidate signatures.
-               mros = tuple(inspect.getmro(t) for t in types)
-               n = len(mros)
-               candidates = [sig for sig in self.registry
-                               if len(sig) == n and
-                                       all(t in mro for t, mro in zip(sig, mros))]
-
-               if not candidates:
-                       # No match at all -- use the default function.
-                       return self.default_func
-               elif len(candidates) == 1:
-                       # Unique match -- that's an easy case.
-                       return self.registry[candidates[0]]
-
-               # More than one match -- weed out the subordinate ones.
-
-               def dominates(dom, sub,
-                               orders=tuple(dict((t, i) for i, t in enumerate(mro))
-                                                       for mro in mros)):
-                       # Predicate to decide whether dom strictly dominates sub.
-                       # Strict domination is defined as domination without equality.
-                       # The arguments dom and sub are type tuples of equal length.
-                       # The orders argument is a precomputed auxiliary data structure
-                       # giving dicts of ordering information corresponding to the
-                       # positions in the type tuples.
-                       # A type d dominates a type s iff order[d] <= order[s].
-                       # A type tuple (d1, d2, ...) dominates a type tuple of equal length
-                       # (s1, s2, ...) iff d1 dominates s1, d2 dominates s2, etc.
-                       if dom is sub:
-                               return False
-                       return all(order[d] <= order[s] for d, s, order in zip(dom, sub, orders))
-
-               # I suppose I could inline dominates() but it wouldn't get any clearer.
-               candidates = [cand
-                               for cand in candidates
-                                       if not any(dominates(dom, cand) for dom in candidates)]
-               if len(candidates) == 1:
-                       # There's exactly one candidate left.
-                       return self.registry[candidates[0]]
-
-               # Perhaps these multiple candidates all have the same implementation?
-               funcs = set(self.registry[cand] for cand in candidates)
-               if len(funcs) == 1:
-                       return funcs.pop()
-
-               # No, the situation is irreducibly ambiguous.
-               raise TypeError("ambigous call; types=%r; candidates=%r" %
-                                               (types, candidates))