def test_dict_api_is_delegated_to_state(self): eng = bd.Engine() eng['a'] = 10 assert eng['a'] == 10 for key, val in eng.items(): assert key == 'a' assert val == 10 eng['b'] = 100 assert eng.b == 100 x = eng.pop('b') assert x == 100 with pytest.raises(AttributeError) as e: eng.b assert 'has no attribute' in str(e) eng.b = 100 eng_2 = bd.Engine() eng_2.a = 32 eng_2.c = 50 assert eng.a == 10 assert eng.b == 100 with pytest.raises(AttributeError): eng.c eng.update(eng_2) assert eng.a == 32 assert eng.b == 100 assert eng.c == 50 assert eng_2.a == 32 with pytest.raises(AttributeError): eng_2.b assert eng_2.c == 50
def test_can_pass_different_engine_to_function(self): eng_1, eng_2 = bd.Engine(), bd.Engine() eng_1.x = 10 eng_2.x = 20 def f(engine): return engine.x eng_1.register('f', f) assert eng_1.f() == [10] assert eng_1.f(eng_1) == [10] assert eng_1.f(eng_2) == [20]
def test_can_register_function_on_different_engines(self): eng = bd.Engine() eng_2 = bd.Engine() def f(engine): return 100 eng.register('do', f) ret = eng.event('do') assert ret == [100] eng_2.register('do', f) ret = eng_2.event('do') assert ret == [100]
def test_can_register_staticmethod(self): class Foo: @staticmethod def bar(a, b): return a * b eng = bd.Engine() eng.register('x', Foo.bar) eng.register('y', Foo().bar) assert eng.x(2, 3) == [6] assert eng.y(2, 3) == [6] class Foo: @bd.on('z') @staticmethod def bar(a, b): return a * b eng.register(Foo.bar) assert eng.z(2, 3) == [6] class Baz: @staticmethod @bd.on('w') def baz(a, b): return a * b eng.register(Baz.baz) assert eng.w(2, 3) == [6]
def test_can_assign_the_state_attribute(self): eng = bd.Engine() eng.a = 2 assert eng.a == 2 eng.state = {'a': 3} assert eng.a == 3 assert isinstance(eng.state, bd.State)
def test_can_assign_the_state_item(self): eng = bd.Engine() eng.a = 2 assert eng.a == 2 eng['state'] = {'a': 3} assert eng.a == 3 assert isinstance(eng.state, bd.State)
def test_can_use_event_name_to_call_func(self): eng = bd.Engine() def f(engine): return 100 eng.register('name', f) assert eng.name() == [100]
def test_can_set_attribute_to_state(self): eng = bd.Engine() eng.a = 10 assert eng.a == 10 assert eng['a'] == 10 eng['b'] = 15 assert eng.b == 15 assert eng['b'] == 15
def test_can_assign_the_state_attribute_only_with_mapping(self): eng = bd.Engine() with pytest.raises(TypeError) as e: eng.state = 5 assert 'Expected object of type mapping' in str(e) with pytest.raises(TypeError) as e: eng['state'] = 5 assert 'Expected object of type mapping' in str(e)
def test_can_register_function_single_event(self): eng = bd.Engine() def f(engine): return 100 eng.register('do', f) ret = eng.event('do') assert ret == [100]
def test_nested_dicts_of_assigned_state_items_become_state(self): eng = bd.Engine() eng.a = 2 assert eng.a == 2 eng['state'] = {'a': 3, 'b': {'c': 5}} assert eng.a == 3 assert isinstance(eng.state, bd.State) assert isinstance(eng.b, bd.State) assert eng.b.c == 5
def test_can_register_with_decorator(self): eng = bd.Engine() @bd.on('foo') def f(a, b): return a * b eng.register(f) assert eng.foo(2, 3) == [6]
def test_can_register_function_twice_but_runs_once(self): eng = bd.Engine() def f(engine): return 100 eng.register('do', f) eng.register('do', f) ret = eng.event('do') assert ret == [100]
def test_event_functions_return_eventreturnvalue_which_is_list(self): eng = bd.Engine() def f(engine): return 100 eng.register('do', f) ret = eng.event('do') assert isinstance(ret, list) assert isinstance(ret, bd.EventReturnValue)
def test_can_register_function_with_multiple_events(self): eng = bd.Engine() def f(engine): return 100 eng.register('do', 'do2', f) ret = eng.event('do') assert ret == [100] ret = eng.event('do2') assert ret == [100]
def test_can_not_set_reserved_attributes_and_items(self): from boardom.engine.engine import _API eng = bd.Engine() for key in _API: with pytest.raises(AttributeError) as e: setattr(eng, key, 100) assert 'Can not set' in str(e) with pytest.raises(KeyError) as e: eng[key] = 100 assert 'Can not set' in str(e)
def test_can_set_and_access_nested_attributes_and_items(self): eng = bd.Engine() eng.a = {'b': {'c': 10}} assert eng.a.b.c == 10 assert eng.a['b'].c == 10 assert eng.a.b['c'] == 10 assert eng['a.b.c'] == 10 eng['a.b.c'] = 15 assert eng.a.b.c == 15 assert eng.a['b'].c == 15 assert eng.a.b['c'] == 15 assert eng['a.b.c'] == 15
def test_can_register_object_members(self): class Foo: def __init__(self, val): self.val = val @bd.on('st') @staticmethod def static(a, b): return a * b @bd.on('meth') def method(self, a, b): return a * b * self.val @bd.on('meth_eng') def method_w_engine(self, a, b, engine): return a * b * self.val @staticmethod def static_no_on(self, a, b): return a * b * self.val def method_no_on(self, a, b): return a * b * self.val def to_attach(self, a, b): return a * b * self.val def attach(self, engine): engine.register('from_attach', self.to_attach) class DummyForStaticSelfVal: val = 7 obj = Foo(5) eng = bd.Engine().register(obj) eng.register('st_no_on', obj.static_no_on) eng.register('meth_no_on', obj.method_no_on) assert eng.st(2, 3) == [6] assert eng.meth(2, 3) == [30] assert eng.meth_eng(2, 3) == [30] assert eng.meth_eng(2, 3, eng) == [30] assert eng.st_no_on(DummyForStaticSelfVal, 2, 3) == [42] assert eng.meth_no_on(2, 3) == [30] assert eng.from_attach(2, 3) == [30]
def test_can_check_membership(self): eng = bd.Engine() eng.state = {'a': {'b': 10, 'd': ('f', 'g')}} assert 'a' in eng assert 'a.b' in eng assert 'c' not in eng assert 'a.c' not in eng assert 'a.d' in eng assert 'a.d.f' not in eng def f(engine): return 100 eng.register('do', f) assert 'f' not in eng assert 'do' not in eng
def test_can_register_class_members(self): class Foo: @bd.on('st') @staticmethod def static(a, b): return a * b @bd.on('meth') def method(self, a, b): return a * b @bd.on('meth_eng') def method_w_engine(self, a, b, engine): return a * b @staticmethod def static_no_on(self, a, b): return a * b def method_no_on(self, a, b): return a * b def to_attach(a, b): return a * b def attach(engine): engine.register('from_attach', Foo.to_attach) eng = bd.Engine().register(Foo) eng.register('st_no_on', Foo.static_no_on) eng.register('meth_no_on', Foo.method_no_on) assert eng.st(2, 3) == [6] assert eng.meth(None, 2, 3) == [6] with pytest.raises(TypeError) as e: eng.meth(2, 3) == [6] assert 'missing 1 required' in str(e) assert eng.meth_eng(None, 2, 3) == [6] with pytest.raises(TypeError) as e: eng.meth_eng(2, 3) == [6] assert 'missing 1 required' in str(e) assert eng.meth_eng(None, 2, 3, eng) == [6] assert eng.st_no_on(None, 2, 3) == [6] assert eng.meth_no_on(None, 2, 3) == [6] assert eng.from_attach(2, 3) == [6]
def test_works_when_function_called_from_other_engine(self): class A(bd.Engine): val = 2 @bd.on('foo') def f(self): return self.val a = A() b = bd.Engine().register(a) b.val = 3 assert a.val == 2 assert a.foo() == [2] assert a.foo(b) == [3] assert b.foo() == [3] assert b.foo(a) == [2]
def test_can_delete_item_and_attribute_from_state(self): eng = bd.Engine() eng['a'] = 10 eng.b = 42 assert eng['a'] == 10 assert eng.a == 10 assert eng['b'] == 42 assert eng.b == 42 del eng['a'] with pytest.raises(KeyError): eng['a'] with pytest.raises(AttributeError): eng.a assert eng.b == 42 del eng.b with pytest.raises(KeyError): eng['b'] with pytest.raises(AttributeError): eng.b
def test_can_pass_kwargs_to_func(self): eng = bd.Engine() def f(engine, a, b): return a * b def g(a, engine, b): return a * b def h(a, b, engine): return a * b eng.register('f', f) eng.register('g', g) eng.register('h', h) # f no engine assert eng.f(a=2, b=3) == [6] assert eng.f(2, b=3) == [6] # f with engine assert eng.f(eng, 2, b=3) == [6] assert eng.f(eng, a=2, b=3) == [6] assert eng.f(engine=eng, a=2, b=3) == [6] # g no engine assert eng.g(a=2, b=3) == [6] assert eng.g(2, b=3) == [6] # g with engine assert eng.g(2, eng, b=3) == [6] assert eng.g(2, engine=eng, b=3) == [6] assert eng.g(a=2, engine=eng, b=3) == [6] # h no engine assert eng.h(a=2, b=3) == [6] assert eng.h(2, b=3) == [6] # h with engine assert eng.h(2, 3, eng) == [6] assert eng.h(2, 3, engine=eng) == [6] assert eng.h(2, b=3, engine=eng) == [6] assert eng.h(a=2, b=3, engine=eng) == [6]
def test_cleanup_works(self): eng = bd.Engine() eng.state = {'a': 3, 'b': {'c': {'d': 15}, 'e': 1}, 'f': 3} with bd.CleanupState(eng): eng.state.d = 10 assert (eng.state.d) == 10 eng.state.g = {'h': {'j': 13}} assert eng.state.g.h.j == 13 eng.state.b.c.w = {'z': 2} assert eng.state.b.c.w.z == 2 assert 'b.c.w.z' in eng assert eng.state.a == 3 assert eng.state.b.c.d == 15 assert eng.state.b.e == 1 assert eng.state.f == 3 assert 'd' not in eng.state assert 'g.h.j' not in eng.state assert 'g.h' not in eng.state assert 'g' not in eng.state assert 'b.c.w' not in eng.state
def test_can_pass_args_to_func(self): eng = bd.Engine() def f(engine, a, b): return a * b def g(a, engine, b): return a * b def h(a, b, engine): return a * b def w(a, b): return a * b eng.register('f', f) eng.register('g', g) eng.register('h', h) eng.register('w', w) assert eng.f(2, 3) == [6] assert eng.g(2, 3) == [6] assert eng.h(2, 3) == [6] assert eng.w(2, 3) == [6]
def test_works_with_default_kwargs(self): eng_1 = bd.Engine() eng_1.x = 7 eng_2 = bd.Engine() eng_2.x = 11 def f(engine, a, b=5): return a * b * engine.x eng_1.register('f', f) # f eng_1 assert eng_1.f(2) == [70] assert eng_1.f(2, 3) == [42] assert eng_1.f(2, b=3) == [42] assert eng_1.f(a=2, b=3) == [42] # f eng_1 passed assert eng_1.f(2, engine=eng_1) == [70] assert eng_1.f(2, 3, engine=eng_1) == [42] assert eng_1.f(2, b=3, engine=eng_1) == [42] assert eng_1.f(a=2, engine=eng_1, b=3) == [42] # f eng_2 passed assert eng_1.f(2, engine=eng_2) == [110] assert eng_1.f(2, 3, engine=eng_2) == [66] assert eng_1.f(2, b=3, engine=eng_2) == [66] assert eng_1.f(a=2, engine=eng_2, b=3) == [66] def g(a, engine=eng_2, b=5): return a * b * engine.x eng_1.register('g', g) # g eng_2 is default assert eng_1.g(2) == [110] assert eng_1.g(2, 3) == [66] assert eng_1.g(2, b=3) == [66] assert eng_1.g(a=2, b=3) == [66] # g eng_1 passed kwarg assert eng_1.g(2, engine=eng_1) == [70] assert eng_1.g(2, 3, engine=eng_1) == [42] assert eng_1.g(2, b=3, engine=eng_1) == [42] assert eng_1.g(a=2, engine=eng_1, b=3) == [42] # g eng_1 passed arg assert eng_1.g(2, eng_1) == [70] assert eng_1.g(2, eng_1, 3) == [42] with pytest.raises(RuntimeError) as e: eng_1.g(2, 3, eng_1) assert 'extra args' in str(e) assert eng_1.g(2, eng_1, b=3) == [42] assert eng_1.g(engine=eng_1, a=2, b=3) == [42] # g eng_2 passed assert eng_1.g(2, engine=eng_2) == [110] assert eng_1.g(2, 3, engine=eng_2) == [66] assert eng_1.g(2, b=3, engine=eng_2) == [66] assert eng_1.g(a=2, engine=eng_2, b=3) == [66] def h(a=13, b=5, engine=eng_2): return a * b * engine.x eng_1.register('h', h) # h eng_2 is default assert eng_1.h() == [715] assert eng_1.h(2) == [110] assert eng_1.h(2, 3) == [66] assert eng_1.h(2, b=3) == [66] assert eng_1.h(a=2, b=3) == [66] # h eng_1 passed kwarg assert eng_1.h(2, engine=eng_1) == [70] assert eng_1.h(2, 3, engine=eng_1) == [42] assert eng_1.h(b=3, engine=eng_1) == [273] assert eng_1.h(2, b=3, engine=eng_1) == [42] assert eng_1.h(a=2, engine=eng_1, b=3) == [42] # h eng_1 passed arg with pytest.raises(RuntimeError) as e: eng_1.h(2, eng_1, b=3) assert 'extra args' in str(e) assert eng_1.h(2, 3, eng_1) == [42] # h eng_2 passed assert eng_1.h(2, engine=eng_2) == [110] assert eng_1.h(2, 3, engine=eng_2) == [66] assert eng_1.h(2, b=3, engine=eng_2) == [66] assert eng_1.h(a=2, engine=eng_2, b=3) == [66]
def test_can_set_item_to_state(self): eng = bd.Engine() eng['a'] = 10 assert eng['a'] == 10
def test_unregistered_events_run_with_any_args_and_kwargs_and_return_none( self, ): eng = bd.Engine() ret = eng.event('unreg') assert ret is None
def test_can_be_created(self): bd.Engine()
def test_can_register_lambda(self): eng = bd.Engine() eng.register('f', lambda engine, a, b: a * b) assert eng.f(2, 3) == [6]