Exemplo n.º 1
0
def test_nestedbackend():
    obj = object()
    be_outer = Backend()
    be_outer.__ua_function__ = lambda f, a, kw: obj

    mm1 = ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                  "ua_tests")

    def default(*a, **kw):
        return mm1(*a, **kw)

    mm2 = ua.generate_multimethod(lambda: (),
                                  lambda a, kw, d: (a, kw),
                                  "ua_tests",
                                  default=default)

    be_inner = Backend()

    def be2_ua_func(f, a, kw):
        with ua.skip_backend(be_inner):
            return f(*a, **kw)

    be_inner.__ua_function__ = be2_ua_func
    with ua.set_backend(be_outer), ua.set_backend(be_inner):
        assert mm2() is obj
Exemplo n.º 2
0
def test_hierarchical_backends():
    mm = ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                 "ua_tests.foo.bar")
    subdomains = "ua_tests.foo.bar".split(".")
    depth = len(subdomains)

    mms = [
        ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                ".".join(subdomains[:i + 1]))
        for i in range(depth)
    ]

    be = [DisableBackend(".".join(subdomains[:i + 1])) for i in range(depth)]

    ua.set_global_backend(be[1])
    with pytest.raises(ua.BackendNotImplementedError):
        mms[0]()

    for i in range(1, depth):
        assert mms[i]() is be[1].ret

    ua.set_global_backend(be[0])

    for i in range(depth):
        assert mms[i]() is be[min(i, 1)].ret

    ua.set_global_backend(be[2])

    for i in range(depth):
        assert mms[i]() is be[i].ret

    be[2].active = False
    for i in range(depth):
        print(i)
        assert mms[i]() is be[min(i, 1)].ret

    be[1].active = False
    for i in range(depth):
        assert mms[i]() is be[0].ret

    be[0].active = False
    for i in range(depth):
        with pytest.raises(ua.BackendNotImplementedError):
            mms[i]()

    # only=True prevents all further domain checking
    be[0].active = True
    be[1].active = True
    with ua.set_backend(be[2], only=True), pytest.raises(
            ua.BackendNotImplementedError):
        mms[2]()
Exemplo n.º 3
0
def test_default(nullary_mm):
    obj = object()
    be = Backend()
    be.__ua_function__ = lambda f, a, kw: NotImplemented

    # If a backend returns NotImplemented, the default is called
    def default1(*a, **kw):
        return obj

    mm1 = ua.generate_multimethod(lambda: (),
                                  lambda a, kw, d: (a, kw),
                                  "ua_tests",
                                  default=default1)

    with ua.set_backend(be):
        assert mm1() is obj

    # If all backends fail, the default is called again without a specific backend
    num_calls = [0]

    def default2(*a, **kw):
        num_calls[0] = num_calls[0] + 1
        raise ua.BackendNotImplementedError()

    mm2 = ua.generate_multimethod(lambda: (),
                                  lambda a, kw, d: (a, kw),
                                  "ua_tests",
                                  default=default2)

    with ua.set_backend(be), pytest.raises(ua.BackendNotImplementedError):
        mm2()

    assert num_calls[0] == 2

    # If the last backend is set as only or coerce, the last default call is skipped
    num_calls[0] = 0
    with ua.set_backend(be, only=True), pytest.raises(
            ua.BackendNotImplementedError):
        mm2()
    assert num_calls[0] == 1
    num_calls[0] = 0
    with ua.set_backend(be, coerce=True), pytest.raises(
            ua.BackendNotImplementedError):
        mm2()
    assert num_calls[0] == 1
Exemplo n.º 4
0
def test_global(cleanup_backends):
    obj = object()
    be = Backend()
    be.__ua_function__ = lambda f, a, kw: obj
    mm = ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                 "ua_tests")

    ua.set_global_backend(be)
    assert mm() is obj
Exemplo n.º 5
0
def test_get_extractor_replacer():
    def extractor():
        return ()

    def replacer(a, kw, d):
        return a, kw

    mm = ua.generate_multimethod(extractor, replacer, "ua_tests")

    assert mm.arg_extractor is extractor
    assert mm.arg_replacer is replacer
Exemplo n.º 6
0
def test_determine_backend_coerce(nullary_mm):
    class TypeA:
        pass

    class TypeB:
        pass

    mark = "determine_backend_test"

    class TypeBackend:
        __ua_domain__ = "ua_tests"

        def __init__(self, my_type):
            self.my_type = my_type

        def __ua_convert__(self, dispatchables, coerce):
            if len(dispatchables) > 0:
                print(dispatchables[0], coerce)
            if coerce and all(d.coercible for d in dispatchables):
                return tuple(self.my_type() for _ in dispatchables)

            if not all(
                    type(d.value) is self.my_type and d.type is mark
                    for d in dispatchables):
                return NotImplemented
            return tuple(d.value for d in dispatchables)

        def __ua_function__(self, func, args, kwargs):
            return self.my_type

    BackendA = TypeBackend(TypeA)
    BackendB = TypeBackend(TypeB)
    unary_mm = ua.generate_multimethod(lambda a: (ua.Dispatchable(a, mark), ),
                                       lambda a, kw, d: (d, kw), "ua_tests")

    # coercion is not forced on the existing set backend
    with ua.set_backend(BackendA), ua.set_backend(BackendB):
        with ua.determine_backend(TypeA(),
                                  mark,
                                  domain="ua_tests",
                                  coerce=True):
            assert nullary_mm() is TypeA
            assert unary_mm(TypeB()) is TypeA

    # But is allowed if the backend was set with coerce in the first place
    with ua.set_backend(BackendA), ua.set_backend(BackendB, coerce=True):
        with ua.determine_backend(TypeA(),
                                  mark,
                                  domain="ua_tests",
                                  coerce=True):
            assert nullary_mm() is TypeB
            assert unary_mm(TypeA()) is TypeB
Exemplo n.º 7
0
def test_global_before_registered(cleanup_backends):
    obj = object()
    obj2 = object()
    be = Backend()
    be.__ua_function__ = lambda f, a, kw: obj

    be2 = Backend()
    be2.__ua_function__ = lambda f, a, kw: obj2
    mm = ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                 "ua_tests")

    ua.set_global_backend(be)
    ua.register_backend(be2)
    assert mm() is obj
Exemplo n.º 8
0
def test_global_only(cleanup_backends):
    obj = object()
    be = Backend()
    be.__ua_function__ = lambda f, a, kw: NotImplemented

    be2 = Backend()
    be2.__ua_function__ = lambda f, a, kw: obj
    mm = ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                 "ua_tests")

    ua.set_global_backend(be, only=True)
    ua.register_backend(be2)

    with pytest.raises(ua.BackendNotImplementedError):
        mm()
Exemplo n.º 9
0
def test_clear_backends(cleanup_backends):
    obj = object()
    obj2 = object()
    be = Backend()
    be.__ua_function__ = lambda f, a, kw: obj

    be2 = Backend()
    be2.__ua_function__ = lambda f, a, kw: obj2
    mm = ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                 "ua_tests")

    ua.set_global_backend(be)
    ua.register_backend(be2)

    ua.clear_backends(Backend.__ua_domain__, registered=True, globals=True)
    with pytest.raises(ua.BackendNotImplementedError):
        mm()
Exemplo n.º 10
0
def test_multidomain_backends():
    n_domains = 2
    be = DisableBackend(domain=["ua_tests" + str(i) for i in range(n_domains)])

    mms = [
        ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                "ua_tests" + str(i)) for i in range(n_domains)
    ]

    def assert_no_backends():
        for i in range(len(mms)):
            with pytest.raises(ua.BackendNotImplementedError):
                mms[i]()

    def assert_backend_active(backend):
        assert all(mms[i]() is backend.ret for i in range(len(mms)))

    assert_no_backends()

    with ua.set_backend(be):
        assert_backend_active(be)

    ua.set_global_backend(be)
    assert_backend_active(be)

    with ua.skip_backend(be):
        assert_no_backends()

    assert_backend_active(be)

    for i in range(len(mms)):
        ua.clear_backends(mms[i].domain, globals=True)

        with pytest.raises(ua.BackendNotImplementedError):
            mms[i]()

        for j in range(i + 1, len(mms)):
            assert mms[j]() is be.ret

    assert_no_backends()

    ua.register_backend(be)
    assert_backend_active(be)
Exemplo n.º 11
0
def test_function_attrs():
    def extractor():
        return ()

    def replacer(a, kw, d):
        return a, kw

    def default():
        return NotImplemented

    mm = ua.generate_multimethod(extractor,
                                 replacer,
                                 "ua_tests",
                                 default=default)

    assert mm.arg_extractor is extractor
    assert mm.arg_replacer is replacer
    assert mm.default is default
    assert mm.domain == "ua_tests"
Exemplo n.º 12
0
def nullary_mm():
    return ua.generate_multimethod(lambda: (), lambda a, kw, d: (a, kw),
                                   "ua_tests")
Exemplo n.º 13
0
        return self.my_types[0]()


class TypeA:
    @classmethod
    def __repr__(cls):
        return cls.__name__


class TypeB(TypeA):
    pass


class TypeC(TypeA):
    pass


BackendA = _TypedBackend(TypeA)
BackendB = _TypedBackend(TypeB)
BackendC = _TypedBackend(TypeC)
BackendAB = _TypedBackend(TypeA, TypeB)
BackendBC = _TypedBackend(TypeB, TypeC)

creation_multimethod = ua.generate_multimethod(lambda: (), lambda a, kw, d:
                                               (a, kw), "ua_examples")
call_multimethod = ua.generate_multimethod(
    lambda *a: tuple(ua.Dispatchable(x, "mark") for x in a),
    lambda a, kw, d: (a, kw),
    "ua_examples",
)