From 7fb0462cf06a5c21cf6c9272689acf12ab136af0 Mon Sep 17 00:00:00 2001 From: Stuart Cook Date: Tue, 25 Sep 2018 13:35:51 +1000 Subject: [PATCH] Add docstrings and comments for Example and Block --- hypothesis-python/RELEASE.rst | 4 ++ .../hypothesis/internal/conjecture/data.py | 43 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 hypothesis-python/RELEASE.rst diff --git a/hypothesis-python/RELEASE.rst b/hypothesis-python/RELEASE.rst new file mode 100644 index 0000000000..c36d6167ef --- /dev/null +++ b/hypothesis-python/RELEASE.rst @@ -0,0 +1,4 @@ +RELEASE_TYPE: patch + +This patch adds additional comments to some of the core engine's internal +data structures. There is no user-visible change. diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/data.py b/hypothesis-python/src/hypothesis/internal/conjecture/data.py index 569b4a2f98..cacaccf5e2 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/data.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/data.py @@ -43,9 +43,31 @@ def __repr__(self): @attr.s(slots=True) class Example(object): + """Examples track the hierarchical structure of draws from the byte stream. + + An example usually corresponds to a single draw from a strategy, and + includes that strategy's nested draws as children. There are also other + kinds of examples, such as leaf examples that correspond to individual + low-level blocks, and a single top-level example that spans the entire + input. + + Example-tracking allows the shrinker to try "high-level" transformations, + such as rearranging or deleting the elements of a list, without having + to understand their exact representation in the byte stream. + """ + + # Depth of this example in the example tree, which is equal to its number + # of ancestor examples. depth = attr.ib() + + # A label is an opaque value that associates each example with its + # approximate origin, such as a particular strategy class or a particular + # kind of draw. label = attr.ib() + + # Index of this example inside the overall list of examples. index = attr.ib() + start = attr.ib() end = attr.ib(default=None) @@ -53,7 +75,13 @@ class Example(object): # All examples start out as trivial, and then get marked non-trivial when # we see a byte that is neither forced nor zero. trivial = attr.ib(default=True) + + # True if this example can be discarded by the shrinker, without affecting + # the value produced by the enclosing example. Typically set when a + # rejection sampler decides to reject a generated value and try again. discarded = attr.ib(default=None) + + # List of child examples, represented as indices into the example list. children = attr.ib(default=attr.Factory(list)) @property @@ -63,11 +91,26 @@ def length(self): @attr.s(slots=True, frozen=True) class Block(object): + """Blocks track the flat list of lowest-level draws from the byte stream. + + Block-tracking allows the shrinker to try "low-level" + transformations, such as minimizing the numeric value of individual + blocks, or of pairs of blocks. + """ + start = attr.ib() end = attr.ib() + + # Index of this block inside the overall list of blocks. index = attr.ib() + # True if this block's byte values were forced by a write operation, and + # were not read from the input stream. Modifying those byte values in the + # shrinker is unlikely to be useful. forced = attr.ib() + + # True if this block's byte values are all 0. Reading this flag can be + # more convenient than explicitly checking a slice for non-zero bytes. all_zero = attr.ib() @property