def test_method_lambda_function_no_overrides(): class F(object): Type = int def __init__(self, arg): self.arg = arg @dispatch(lambda cls: cls.Type) def __mul__(self, other): return self.arg * other class G(F): Type = float def __init__(self, arg): F.__init__(self, arg) class H(F): Type = str def __init__(self, arg): F.__init__(self, arg) assert F(1) * 2 == 2 assert raises(UnavailableSignatureError, lambda: G(1) * 2) assert G(2) * 2. == 4. assert raises(UnavailableSignatureError, lambda: G(3) * "test") assert raises(UnavailableSignatureError, lambda: H(1) * 2) assert raises(UnavailableSignatureError, lambda: H(2) * 2.) assert H(3) * "test" == "testtesttest"
def test_override_4(): class B(object): def __init__(self, arg): self.arg = arg @dispatch(int) def __mul__(self, other): return self.arg*other class C(B): @dispatch(float) def __mul__(self, other): return 2.*self.arg*other class D(C): @dispatch(str) def __mul__(self, other): return 3*self.arg*other assert B(1)*2 == 2 assert raises(UnavailableSignatureError, lambda: B(1)*2.) assert raises(UnavailableSignatureError, lambda: B(1)*"test") assert C(1)*2 == 2 assert C(1)*2. == 4. assert raises(UnavailableSignatureError, lambda: C(1)*"test") assert D(1)*2 == 2 assert D(1)*2. == 4. assert D(1)*"test" == "testtesttest"
def test_function_custom_module(): module = types.ModuleType("module", "A runtime generated module") @dispatch(int, module=module) def f(arg): return arg assert inspect.isfunction(f) assert isinstance(module.f, Dispatcher) @dispatch(float, module=module) def f(arg): return 2.*arg assert inspect.isfunction(f) assert isinstance(module.f, Dispatcher) @dispatch(str, module=module) def f(arg): return arg[0] assert inspect.isfunction(f) assert isinstance(module.f, Dispatcher) f = module.f assert f(1) == 1 assert f(1.) == 2. assert f("test") == "t" assert raises(UnavailableSignatureError, lambda: f(object()))
def test_not_implemented_error(): f = Dispatcher('f') @f.register(float) def _(a): raise MDNotImplementedError() assert raises(NotImplementedError, lambda: f(1.0))
def test_vararg_no_args_failure(): f = Dispatcher('f') @f.register([str]) def _2(*strings): return 'strings' assert raises(NotImplementedError, lambda: f('a', 'b', 1))
def test_register_stacking(): f = Dispatcher('f') @f.register(list) @f.register(tuple) def rev(x): return x[::-1] assert f((1, 2, 3)) == (3, 2, 1) assert f([1, 2, 3]) == [3, 2, 1] assert raises(NotImplementedError, lambda: f('hello')) assert rev('hello') == 'olleh'
def test_register_stacking__list_of__tuple_of(): f = Dispatcher('f') @f.register(list_of(int)) @f.register(tuple_of(int)) def rev(x): return x[::-1] assert f((1, 2, 3)) == (3, 2, 1) assert f([1, 2, 3]) == [3, 2, 1] assert raises(UnavailableSignatureError, lambda: f('hello')) assert rev('hello') == 'olleh'
def test_inheritance_and_multiple_dispatch(): @dispatch(A, A) def f(x, y): return type(x), type(y) @dispatch(A, B) def f(x, y): return 0 assert f(A(), A()) == (A, A) assert f(A(), C()) == (A, C) assert f(A(), B()) == 0 assert f(C(), B()) == 0 assert raises(NotImplementedError, lambda: f(B(), B()))
def test_method_lambda_function_change(): class F(object): Type = int def __init__(self, arg): self.arg = arg @dispatch(lambda cls: cls.Type) def __mul__(self, other): return self.arg*other assert F(3)*2 == 6 and isinstance(F(3)*2, int) F.Type = float # this has no effect because assert raises(UnavailableSignatureError, lambda: F(3)*2.) # the Type has been already processed, assert F(3)*2 == 6 and isinstance(F(3)*2, int) # so the internal signature is unchanged
def test_dispatch_twice_function_automatic_resolution(): @dispatch(float) def g(arg): return arg assert raises(UnavailableSignatureError, lambda: g(1)) assert g(1.) == 1. @dispatch((int, float)) def g(arg): return 2*arg assert g(1) == 2 assert g(1.) == 1. @dispatch(int) def g(arg): return 3*arg assert g(1) == 3 assert g(1.) == 1.
def test_singledispatch(): @dispatch(int) def f(x): return x + 1 @dispatch(int) def g(x): return x + 2 @dispatch(float) def f(x): return x - 1 assert f(1) == 2 assert g(1) == 3 assert f(1.0) == 0 assert raises(NotImplementedError, lambda: f('hello'))
def test_not_implemented(): f = Dispatcher('f') @f.register(object) def _1(x): return 'default' @f.register(int) def _2(x): if x % 2 == 0: return 'even' else: raise MDNotImplementedError() assert f('hello') == 'default' # default behavior assert f(2) == 'even' # specialized behavior assert f(3) == 'default' # fall back to default behavior assert raises(NotImplementedError, lambda: f(1, 2))
def test_competing_solutions_for_dict_of_keys(): class A(object): pass class C(A): pass class D(C): pass @dispatch(dict_of(A, int)) def h(x): return 1 @dispatch(dict_of(C, int)) def h(x): return 2 assert h({A(): 1}) == 1 assert h({C(): 2}) == 2 assert h({D(): 3}) == 2 assert raises(UnavailableSignatureError, lambda: h({A(): 4.}))
def test_inheritance_for_dict_of_values(): class A(object): pass class B(object): pass class C(A): pass @dispatch(dict_of(int, A)) def f(x): return 'a' @dispatch(dict_of(int, B)) def f(x): return 'b' assert f({1: A()}) == 'a' assert f({2: B()}) == 'b' assert f({3: C()}) == 'a' assert raises(UnavailableSignatureError, lambda: f({4.: B()}))
def test_competing_solutions_for_dict_of_values(): class A(object): pass class C(A): pass class D(C): pass @dispatch(dict_of(int, A)) def h(x): return 1 @dispatch(dict_of(int, C)) def h(x): return 2 assert h({1: A()}) == 1 assert h({2: C()}) == 2 assert h({3: D()}) == 2 assert raises(UnavailableSignatureError, lambda: h({4.: A()}))
def test_function_current_module(): @dispatch(int) def f(arg): return arg assert isinstance(f, Dispatcher) @dispatch(float) def f(arg): return 2.*arg assert isinstance(f, Dispatcher) @dispatch(str) def f(arg): return arg[0] assert isinstance(f, Dispatcher) assert f(1) == 1 assert f(1.) == 2. assert f("test") == "t" assert raises(UnavailableSignatureError, lambda: f(object()))
def test_inheritance_for_dict_of_keys(): class A(object): pass class B(object): pass class C(A): pass @dispatch(dict_of(A, int)) def f(x): return 'a' @dispatch(dict_of(B, int)) def f(x): return 'b' assert f({A(): 1}) == 'a' assert f({B(): 2}) == 'b' assert f({C(): 3}) == 'a' assert raises(UnavailableSignatureError, lambda: f({B(): 4.}))
def test_inheritance_for_list_of(): class A(object): pass class B(object): pass class C(A): pass @dispatch(list_of(A)) def f(x): return 'a' @dispatch(list_of(B)) def f(x): return 'b' assert f([A(), A()]) == 'a' assert f([B(), B()]) == 'b' assert f([C(), C()]) == 'a' assert f([C(), A()]) == 'a' assert raises(UnavailableSignatureError, lambda: f(B(), C()))
def test_inheritance_for_dict_of_keys_tuple_of(): class A(object): pass class B(object): pass class C(A): pass @dispatch(dict_of(tuple_of(A), int)) def f(x): return 'a' @dispatch(dict_of(tuple_of(B), int)) def f(x): return 'b' assert f({(A(), A()): 1}) == 'a' assert f({(B(), B()): 2}) == 'b' assert f({(C(), C()): 3}) == 'a' assert f({(C(), A()): 4}) == 'a' assert raises(UnavailableSignatureError, lambda: f({(B(), B()): 5.}))
def test_enabled_list_of_multiple(): class E(object): @dispatch(list_of(float)) def __init__(self, arg): self.arg = arg[0] @dispatch(list_of((float, int))) def __init__(self, arg): self.arg = 2*arg[0] @dispatch(list_of((float, str))) def __init__(self, arg): self.arg = 3*arg[0] assert E([1.]).arg == 1. and isinstance(E([1., 2.]).arg, float) assert E(["a"]).arg == "aaa" assert E([1]).arg == 2 and isinstance(E([1]).arg, int) assert E([1., 2.]).arg == 1. and isinstance(E([1., 2.]).arg, float) assert E([4., 3]).arg == 8. and isinstance(E([4., 3]).arg, float) assert E([4, 3.]).arg == 8 and isinstance(E([4, 3.]).arg, int) assert E([2., "a"]).arg == 6. and isinstance(E([2., "a"]).arg, float) assert raises(UnavailableSignatureError, lambda: E([object()]))
def test_competing_solutions_for_dict_of_keys_and_values(): class A(object): pass class C(A): pass class D(C): pass @dispatch(dict_of(A, A)) def h(x): return 1 @dispatch(dict_of(C, C)) def h(x): return 2 assert h({A(): A()}) == 1 assert h({C(): C()}) == 2 assert h({D(): D()}) == 2 assert h({A(): D()}) == 1 assert h({D(): A()}) == 1 assert raises(UnavailableSignatureError, lambda: h({A(): object()}))
def test_inheritance_for_dict_of_keys_values(): class A(object): pass class B(object): pass class C(A): pass @dispatch(dict_of(A, A)) def f(x): return "a" @dispatch(dict_of(B, B)) def f(x): return "b" assert f({A(): A()}) == "a" assert f({B(): B()}) == "b" assert f({C(): C()}) == "a" assert f({A(): C()}) == "a" assert f({C(): A()}) == "a" assert raises(UnavailableSignatureError, lambda: f({A(): B()}))
def test_raise_error_on_non_class(): f = Dispatcher('f') assert raises(TypeError, lambda: f.add((1,), inc))
def test_vararg_has_multiple_elements(): f = Dispatcher('f') assert raises(TypeError, lambda: f.register([float, str])(lambda: None))
def test_vararg_not_last_element_of_signature(): f = Dispatcher('f') assert raises(TypeError, lambda: f.register([float], str)(lambda: None))
def test_no_implementations(): f = Dispatcher('f') assert raises(NotImplementedError, lambda: f('hello'))
def test_source_raises_on_missing_function(): f = Dispatcher('f') assert raises(TypeError, lambda: f.source(1))