def _generate_state_machine(rules_object: type) -> type: bases = (_BrownieStateMachine, rules_object, sf.RuleBasedStateMachine) machine = type("BrownieStateMachine", bases, {}) strategies = { k: v for k, v in getmembers(rules_object) if isinstance(v, SearchStrategy) } for attr, fn in filter(_member_filter, getmembers(machine)): varnames = [[i] for i in fn.__code__.co_varnames[1:fn.__code__.co_argcount] ] if fn.__defaults__: for i in range(-1, -1 - len(fn.__defaults__), -1): varnames[i].append(fn.__defaults__[i]) if _attr_filter(attr, "initialize"): wrapped = sf.initialize( **{key[0]: strategies[key[-1]] for key in varnames}) setattr(machine, attr, wrapped(fn)) elif _attr_filter(attr, "invariant"): setattr(machine, attr, sf.invariant()(fn)) elif _attr_filter(attr, "rule"): wrapped = sf.rule( **{key[0]: strategies[key[-1]] for key in varnames}) setattr(machine, attr, wrapped(fn)) return machine
def another_invariant(self): raise ValueError() @rule() def do_stuff(self): pass run_state_machine_as_test(Invariant) @pytest.mark.parametrize( "decorators", [ (invariant(), rule()), (rule(), invariant()), (invariant(), initialize()), (initialize(), invariant()), (invariant(), precondition(lambda self: True), rule()), (rule(), precondition(lambda self: True), invariant()), (precondition(lambda self: True), invariant(), rule()), (precondition(lambda self: True), rule(), invariant()), ], ids=lambda x: "-".join(f.__qualname__.split(".")[0] for f in x), ) def test_invariant_and_rule_are_incompatible(decorators): """It's an error to apply @invariant and @rule to the same method.""" def method(self): pass for d in decorators[:-1]: