Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate DataTree to the new IR #3818

Merged
merged 174 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
174 commits
Select commit Hold shift + click to select a range
9b356da
initial work on datatree ir migration
tybug Dec 19, 2023
cae9b3b
remove outdated comment
tybug Dec 19, 2023
b083a4f
move choice() method to ConjectureData
tybug Dec 27, 2023
b86ae5b
fix label name collision
tybug Dec 28, 2023
0095ec0
fix almost all shrinker tests
tybug Dec 28, 2023
4ab7c6e
fix optimiser tests
tybug Dec 28, 2023
9a01468
remove test duplicated in test_pareto
tybug Dec 28, 2023
842b732
fix most engine tests
tybug Dec 28, 2023
5c335e1
fix most pareto tests
tybug Dec 28, 2023
833c4cd
fix wrong data.choice usage
tybug Dec 28, 2023
23eafff
use existing count_between_floats
tybug Dec 28, 2023
1958a4c
migrate draw_bits in test_test_data
tybug Jan 6, 2024
ff0ffe6
migrate draw_bits in test_shrinking_dfas
tybug Jan 6, 2024
98947c4
remove ConjectureData#write in favor of draw_bytes(forced=...)
tybug Jan 6, 2024
d219cbf
remove test_draw_write_round_trip. This is better covered by test_for…
tybug Jan 6, 2024
720c750
fix test_float_encoding tests via buffers
tybug Jan 6, 2024
4b0a103
more ConjectureData#write / draw_bytes fixes
tybug Jan 6, 2024
98c93b3
add DRAW_FLOAT_INNER_LABEL to bring float shrinking back to normal
tybug Jan 6, 2024
6ed83ae
improve `minimal` readability with nonlocal
tybug Jan 6, 2024
56d78f1
add and use MAX_CHILDREN_EFFECTIVELY_INFINITE
tybug Jan 6, 2024
8a5a163
add cached_property comment
tybug Jan 6, 2024
dc95a63
use bit representation of floats for keys
tybug Jan 6, 2024
70f9c35
use unweighted sampling if rejection sampling is not making progress
tybug Jan 6, 2024
57fc9ac
more draw_bits -> draw_integer migrations
tybug Jan 6, 2024
8ea0dae
avoid 32 bit integers which draws more data
tybug Jan 6, 2024
4177416
fix test_example_depth_marking
tybug Jan 6, 2024
84a9eb3
spacing
tybug Jan 6, 2024
3f87784
fix test_child_indices for additional draw_boolean examples
tybug Jan 6, 2024
56613bc
add TODO for DRAW_BYTES_LABEL
tybug Jan 6, 2024
01b5cf3
increase test_last_block_length buffer to account for >24 bit integers
tybug Jan 6, 2024
4e314a1
fix test_can_observe_draws
tybug Jan 6, 2024
39d3436
more correct test_can_write_empty_bytes test
tybug Jan 7, 2024
4ab240d
never write exact-value pseudo choices to the IR
tybug Jan 7, 2024
bb2ba67
Merge branch 'various-core-touchups' into 'datatree-ir'
tybug Jan 11, 2024
12efba8
simplify compute_max_children for integers
tybug Jan 11, 2024
bacf301
Merge branch 'master' into datatree-ir
tybug Jan 11, 2024
46a0b1f
rename forced -> was_forced in observer
tybug Jan 11, 2024
142a13d
formatting
tybug Jan 11, 2024
e81d0ad
document `observe` argument
tybug Jan 11, 2024
4490070
add TODO for draw_bytes min/max size
tybug Jan 11, 2024
a154d56
update explore_arbitrary_languages test
tybug Jan 14, 2024
38e758b
note string values in test
tybug Jan 14, 2024
a854245
condition test_basic_indices_options on tuples, add more cases
tybug Jan 14, 2024
3e8a051
formatting
tybug Jan 14, 2024
a42c06c
move Intervals strategy to common
tybug Jan 14, 2024
b5178e5
factor our ir kwarg generation into tests.conjecture.common
tybug Jan 14, 2024
0bb0763
add draw_bytes size assert
tybug Jan 14, 2024
bfacdd2
fix incorrect draw_bits migrations
tybug Jan 14, 2024
dbbe785
handle empty intervals case in compute_max_children
tybug Jan 14, 2024
a1896b9
more reasonable draw_string_kwargs sizes
tybug Jan 14, 2024
97f96aa
linting
tybug Jan 14, 2024
b118cf0
add tests for single-value "choices" not writing to bistream
tybug Jan 14, 2024
1b6c46a
formatting
tybug Jan 14, 2024
99345f8
condition test_basic_indices_options on tuples, add more cases
tybug Jan 14, 2024
a74e468
move Intervals strategy to common
tybug Jan 14, 2024
ec3fe52
factor our ir kwarg generation into tests.conjecture.common
tybug Jan 14, 2024
46220fd
add draw_bytes size assert
tybug Jan 14, 2024
566f88e
fix incorrect draw_bits migrations
tybug Jan 14, 2024
03f22b0
more reasonable draw_string_kwargs sizes
tybug Jan 14, 2024
9970233
formatting
tybug Jan 14, 2024
77cd157
remove ConjectureData#write in favor of draw_bytes(forced=...)
tybug Jan 6, 2024
5e5e4e1
more ConjectureData#write / draw_bytes fixes
tybug Jan 6, 2024
76c48dc
update explore_arbitrary_languages test
tybug Jan 14, 2024
c6f1f8a
formatting
tybug Jan 14, 2024
cc58f53
migrate more draw_bits
tybug Jan 14, 2024
e706709
update test_dependent_block_pairs_is_up_to_shrinking_integers
tybug Jan 15, 2024
1b5c376
fix draw_float_kwargs for nan forced
tybug Jan 15, 2024
6df50bd
fix draw_string_kwargs computation
tybug Jan 15, 2024
6d24152
fix test_can_write_empty_bytes
tybug Jan 15, 2024
e41514b
rewrite float drawing for nan/clamper interaction
tybug Jan 15, 2024
017f20b
Merge branch 'master' of https://github.com/tybug/hypothesis into var…
tybug Jan 15, 2024
db69f87
Merge branch 'master' into various-touchups-2
tybug Jan 15, 2024
c5fba69
remove forgotten debug statement
tybug Jan 15, 2024
baf67f7
implement forced for out of bounds p in draw_boolean
tybug Jan 15, 2024
057271b
better draw_integers_kwargs comments and weights
tybug Jan 15, 2024
7e31ebd
rewrite nan/clamper handling, again
tybug Jan 15, 2024
156cfd0
add release notes
tybug Jan 15, 2024
8583a2d
return False with p=0, even if forced True
tybug Jan 15, 2024
7e2f80a
rework forced sampling to account for 0 probabilities
tybug Jan 15, 2024
f15ef5f
oops
tybug Jan 15, 2024
23f5e91
Merge branch 'master' into datatree-ir
tybug Jan 15, 2024
4c2e0c3
update test_integer_range_lower_equals_upper
tybug Jan 15, 2024
3cc51d4
update test_regression_1
tybug Jan 15, 2024
d72adfd
rewrite for clarity in Sampler.sample
tybug Jan 17, 2024
993b51b
more clear assume statement
tybug Jan 17, 2024
c760c55
improve draw_integer_kwargs distribution and speed
tybug Jan 17, 2024
d227ab8
add invariant to comment
tybug Jan 17, 2024
f0cd78b
improve draw_string_kwargs distribution and performance
tybug Jan 17, 2024
372a3e2
improve weight drawing in draw_integer_kwargs
tybug Jan 17, 2024
234f2ea
apparently 64 bit boolean draws are totally fine!
tybug Jan 17, 2024
a0e9cfb
fix accidentally weakened forced testing
tybug Jan 17, 2024
8a503f1
typo
tybug Jan 17, 2024
46cf059
rename intervals strategies, improve speed
tybug Jan 17, 2024
b4b88c5
change test format to avoid st.data()
tybug Jan 17, 2024
c3edf81
add use_{min, max}_value to draw_float_kwargs
tybug Jan 17, 2024
9b67c03
dont force sign bit if nans are allowed
tybug Jan 17, 2024
214b6c4
Merge branch 'test-forced-improvements' into datatree-ir
tybug Jan 17, 2024
575fd0e
Merge branch 'master' into datatree-ir
tybug Jan 17, 2024
280434f
revert fixed workaround for non-str notes
tybug Jan 17, 2024
9d1d316
delete release
tybug Jan 17, 2024
e2e820f
change outdated reference to draw_bits
tybug Jan 19, 2024
43506a9
fix compute_max_children case for integers, add simple test case
tybug Jan 19, 2024
007cc9d
add test for differentiating between 0.0 and -0.0 float draws
tybug Jan 19, 2024
3eb27b2
fix draw_string with single interval and equal bounds, and add test
tybug Jan 19, 2024
21db4bb
add IRType type alias
tybug Jan 19, 2024
6e42732
simplify helpers in generate_novel_prefix
tybug Jan 19, 2024
1b47296
import BUFFER_SIZE instead of redefining
tybug Jan 19, 2024
f575070
rewrite datatree documentation
tybug Jan 20, 2024
bfb8e69
avoid TypeAlias errors on python < 3.10
tybug Jan 20, 2024
b383a5c
extract draw_string max size to shared var
tybug Jan 20, 2024
aa999ba
move max_children > 1 assert
tybug Jan 20, 2024
b91783d
mark was_forced as keyword only
tybug Jan 20, 2024
f21b74d
use unbiased kwargs in data tree when stuck
tybug Jan 21, 2024
ff46d20
Merge branch 'master' into datatree-ir
tybug Jan 21, 2024
f9441a1
reword todo comment
tybug Jan 21, 2024
b41d425
revert accidental changes
tybug Jan 21, 2024
e66c88d
revert float changes
tybug Jan 21, 2024
6e2f394
let's just revert a bunch of stuff, shall we?
tybug Jan 21, 2024
dd6d377
formatting
tybug Jan 21, 2024
3ce8fdb
Merge branch 'more-test-changes' into datatree-ir
tybug Jan 22, 2024
245475f
nocover error case in datatree ir handling
tybug Jan 22, 2024
433ac7a
add observer param to fresh_data
tybug Jan 23, 2024
2defb40
add tests for observing and non-observing draws
tybug Jan 23, 2024
90e9600
rename test
tybug Jan 23, 2024
e7475a3
rewrite compute_max_children string case to be more correct
tybug Jan 23, 2024
42f2d17
add morecover tests for IntList
tybug Jan 23, 2024
a2dcfd9
avoid forcefully splitting on forced nodes
tybug Jan 23, 2024
4909988
Merge branch 'master' into datatree-ir
tybug Jan 23, 2024
e49c829
update test_targeting_can_drive_length_very_high with draw_boolean
tybug Jan 23, 2024
6d60e79
give up on novel prefixes when they are too hard to discover
tybug Jan 24, 2024
e26e5d1
kneecap inquisitor test (unfortunately)
tybug Jan 24, 2024
11c5681
give up completely on novel generation instead of returning non-novel
tybug Jan 24, 2024
4ab69f2
increase attempts budget
tybug Jan 24, 2024
9829729
kneecap test_discards_kill_branches for now
tybug Jan 24, 2024
df121e7
weaken test_one_dead_branch
tybug Jan 24, 2024
0f24890
fix compute_max_children for certain boolean draws
tybug Jan 24, 2024
38b0747
weaken test_lot_of_dead_nodes
tybug Jan 24, 2024
95d4f71
type observe params
tybug Jan 24, 2024
ab47af7
fix float keys being interpreted incorrectly in simulate_test_function
tybug Jan 25, 2024
c4de1c9
formatting
tybug Jan 25, 2024
931508d
add TooHard cover test
tybug Jan 25, 2024
6d5b1a9
nocover TooHard in generate_new_examples
tybug Jan 25, 2024
6469428
add types to ir kwargs/values
tybug Jan 25, 2024
bff153f
formatting
tybug Jan 25, 2024
cf786db
type datatree more
tybug Jan 25, 2024
9245460
some linting adjustments
tybug Jan 25, 2024
3cf8d3e
fix test_can_observe_draws
tybug Jan 25, 2024
4386a9a
fix lint rule
tybug Jan 25, 2024
cfb4439
add test for jsonable large ints
tybug Jan 25, 2024
459e96f
deflake test_finds_multiple_failures_in_generation
tybug Jan 25, 2024
7e422a0
deflake test_shrinks_both_failures
tybug Jan 25, 2024
9f1f0bf
add release notes
tybug Jan 25, 2024
d5a0edc
reword
tybug Jan 25, 2024
5832b5f
rewrite comment
tybug Jan 25, 2024
55e6c76
lint
tybug Jan 26, 2024
c15a19e
more consistent test_novel_prefix_gives_up_when_too_hard
tybug Jan 26, 2024
4deffdd
switch order of kwargs and ir_type in compute_max_children
tybug Jan 29, 2024
9040090
compute and draw from a set of available children instead of giving u…
tybug Jan 30, 2024
77680cb
fix ordering in floats_between
tybug Jan 31, 2024
c9eaf6c
add more ir tests
tybug Jan 31, 2024
bce60d5
no-branch on _draw_from_cache
tybug Jan 31, 2024
797d67c
account for 0 weight integers in children computation
tybug Jan 31, 2024
c8c326a
split asserts
tybug Jan 31, 2024
85316f4
format
tybug Jan 31, 2024
575b53b
deflake test_subtraction_of_intervals
tybug Feb 1, 2024
5058f50
fix float key representation in _draw_from_cache
tybug Feb 1, 2024
d9b0e0f
add cover test for hard floats
tybug Feb 2, 2024
3ff7e49
deflake test_can_generate_hard_floats
tybug Feb 3, 2024
a1eb9a9
more consistent conjecture float coverage
tybug Feb 4, 2024
db565f3
simpler Literal
tybug Feb 4, 2024
081e32e
wording
tybug Feb 4, 2024
285bbf9
more idiomatic unhandled ir_type error
tybug Feb 4, 2024
2c16f46
Merge branch 'master' into datatree-ir
Zac-HD Feb 4, 2024
4d4a32f
formatting
Zac-HD Feb 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions hypothesis-python/RELEASE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
RELEASE_TYPE: patch

This release improves our distribution of generated values for all strategies, by doing a better job of tracking which values we have generated before and avoiding generating them again.

For example, ``st.lists(st.integers())`` previously generated ~5 each of ``[]`` ``[0]`` in 100 examples. In this release, each of ``[]`` and ``[0]`` are generated ~1-2 times each.
189 changes: 149 additions & 40 deletions hypothesis-python/src/hypothesis/internal/conjecture/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
Set,
Tuple,
Type,
TypedDict,
TypeVar,
Union,
)
Expand Down Expand Up @@ -163,6 +164,8 @@ def structural_coverage(label: int) -> StructuralCoverageTag:

FLOAT_INIT_LOGIC_CACHE = LRUReusedCache(4096)

DRAW_STRING_DEFAULT_MAX_SIZE = 10**10 # "arbitrarily large"


class Example:
"""Examples track the hierarchical structure of draws from the byte stream,
Expand Down Expand Up @@ -794,6 +797,34 @@ def as_result(self) -> "_Overrun":
MAX_DEPTH = 100


class IntegerKWargs(TypedDict):
min_value: Optional[int]
max_value: Optional[int]
weights: Optional[Sequence[float]]
shrink_towards: int


class FloatKWargs(TypedDict):
min_value: float
max_value: float
allow_nan: bool
smallest_nonzero_magnitude: float


class StringKWargs(TypedDict):
intervals: IntervalSet
min_size: int
max_size: Optional[int]


class BytesKWargs(TypedDict):
size: int


class BooleanKWargs(TypedDict):
p: float


class DataObserver:
"""Observer class for recording the behaviour of a
ConjectureData object, primarily used for tracking
Expand All @@ -810,18 +841,34 @@ def conclude_test(
Note that this is called after ``freeze`` has completed.
"""

def draw_bits(self, n_bits: int, *, forced: bool, value: int) -> None:
"""Called when ``draw_bits`` is called on on the
observed ``ConjectureData``.
* ``n_bits`` is the number of bits drawn.
* ``forced`` is True if the corresponding
draw was forced or ``False`` otherwise.
* ``value`` is the result that ``draw_bits`` returned.
"""

def kill_branch(self) -> None:
"""Mark this part of the tree as not worth re-exploring."""

def draw_integer(
self, value: int, *, was_forced: bool, kwargs: IntegerKWargs
) -> None:
pass

def draw_float(
self, value: float, *, was_forced: bool, kwargs: FloatKWargs
) -> None:
pass

def draw_string(
self, value: str, *, was_forced: bool, kwargs: StringKWargs
) -> None:
pass

def draw_bytes(
self, value: bytes, *, was_forced: bool, kwargs: BytesKWargs
) -> None:
pass

def draw_boolean(
self, value: bool, *, was_forced: bool, kwargs: BooleanKWargs
) -> None:
pass


@dataclass_transform()
@attr.s(slots=True)
Expand Down Expand Up @@ -995,7 +1042,7 @@ def draw_integer(
assert min_value is not None
assert max_value is not None

sampler = Sampler(weights)
sampler = Sampler(weights, observe=False)
gap = max_value - shrink_towards

forced_idx = None
Expand Down Expand Up @@ -1023,7 +1070,7 @@ def draw_integer(
probe = shrink_towards + self._draw_unbounded_integer(
forced=None if forced is None else forced - shrink_towards
)
self._cd.stop_example(discard=max_value < probe)
self._cd.stop_example()
return probe

if max_value is None:
Expand All @@ -1034,7 +1081,7 @@ def draw_integer(
probe = shrink_towards + self._draw_unbounded_integer(
forced=None if forced is None else forced - shrink_towards
)
self._cd.stop_example(discard=probe < min_value)
self._cd.stop_example()
return probe

return self._draw_bounded_integer(
Expand Down Expand Up @@ -1091,7 +1138,7 @@ def draw_float(
assert pos_clamper is not None
clamped = pos_clamper(result)
if clamped != result and not (math.isnan(result) and allow_nan):
self._cd.stop_example(discard=True)
self._cd.stop_example()
self._cd.start_example(DRAW_FLOAT_LABEL)
self._draw_float(forced=clamped)
result = clamped
Expand All @@ -1113,7 +1160,7 @@ def draw_string(
forced: Optional[str] = None,
) -> str:
if max_size is None:
max_size = 10**10 # "arbitrarily large"
max_size = DRAW_STRING_DEFAULT_MAX_SIZE

assert forced is None or min_size <= len(forced) <= max_size

Expand All @@ -1129,6 +1176,7 @@ def draw_string(
max_size=max_size,
average_size=average_size,
forced=None if forced is None else len(forced),
observe=False,
)
while elements.more():
forced_i: Optional[int] = None
Expand Down Expand Up @@ -1264,7 +1312,7 @@ def _draw_bounded_integer(
probe = self._cd.draw_bits(
bits, forced=None if forced is None else abs(forced - center)
)
self._cd.stop_example(discard=probe > gap)
self._cd.stop_example()

if above:
result = center + probe
Expand Down Expand Up @@ -1356,7 +1404,7 @@ def permitted(f):
]
nasty_floats = [f for f in NASTY_FLOATS + boundary_values if permitted(f)]
weights = [0.2 * len(nasty_floats)] + [0.8] * len(nasty_floats)
sampler = Sampler(weights) if nasty_floats else None
sampler = Sampler(weights, observe=False) if nasty_floats else None

pos_clamper = neg_clamper = None
if sign_aware_lte(0.0, max_value):
Expand Down Expand Up @@ -1465,6 +1513,19 @@ def __repr__(self):
", frozen" if self.frozen else "",
)

# A bit of explanation of the `observe` argument in our draw_* functions.
#
# There are two types of draws: sub-ir and super-ir. For instance, some ir
# nodes use `many`, which in turn calls draw_boolean. But some strategies
# also use many, at the super-ir level. We don't want to write sub-ir draws
# to the DataTree (and consequently use them when computing novel prefixes),
# since they are fully recorded by writing the ir node itself.
# But super-ir draws are not included in the ir node, so we do want to write
# these to the tree.
#
# `observe` formalizes this distinction. The draw will only be written to
# the DataTree if observe is True.
Comment on lines +1516 to +1527
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love these explanatory comments 🤩


I'm also trying to think of a way to get rid of sub-ir draws as soon as possible. They're annoying to think about, we want to get rid of them soon anyway, and it's making managing the refactoring process harder. However I really don't see a way to do it without having the shrinker able to operate on the IR, so... I think this is the best we can do for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, they're unfortunate 😕. Agreed we kinda have to live with them for now. Dealing with the gotchas here has definitely bumped up "migrate the shrinker off the bitstream asap" on my task list.


def draw_integer(
self,
min_value: Optional[int] = None,
Expand All @@ -1474,6 +1535,7 @@ def draw_integer(
weights: Optional[Sequence[float]] = None,
shrink_towards: int = 0,
forced: Optional[int] = None,
observe: bool = True,
) -> int:
# Validate arguments
if weights is not None:
Expand All @@ -1494,13 +1556,18 @@ def draw_integer(
if forced is not None and max_value is not None:
assert forced <= max_value

return self.provider.draw_integer(
min_value=min_value,
max_value=max_value,
weights=weights,
shrink_towards=shrink_towards,
forced=forced,
)
kwargs: IntegerKWargs = {
"min_value": min_value,
"max_value": max_value,
"weights": weights,
"shrink_towards": shrink_towards,
}
value = self.provider.draw_integer(**kwargs, forced=forced)
if observe:
self.observer.draw_integer(
value, was_forced=forced is not None, kwargs=kwargs
)
return value

def draw_float(
self,
Expand All @@ -1514,6 +1581,7 @@ def draw_float(
# width: Literal[16, 32, 64] = 64,
# exclude_min and exclude_max handled higher up,
forced: Optional[float] = None,
observe: bool = True,
) -> float:
assert smallest_nonzero_magnitude > 0
assert not math.isnan(min_value)
Expand All @@ -1523,13 +1591,18 @@ def draw_float(
assert allow_nan or not math.isnan(forced)
assert math.isnan(forced) or min_value <= forced <= max_value

return self.provider.draw_float(
min_value=min_value,
max_value=max_value,
allow_nan=allow_nan,
smallest_nonzero_magnitude=smallest_nonzero_magnitude,
forced=forced,
)
kwargs: FloatKWargs = {
"min_value": min_value,
"max_value": max_value,
"allow_nan": allow_nan,
"smallest_nonzero_magnitude": smallest_nonzero_magnitude,
}
value = self.provider.draw_float(**kwargs, forced=forced)
if observe:
tybug marked this conversation as resolved.
Show resolved Hide resolved
self.observer.draw_float(
value, kwargs=kwargs, was_forced=forced is not None
)
return value

def draw_string(
self,
Expand All @@ -1538,19 +1611,44 @@ def draw_string(
min_size: int = 0,
max_size: Optional[int] = None,
forced: Optional[str] = None,
observe: bool = True,
) -> str:
assert forced is None or min_size <= len(forced)
return self.provider.draw_string(
intervals, min_size=min_size, max_size=max_size, forced=forced
)

def draw_bytes(self, size: int, *, forced: Optional[bytes] = None) -> bytes:
kwargs: StringKWargs = {
"intervals": intervals,
"min_size": min_size,
"max_size": max_size,
}
value = self.provider.draw_string(**kwargs, forced=forced)
if observe:
self.observer.draw_string(
value, kwargs=kwargs, was_forced=forced is not None
)
return value

def draw_bytes(
self,
# TODO move to min_size and max_size here.
size: int,
*,
forced: Optional[bytes] = None,
observe: bool = True,
) -> bytes:
assert forced is None or len(forced) == size
assert size >= 0

return self.provider.draw_bytes(size, forced=forced)
kwargs: BytesKWargs = {"size": size}
value = self.provider.draw_bytes(**kwargs, forced=forced)
if observe:
self.observer.draw_bytes(
value, kwargs=kwargs, was_forced=forced is not None
)
return value

def draw_boolean(self, p: float = 0.5, *, forced: Optional[bool] = None) -> bool:
def draw_boolean(
self, p: float = 0.5, *, forced: Optional[bool] = None, observe: bool = True
) -> bool:
# Internally, we treat probabilities lower than 1 / 2**64 as
# unconditionally false.
#
Expand All @@ -1561,7 +1659,13 @@ def draw_boolean(self, p: float = 0.5, *, forced: Optional[bool] = None) -> bool
if forced is False:
assert p < (1 - 2 ** (-64))

return self.provider.draw_boolean(p, forced=forced)
kwargs: BooleanKWargs = {"p": p}
value = self.provider.draw_boolean(**kwargs, forced=forced)
if observe:
self.observer.draw_boolean(
value, kwargs=kwargs, was_forced=forced is not None
)
return value

def as_result(self) -> Union[ConjectureResult, _Overrun]:
"""Convert the result of running this test into
Expand Down Expand Up @@ -1735,9 +1839,15 @@ def freeze(self) -> None:
self.buffer = bytes(self.buffer)
self.observer.conclude_test(self.status, self.interesting_origin)

def choice(self, values: Sequence[T], *, forced: Optional[T] = None) -> T:
def choice(
self,
values: Sequence[T],
*,
forced: Optional[T] = None,
observe: bool = True,
) -> T:
forced_i = None if forced is None else values.index(forced)
i = self.draw_integer(0, len(values) - 1, forced=forced_i)
i = self.draw_integer(0, len(values) - 1, forced=forced_i, observe=observe)
return values[i]

def draw_bits(self, n: int, *, forced: Optional[int] = None) -> int:
Expand Down Expand Up @@ -1774,7 +1884,6 @@ def draw_bits(self, n: int, *, forced: Optional[int] = None) -> int:
buf = bytes(buf)
result = int_from_bytes(buf)

self.observer.draw_bits(n, forced=forced is not None, value=result)
self.__example_record.draw_bits(n, forced)

initial = self.index
Expand Down
Loading
Loading