def test_registry_sources(): reg = Registry() class Document(object): pass class SpecialDocument(Document): pass def linecount(obj): pass reg.register(linecount, [Document], 'document line count') reg.register(linecount, [SpecialDocument], 'special document line count') assert (reg.component(linecount, [Document()]) == 'document line count') assert (reg.component( linecount, [SpecialDocument()]) == 'special document line count') class AnotherDocument(Document): pass assert (reg.component(linecount, [AnotherDocument()]) == 'document line count') class Other(object): pass assert reg.component(linecount, [Other()], default=None) is None
def test_register_dispatch_predicates_twice(): @dispatch_external_predicates() def foo(obj): pass def for_bar(obj): return "for bar" def for_qux(obj): return "for qux" class Bar(object): pass class Qux(object): pass registry = Registry() registry.register_dispatch_predicates( foo, [match_instance('obj', lambda obj: obj)]) assert foo in registry.initialized # second time has no effect registry.register_dispatch_predicates( foo, [match_instance('obj', lambda obj: obj)])
def test_dispatch_match_instance(): @dispatch(match_instance('obj', lambda obj: obj)) def foo(obj): pass def for_bar(obj): return obj.method() def for_qux(obj): return obj.method() class Bar(object): def method(self): return "bar's method" class Qux(object): def method(self): return "qux's method" registry = Registry() registry.register_function(foo, for_bar, obj=Bar) registry.register_function(foo, for_qux, obj=Qux) lookup = registry.lookup() assert foo(Bar(), lookup=lookup) == "bar's method" assert foo(Qux(), lookup=lookup) == "qux's method"
def test_call_two_sources(): reg = Registry() @generic def target(a, b): pass class Adapted(object): def __init__(self, alpha, beta): self.alpha = alpha self.beta = beta def foo(self): pass reg.register(target, [IAlpha, IBeta], Adapted) alpha = Alpha() beta = Beta() adapted = reg.call(target, [alpha, beta]) assert isinstance(adapted, Adapted) assert adapted.alpha is alpha assert adapted.beta is beta adapted = target(alpha, beta, lookup=reg) assert isinstance(adapted, Adapted) assert adapted.alpha is alpha assert adapted.beta is beta
def test_adapter_two_sources(): reg = Registry() class Adapted(ITarget): def __init__(self, alpha, beta): self.alpha = alpha self.beta = beta def foo(self): pass reg.register(ITarget, [IAlpha, IBeta], Adapted) alpha = Alpha() beta = Beta() adapted = reg.adapt(ITarget, [alpha, beta]) assert isinstance(adapted, Adapted) assert adapted.alpha is alpha assert adapted.beta is beta adapted = ITarget.adapt(alpha, beta, lookup=reg) assert isinstance(adapted, Adapted) assert adapted.alpha is alpha assert adapted.beta is beta
def test_component_inheritance_old_style_class(): reg = Registry() foo = object() class Gamma: pass class Delta(Gamma): pass @generic def target(): pass reg.register(target, [Gamma], foo) gamma = Gamma() delta = Delta() assert reg.component(target, [gamma]) is foo assert target.component(gamma, lookup=reg) is foo # inheritance case assert reg.component(target, [delta]) is foo assert target.component(delta, lookup=reg) is foo
def test_registry_target_find_specific(): reg = Registry() class Document(object): pass class SpecialDocument(Document): pass def linecount(obj): pass def special_linecount(obj): pass reg.register(linecount, [Document], 'line count') reg.register(special_linecount, [Document], 'special line count') assert reg.component(linecount, [Document()]) == 'line count' assert (reg.component(special_linecount, [Document()]) == 'special line count') assert reg.component(linecount, [SpecialDocument()]) == 'line count' assert (reg.component(special_linecount, [SpecialDocument()]) == 'special line count')
def test_register_no_external_predicates_for_external(): @dispatch_external_predicates() def foo(): pass r = Registry() with pytest.raises(RegistrationError): r.register_dispatch(foo)
def test_component_two_sources(): reg = Registry() foo = object() reg.register(ITarget, (IAlpha, IBeta), foo) alpha = Alpha() beta = Beta() assert reg.component(ITarget, [alpha, beta]) is foo assert ITarget.component(alpha, beta, lookup=reg) is foo
def test_component_class_based_registration(): reg = Registry() foo = object() reg.register(ITarget, (Alpha,), foo) alpha = Alpha() assert reg.component(ITarget, [alpha]) is foo assert ITarget.component(alpha, lookup=reg) is foo
def test_non_adapter_looked_up_as_adapter(): reg = Registry() foo = object() reg.register(ITarget, [Alpha], foo) alpha = Alpha() with py.test.raises(TypeError): ITarget.adapt(alpha, lookup=reg)
def test_chain_class_lookup_all(): reg1 = Registry() reg2 = Registry() reg1.register(target, (), 'reg1') reg2.register(target, (), 'reg2') lookup = ChainClassLookup(reg1, reg2) assert list(lookup.all(target, ())) == ['reg1', 'reg2']
def test_dict_to_predicate_key_for_unknown_dispatch(): @dispatch() def foo(): pass r = Registry() with pytest.raises(KeyError): r.key_dict_to_predicate_key(foo, {})
def test_lookup_passed_along_fallback(): @dispatch() def a(lookup): return "fallback" reg = Registry() reg.register_dispatch(a) assert a(lookup=reg.lookup()) == 'fallback'
def test_list_class_lookup_all(): reg1 = Registry() reg2 = Registry() reg1.register(target, (), 'reg1') reg2.register(target, (), 'reg2') lookup = ListClassLookup([reg1, reg2]) assert list(lookup.all(target, ())) == ['reg1', 'reg2']
def test_interface_component(): class IFoo(Interface): pass registry = Registry() registry.register(IFoo, (), "test component") assert IFoo.component(lookup=registry) == 'test component'
def test_adapter_returns_none(): def adapt(obj): return None reg = Registry() reg.register(ITarget, [Alpha], adapt) alpha = Alpha() with py.test.raises(ComponentLookupError): ITarget.adapt(alpha, lookup=reg) assert ITarget.adapt(alpha, lookup=reg, default='default') == 'default'
def test_component(): @generic def foo(): pass registry = Registry() registry.register(foo, (), "test component") assert foo.component(lookup=registry) == 'test component'
def test_component_to_itself(): reg = Registry() alpha = Alpha() foo = object() reg.register(IAlpha, [IAlpha], foo) assert reg.component(IAlpha, [alpha]) is foo assert IAlpha.component(alpha, lookup=reg) is foo
def test_extra_kw(): reg = Registry() foo = object() reg.register(ITarget, [Alpha], foo) alpha = Alpha() with py.test.raises(TypeError) as e: ITarget.component(alpha, lookup=reg, extra="illegal") assert str(e.value) == 'Illegal extra keyword arguments: extra'
def test_implicit_component_lookup(): class ITarget(Interface): pass reg = Registry() reg.register(ITarget, (), 'test component') implicit.initialize(reg) assert ITarget.component() == 'test component'
def test_registry_sources(): reg = Registry() class Document(object): pass class SpecialDocument(Document): pass def linecount(obj): pass reg.register(linecount, [Document], 'document line count') reg.register(linecount, [SpecialDocument], 'special document line count') assert (reg.component(linecount, [Document()]) == 'document line count') assert (reg.component(linecount, [SpecialDocument()]) == 'special document line count') class AnotherDocument(Document): pass assert (reg.component(linecount, [AnotherDocument()]) == 'document line count') class Other(object): pass assert reg.component(linecount, [Other()], default=None) is None
def test_fallback_to_fallback(): def fallback(obj): return 'fallback!' @dispatch(match_instance('obj', lambda obj: obj, fallback=fallback)) def target(obj): return 'not the fallback we want' reg = Registry() def specific_target(obj): return 'specific' reg.register_dispatch(target) reg.register_function(target, specific_target, obj=Alpha) beta = Beta() assert target(beta, lookup=reg.lookup()) == 'fallback!' # this is *not* a registered fallback so won't be returned here assert target.fallback(beta, lookup=reg.lookup()) is fallback # we cannot find a fallback for alpha, as it doesn't hit the fallback assert target(Alpha(), lookup=reg.lookup()) == 'specific' assert target.fallback(Alpha(), lookup=reg.lookup()) is NOT_FOUND
def test_registry_target_find_specific(): reg = Registry() class Document(object): pass class LineCount(object): pass class SpecialLineCount(LineCount): pass class SpecialDocument(Document): pass reg.register(LineCount, (Document,), 'line count') reg.register(SpecialLineCount, (Document,), 'special line count') assert reg.component(LineCount, (Document(),)) == 'line count' assert (reg.component(SpecialLineCount, (Document(),)) == 'special line count') assert reg.component(LineCount, (SpecialDocument(),)) == 'line count' assert (reg.component(SpecialLineCount, (SpecialDocument(),)) == 'special line count')
def test_registry_sources(): reg = Registry() class Document(object): pass class SpecialDocument(Document): pass class LineCount(object): pass reg.register(LineCount, (Document,), 'document line count') reg.register(LineCount, (SpecialDocument,), 'special document line count') assert (reg.component(LineCount, (Document(),)) == 'document line count') assert (reg.component(LineCount, (SpecialDocument(),)) == 'special document line count') class AnotherDocument(Document): pass assert (reg.component(LineCount, (AnotherDocument(),)) == 'document line count') class Other(object): pass assert reg.component(LineCount, (Other(),), default=None) is None
def test_matcher_inheritance(): reg = Registry() class Document(object): def __init__(self, id): self.id = id class SpecialDocument(Document): pass def linecount(obj): pass class DocumentMatcher(Matcher): def __call__(self, doc): if doc.id == 1: return 'normal' else: return 'special' class SpecialDocumentMatcher(Matcher): def __call__(self, doc): if doc.id == 2: return 'extra normal' else: return None reg.register(linecount, [Document], DocumentMatcher()) reg.register(linecount, [SpecialDocument], SpecialDocumentMatcher()) assert reg.component(linecount, [Document(1)]) == 'normal' assert reg.component(linecount, [Document(2)]) == 'special' assert reg.component(linecount, [SpecialDocument(1)]) == 'normal' assert reg.component(linecount, [SpecialDocument(2)]) == 'extra normal' assert reg.component(linecount, [SpecialDocument(3)]) == 'special'
def test_registry_no_sources(): reg = Registry() class Animal(object): pass def something(): pass reg.register(something, (), 'elephant') assert reg.component(something, ()) == 'elephant'
def test_component_no_source(): reg = Registry() foo = object() @generic def target(): pass reg.register(target, (), foo) assert reg.component(target, []) is foo assert target.component(lookup=reg) is foo
def test_implicit_component_lookup(): @generic def func(): pass reg = Registry() reg.register(func, (), 'test component') implicit.initialize(reg) assert func.component() == 'test component'
def test_call_not_found_no_sources(): reg = Registry() @dispatch() def target(): return "default" reg.register_dispatch(target) lookup = reg.lookup() assert target(lookup=lookup) == "default"
def test_list_class_lookup(): reg1 = Registry() reg2 = Registry() reg2.register(target, (), 'reg2 component') lookup = ListClassLookup([reg1, reg2]) assert lookup.get(target, ()) == 'reg2 component' reg1.register(target, (), 'reg1 component') assert lookup.get(target, ()) == 'reg1 component'
def test_chain_class_lookup(): reg1 = Registry() reg2 = Registry() reg2.register(target, (), 'reg2 component') lookup = ChainClassLookup(reg1, reg2) assert lookup.get(target, ()) == 'reg2 component' reg1.register(target, (), 'reg1 component') assert lookup.get(target, ()) == 'reg1 component'
def test_registry_no_sources(): reg = Registry() class Animal(object): pass class Elephant(Animal): pass reg.register(Elephant, (), 'elephant') assert reg.component(Animal, ()) == 'elephant'
def test_component_not_found_no_sources(): reg = Registry() @dispatch() def target(): pass reg.register_dispatch(target) lookup = reg.lookup() assert target.component(lookup=lookup) is None
def test_func_returns_none(): @generic def target(obj): raise NotImplementedError def adapt(obj): return None reg = Registry() reg.register(target, [Alpha], adapt) alpha = Alpha() assert target(alpha, lookup=reg) is None assert target(alpha, lookup=reg, default='default') == 'default'
def test_non_callable_registered(): reg = Registry() @dispatch('obj') def target(obj): pass non_callable = None reg.register_dispatch(target) with pytest.raises(RegistrationError): reg.register_function(target, non_callable, a=Alpha)
def test_fallback(): @generic def target(obj): return 'fallback' reg = Registry() def specific_target(obj): return 'specific' reg.register(target, [Alpha], specific_target) beta = Beta() assert target(beta, lookup=reg) == 'fallback'
def test_component_one_source(): reg = Registry() foo = object() @generic def target(): pass reg.register(target, [Alpha], foo) alpha = Alpha() assert reg.component(target, [alpha]) is foo assert target.component(alpha, lookup=reg) is foo
def test_component_two_sources(): reg = Registry() foo = object() @generic def target(): pass reg.register(target, (IAlpha, IBeta), foo) alpha = Alpha() beta = Beta() assert reg.component(target, [alpha, beta]) is foo assert target.component(alpha, beta, lookup=reg) is foo
def test_non_function_called(): reg = Registry() foo = object() @generic def target(obj): pass reg.register(target, [Alpha], foo) alpha = Alpha() with pytest.raises(TypeError): target(alpha, lookup=reg)
def test_all(): class Base(object): pass class Sub(Base): pass @generic def target(obj): pass registry = Registry() registry.register(target, (Sub, ), 'registered for sub') registry.register(target, (Base, ), 'registered for base') base = Base() sub = Sub() assert list(registry.all( target, [sub])) == ['registered for sub', 'registered for base'] assert list(registry.all(target, [base])) == ['registered for base'] assert list(target.all(sub, lookup=registry)) == [ 'registered for sub', 'registered for base' ] assert list(target.all(base, lookup=registry)) == ['registered for base']
def test_clear(): reg = Registry() def linecount(obj): pass reg.register(linecount, [], 'once') assert reg.component(linecount, []) == 'once' reg.clear() with pytest.raises(ComponentLookupError): reg.component(linecount, [])
def test_extra_kw_for_component(): @generic def target(obj): pass reg = Registry() foo = object() reg.register(target, [Alpha], foo) alpha = Alpha() with pytest.raises(TypeError) as e: target.component(alpha, lookup=reg, extra="illegal") assert str(e.value) == ("component() got an unexpected keyword " "argument 'extra'")
def test_call_no_source(): reg = Registry() foo = object() @generic def target(): pass def factory(): return foo reg.register(target, (), factory) assert reg.call(target, []) is foo assert target(lookup=reg) is foo
def test_call_with_wrong_args(): @generic def target(obj): pass class Adapter(object): # takes no args def __init__(self): pass reg = Registry() reg.register(target, [Alpha], Adapter) alpha = Alpha() with pytest.raises(TypeError): target(alpha, lookup=reg)
def test_lookup_passed_along_fallback(): @generic def a(lookup): return "fallback" reg = Registry() assert a(lookup=reg) == 'fallback'
def test_default(): reg = Registry() @generic def target(): pass assert target.component(lookup=reg, default='blah') == 'blah' assert target(lookup=reg, default='blah') == 'blah'
def test_extra_kw_for_call(): @generic def target(obj, extra): return "General: %s" % extra reg = Registry() def specific(obj, extra): return "Specific: %s" % extra reg.register(target, [Alpha], specific) alpha = Alpha() beta = Beta() assert target(alpha, lookup=reg, extra="allowed") == 'Specific: allowed' assert target(beta, lookup=reg, extra="allowed") == 'General: allowed' assert target(alpha, lookup=reg, default='default', extra='allowed') == 'Specific: allowed' assert target(beta, lookup=reg, default='default', extra='allowed') == 'default'
def test_register_twice_without_sources(): reg = Registry() def linecount(obj): pass reg.register(linecount, [], 'once') reg.register(linecount, [], 'twice') assert reg.component(linecount, []) == 'twice'
def test_component_inheritance(): reg = Registry() foo = object() class Gamma(object): pass class Delta(Gamma): pass @generic def target(): pass reg.register(target, [Gamma], foo) delta = Delta() assert reg.component(target, [delta]) is foo assert target.component(delta, lookup=reg) is foo
def test_lookup_passed_along(): @generic def g1(obj): pass @generic def g2(obj): pass reg = Registry() def g1_impl(obj, lookup): return g2(obj, lookup=lookup) def g2_impl(obj): return "g2" reg.register(g1, [Alpha], g1_impl) reg.register(g2, [Alpha], g2_impl) assert g1(Alpha(), lookup=reg) == 'g2'
def test_matcher(): reg = Registry() class Document(object): def __init__(self, id): self.id = id def linecount(obj): pass class MyMatcher(Matcher): def __call__(self, doc): if doc.id == 1: return 'normal' else: return 'special' reg.register(linecount, [Document], MyMatcher()) assert reg.component(linecount, [Document(1)]) == 'normal' assert reg.component(linecount, [Document(2)]) == 'special'
def test_call(): @generic def foo(obj): pass class Foo(object): def __init__(self, bar): self.bar = bar def foo(self): return "Foo called: " + self.bar.bar() class Bar(object): def bar(self): return "bar's method" registry = Registry() registry.register(foo, (Bar, ), Foo) bar = Bar() assert foo(bar, lookup=registry).foo() == "Foo called: bar's method"