diff --git a/hypothesis-python/src/hypothesis/stateful.py b/hypothesis-python/src/hypothesis/stateful.py index 669325ebef..f81808d99d 100644 --- a/hypothesis-python/src/hypothesis/stateful.py +++ b/hypothesis-python/src/hypothesis/stateful.py @@ -459,12 +459,14 @@ def __attrs_post_init__(self): self.arguments_strategies = {} bundles = [] for k, v in sorted(self.arguments.items()): - # assert not isinstance(v, BundleReferenceStrategy) + assert not isinstance(v, BundleReferenceStrategy) if isinstance(v, Bundle): bundles.append(v) consume = isinstance(v, BundleConsumer) - # v = BundleReferenceStrategy(v.name, consume=consume) + # order of initial values reverses when using new Bundle class + v = BundleReferenceStrategy(v.name, consume=consume) self.arguments_strategies[k] = v + print("TESTING: self.arguments_strategies: ", self.arguments_strategies) self.bundles = tuple(bundles) def __repr__(self) -> str: @@ -475,80 +477,63 @@ def __repr__(self) -> str: self_strategy = st.runner() +class BundleReferenceStrategy(SearchStrategy): + def __init__(self, name: str, *, consume: bool = False): + self.name = name + self.consume = consume -# class New_BundleReferenceStrategy(SampledFromStrategy): -# def __init__(self, name: str, *, consume: bool = False): -# self.name = name -# self.consume = consume -# self.elements = None - -# def initialize_with_bundle(self, bundle): -# super().__init__(bundle) - -# def do_draw(self, data): -# machine = data.draw(self_strategy) -# bundle = machine.bundle(self.name) -# if not bundle: -# data.mark_invalid(f"Cannot draw from empty bundle {self.name!r}") - -# if self.elements is None: -# self.initialize_with_bundle(bundle) -# self.elements = bundle - -# out = super().do_draw(data) -# if self.consume: -# # return bundle.pop(position) # pragma: no cover # coverage is flaky here -# bundle.remove(out) -# return out - - -# class BundleReferenceStrategy(SearchStrategy): -# def __init__(self, name: str, *, consume: bool = False): -# self.name = name -# self.consume = consume - -# def do_draw(self, data): -# machine = data.draw(self_strategy) -# # print("BundleReferenceStrategy do_draw machine: ", machine) -# bundle = machine.bundle(self.name) # TODO: why is data always 0 -# # print("BundleReferenceStrategy do_draw bundle: ", bundle) -# if not bundle: -# data.mark_invalid(f"Cannot draw from empty bundle {self.name!r}") -# # Shrink towards the right rather than the left. This makes it easier -# # to delete data generated earlier, as when the error is towards the -# # end there can be a lot of hard to remove padding. -# position = data.draw_integer(0, len(bundle) - 1, shrink_towards=len(bundle)) -# if self.consume: -# return bundle.pop(position) # pragma: no cover # coverage is flaky here -# else: -# return bundle[position] + def do_draw(self, data): + machine = data.draw(self_strategy) + # print("BundleReferenceStrategy do_draw machine: ", machine) + bundle = machine.bundle(self.name) + # print("BundleReferenceStrategy do_draw bundle: ", bundle) + if not bundle: + data.mark_invalid(f"Cannot draw from empty bundle {self.name!r}") + # Shrink towards the right rather than the left. This makes it easier + # to delete data generated earlier, as when the error is towards the + # end there can be a lot of hard to remove padding. + position = data.draw_integer(0, len(bundle) - 1, shrink_towards=len(bundle)) + if self.consume: + return bundle.pop(position) # pragma: no cover # coverage is flaky here + else: + return bundle[position] class Bundle(SampledFromStrategy): - def __init__(self, name: str, *, consume: bool = False) -> None: self.name = name # self.__reference_strategy = BundleReferenceStrategy(name, consume=consume) self.consume = consume + super().__init__( + # ("a", "b") + (1, 2, 3) + ) # Some random items that'll get replaced in do_draw def do_draw(self, data): machine = data.draw(self_strategy) print("New_Bundle do_draw machine: ", machine) - bundle = machine.bundle(self.name) # TODO: why is data always 0 + bundle = machine.bundle(self.name) print("New_Bundle do_draw bundle: ", bundle) - if not bundle: # Where do I initalize the superclass + if not bundle: data.mark_invalid(f"Cannot draw from empty bundle {self.name!r}") - + self.elements = bundle # if self.elements is None: # self.initialize_with_bundle(bundle) # self.elements = bundle + out = super().do_draw(data) if self.consume: bundle.remove(out) # pragma: no cover # coverage is flaky here return out + # position = data.draw_integer(0, len(bundle) - 1, shrink_towards=len(bundle)) + # if self.consume: + # return bundle.pop(position) # pragma: no cover # coverage is flaky here + # else: + # return bundle[position] + def __repr__(self): - consume = self.__reference_strategy.consume + consume = self.consume # __reference_strategy.consume if consume is False: return f"Bundle(name={self.name!r})" return f"Bundle(name={self.name!r}, {consume=})" @@ -565,55 +550,55 @@ def available(self, data): return bool(machine.bundle(self.name)) -class Old_Bundle(SearchStrategy[Ex]): - """A collection of values for use in stateful testing. +# class Bundle(SearchStrategy[Ex]): +# """A collection of values for use in stateful testing. - Bundles are a kind of strategy where values can be added by rules, - and (like any strategy) used as inputs to future rules. +# Bundles are a kind of strategy where values can be added by rules, +# and (like any strategy) used as inputs to future rules. - The ``name`` argument they are passed is the they are referred to - internally by the state machine; no two bundles may have - the same name. It is idiomatic to use the attribute - being assigned to as the name of the Bundle:: +# The ``name`` argument they are passed is the they are referred to +# internally by the state machine; no two bundles may have +# the same name. It is idiomatic to use the attribute +# being assigned to as the name of the Bundle:: - class MyStateMachine(RuleBasedStateMachine): - keys = Bundle("keys") +# class MyStateMachine(RuleBasedStateMachine): +# keys = Bundle("keys") - Bundles can contain the same value more than once; this becomes - relevant when using :func:`~hypothesis.stateful.consumes` to remove - values again. +# Bundles can contain the same value more than once; this becomes +# relevant when using :func:`~hypothesis.stateful.consumes` to remove +# values again. - If the ``consume`` argument is set to True, then all values that are - drawn from this bundle will be consumed (as above) when requested. - """ - - def __init__(self, name: str, *, consume: bool = False) -> None: - self.name = name - self.__reference_strategy = BundleReferenceStrategy(name, consume=consume) - - # def do_draw(self, data): - # machine = data.draw(self_strategy) - # print("Bundle do_draw machine: ", machine) - # reference = data.draw(self.__reference_strategy) - # print("Bundle do_draw reference: ", reference) - # return machine.names_to_values[reference.name] - - def __repr__(self): - consume = self.__reference_strategy.consume - if consume is False: - return f"Bundle(name={self.name!r})" - return f"Bundle(name={self.name!r}, {consume=})" +# If the ``consume`` argument is set to True, then all values that are +# drawn from this bundle will be consumed (as above) when requested. +# """ - def calc_is_empty(self, recur): - # We assume that a bundle will grow over time - return False +# def __init__(self, name: str, *, consume: bool = False) -> None: +# self.name = name +# self.__reference_strategy = BundleReferenceStrategy(name, consume=consume) - def available(self, data): - # ``self_strategy`` is an instance of the ``st.runner()`` strategy. - # Hence drawing from it only returns the current state machine without - # modifying the underlying buffer. - machine = data.draw(self_strategy) - return bool(machine.bundle(self.name)) +# def do_draw(self, data): +# machine = data.draw(self_strategy) +# # print("Bundle do_draw machine: ", machine) +# reference = data.draw(self.__reference_strategy) +# # print("Bundle do_draw reference: ", reference) +# return machine.names_to_values[reference.name] + +# def __repr__(self): +# consume = self.__reference_strategy.consume +# if consume is False: +# return f"Bundle(name={self.name!r})" +# return f"Bundle(name={self.name!r}, {consume=})" + +# def calc_is_empty(self, recur): +# # We assume that a bundle will grow over time +# return False + +# def available(self, data): +# # ``self_strategy`` is an instance of the ``st.runner()`` strategy. +# # Hence drawing from it only returns the current state machine without +# # modifying the underlying buffer. +# machine = data.draw(self_strategy) +# return bool(machine.bundle(self.name)) class BundleConsumer(Bundle): @@ -1072,7 +1057,9 @@ def rule_is_enabled(r): arguments = {} for k, strat in rule.arguments_strategies.items(): try: - arguments[k] = data.draw(strat) + example = data.draw(strat) + arguments[k] = example + print("TESTING: ", example) except Exception as err: rname = rule.function.__name__ add_note(err, f"while generating {k!r} from {strat!r} for rule {rname}")