Fix error in multimethod's otherwise clause

This commit is contained in:
Arjan Molenaar 2019-11-09 19:27:15 +01:00
parent 6eef860ff4
commit afb1a7996f
3 changed files with 52 additions and 2 deletions

View File

@ -121,6 +121,7 @@ class FunctionDispatcher(Generic[T]):
trimmed_args = args[: self.params_arity]
rule = self.registry.lookup(*trimmed_args)
if not rule:
print(self.registry._tree)
raise TypeError(f"No available rule found for {trimmed_args!r}")
return rule(*args, **kwargs)

View File

@ -85,6 +85,7 @@ class MethodDispatcher(FunctionDispatcher[T]):
""" Process all unbound rule by binding them to ``cls`` type."""
for argtypes, func in self.local.unbound_rules:
argtypes = (cls,) + argtypes
print("register rule", argtypes)
self.register_rule(func, *argtypes)
self.local.unbound_rules = []
@ -106,8 +107,8 @@ class MethodDispatcher(FunctionDispatcher[T]):
def otherwise(self) -> Callable[[T], T]:
""" Decorator which registeres "catch-all" case for multimethod"""
def make_declaration(func):
self.register_unbound_rule(func, [object] * self.params_arity)
def make_declaration(meth):
self.register_unbound_rule(meth, *([object] * (self.params_arity - 1)))
return self
return make_declaration

View File

@ -20,6 +20,54 @@ def test_multimethod():
Dummy().foo([])
def test_multimethod_with_two_arguments():
@has_multimethods
class Dummy(object):
@multimethod(int, int)
def foo(self, x, y):
return x * y
@foo.register(str, int) # type: ignore[no-redef]
def foo(self, s, x):
return s * x
assert Dummy().foo(1, 1) == 1
assert Dummy().foo("1", 2) == "11"
with pytest.raises(TypeError):
Dummy().foo([])
def test_multimethod_otherwise_clause():
@has_multimethods
class Dummy(object):
@multimethod(int)
def foo(self, x):
return x + 1
@foo.otherwise # type: ignore[no-redef]
def foo(self, x):
return type(x)
assert Dummy().foo(1) == 2
assert Dummy().foo("") is str
assert Dummy().foo([]) is list
def test_multimethod_otherwise_clausewith_two_arguments():
@has_multimethods
class Dummy(object):
@multimethod(int, int)
def foo(self, x, y):
return x * y
@foo.otherwise # type: ignore[no-redef]
def foo(self, s, x):
return f"{s} {x}"
assert Dummy().foo(1, 2) == 2
assert Dummy().foo("a", []) == "a []"
def test_inheritance():
@has_multimethods
class Dummy(object):