diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-04-02 00:20:57 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-04-02 00:30:10 +0300 |
commit | 46966b4d9e58a39b178198c5b9a58ff545447c29 (patch) | |
tree | 276d742139795916b56b77e98881700d7385ccd6 | |
parent | 37228dd4d3c67d4556e242895d47a17927490844 (diff) | |
download | ydb-46966b4d9e58a39b178198c5b9a58ff545447c29.tar.gz |
Intermediate changes
10 files changed, 150 insertions, 61 deletions
diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA index 492afb5396..2e17c15b99 100644 --- a/contrib/python/hypothesis/py3/.dist-info/METADATA +++ b/contrib/python/hypothesis/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: hypothesis -Version: 6.99.6 +Version: 6.99.8 Summary: A library for property-based testing Home-page: https://hypothesis.works Author: David R. MacIver and Zac Hatfield-Dodds @@ -41,10 +41,10 @@ Requires-Dist: exceptiongroup >=1.0.0 ; python_version < "3.11" Provides-Extra: all Requires-Dist: black >=19.10b0 ; extra == 'all' Requires-Dist: click >=7.0 ; extra == 'all' -Requires-Dist: crosshair-tool >=0.0.50 ; extra == 'all' +Requires-Dist: crosshair-tool >=0.0.51 ; extra == 'all' Requires-Dist: django >=3.2 ; extra == 'all' Requires-Dist: dpcontracts >=0.4 ; extra == 'all' -Requires-Dist: hypothesis-crosshair >=0.0.1 ; extra == 'all' +Requires-Dist: hypothesis-crosshair >=0.0.2 ; extra == 'all' Requires-Dist: lark >=0.10.1 ; extra == 'all' Requires-Dist: libcst >=0.3.16 ; extra == 'all' Requires-Dist: numpy >=1.17.3 ; extra == 'all' @@ -63,8 +63,8 @@ Requires-Dist: rich >=9.0.0 ; extra == 'cli' Provides-Extra: codemods Requires-Dist: libcst >=0.3.16 ; extra == 'codemods' Provides-Extra: crosshair -Requires-Dist: hypothesis-crosshair >=0.0.1 ; extra == 'crosshair' -Requires-Dist: crosshair-tool >=0.0.50 ; extra == 'crosshair' +Requires-Dist: hypothesis-crosshair >=0.0.2 ; extra == 'crosshair' +Requires-Dist: crosshair-tool >=0.0.51 ; extra == 'crosshair' Provides-Extra: dateutil Requires-Dist: python-dateutil >=1.4 ; extra == 'dateutil' Provides-Extra: django diff --git a/contrib/python/hypothesis/py3/hypothesis/database.py b/contrib/python/hypothesis/py3/hypothesis/database.py index b53e8b8d5f..f584f08e1a 100644 --- a/contrib/python/hypothesis/py3/hypothesis/database.py +++ b/contrib/python/hypothesis/py3/hypothesis/database.py @@ -38,16 +38,20 @@ __all__ = [ ] -def _usable_dir(path: Path) -> bool: +def _usable_dir(path: os.PathLike) -> bool: """ - Returns True iff the desired path can be used as database path because + Returns True if the desired path can be used as database path because either the directory exists and can be used, or its root directory can be used and we can make the directory as needed. """ - while not path.exists(): - # Loop terminates because the root dir ('/' on unix) always exists. - path = path.parent - return path.is_dir() and os.access(path, os.R_OK | os.W_OK | os.X_OK) + path = Path(path) + try: + while not path.exists(): + # Loop terminates because the root dir ('/' on unix) always exists. + path = path.parent + return path.is_dir() and os.access(path, os.R_OK | os.W_OK | os.X_OK) + except PermissionError: + return False def _db_for_path(path=None): @@ -71,7 +75,7 @@ def _db_for_path(path=None): return InMemoryExampleDatabase() if path in (None, ":memory:"): return InMemoryExampleDatabase() - return DirectoryBasedExampleDatabase(str(path)) + return DirectoryBasedExampleDatabase(path) class _EDMeta(abc.ABCMeta): @@ -220,7 +224,7 @@ class DirectoryBasedExampleDatabase(ExampleDatabase): def save(self, key: bytes, value: bytes) -> None: # Note: we attempt to create the dir in question now. We # already checked for permissions, but there can still be other issues, - # e.g. the disk is full + # e.g. the disk is full, or permissions might have been changed. self._key_path(key).mkdir(exist_ok=True, parents=True) path = self._value_path(key, value) if not path.exists(): diff --git a/contrib/python/hypothesis/py3/hypothesis/errors.py b/contrib/python/hypothesis/py3/hypothesis/errors.py index 0d376a7493..d71f1c337e 100644 --- a/contrib/python/hypothesis/py3/hypothesis/errors.py +++ b/contrib/python/hypothesis/py3/hypothesis/errors.py @@ -8,7 +8,6 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. - class HypothesisException(Exception): """Generic parent class for exceptions thrown by Hypothesis.""" diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py index 24e97984fc..e29fc553fc 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py @@ -290,6 +290,14 @@ class Example: return self.owner.ends[self.index] @property + def ir_start(self) -> int: + return self.owner.ir_starts[self.index] + + @property + def ir_end(self) -> int: + return self.owner.ir_ends[self.index] + + @property def depth(self): """Depth of this example in the example tree. The top-level example has a depth of 0.""" @@ -529,6 +537,32 @@ class Examples: def ends(self) -> IntList: return self.starts_and_ends[1] + class _ir_starts_and_ends(ExampleProperty): + def begin(self): + self.starts = IntList.of_length(len(self.examples)) + self.ends = IntList.of_length(len(self.examples)) + + def start_example(self, i: int, label_index: int) -> None: + self.starts[i] = self.ir_node_count + + def stop_example(self, i: int, *, discarded: bool) -> None: + self.ends[i] = self.ir_node_count + + def finish(self) -> Tuple[IntList, IntList]: + return (self.starts, self.ends) + + ir_starts_and_ends: "Tuple[IntList, IntList]" = calculated_example_property( + _ir_starts_and_ends + ) + + @property + def ir_starts(self) -> IntList: + return self.ir_starts_and_ends[0] + + @property + def ir_ends(self) -> IntList: + return self.ir_starts_and_ends[1] + class _discarded(ExampleProperty): def begin(self) -> None: self.result: "Set[int]" = set() # type: ignore # IntList in parent class @@ -856,9 +890,6 @@ class _Overrun: def __repr__(self): return "Overrun" - def as_result(self) -> "_Overrun": - return self - Overrun = _Overrun() @@ -913,7 +944,7 @@ class DataObserver: pass -@attr.s(slots=True) +@attr.s(slots=True, repr=False, eq=False) class IRNode: ir_type: IRTypeName = attr.ib() value: IRType = attr.ib() @@ -931,6 +962,22 @@ class IRNode: was_forced=self.was_forced, ) + def __eq__(self, other): + if not isinstance(other, IRNode): + return NotImplemented + + return ( + self.ir_type == other.ir_type + and ir_value_equal(self.ir_type, self.value, other.value) + and ir_kwargs_equal(self.ir_type, self.kwargs, other.kwargs) + and self.was_forced == other.was_forced + ) + + def __repr__(self): + # repr to avoid "BytesWarning: str() on a bytes instance" for bytes nodes + forced_marker = " [forced]" if self.was_forced else "" + return f"{self.ir_type} {self.value!r}{forced_marker} {self.kwargs!r}" + def ir_value_permitted(value, ir_type, kwargs): if ir_type == "integer": @@ -965,6 +1012,24 @@ def ir_value_permitted(value, ir_type, kwargs): raise NotImplementedError(f"unhandled type {type(value)} of ir value {value}") +def ir_value_equal(ir_type, v1, v2): + if ir_type != "float": + return v1 == v2 + return float_to_int(v1) == float_to_int(v2) + + +def ir_kwargs_equal(ir_type, kwargs1, kwargs2): + if ir_type != "float": + return kwargs1 == kwargs2 + return ( + float_to_int(kwargs1["min_value"]) == float_to_int(kwargs2["min_value"]) + and float_to_int(kwargs1["max_value"]) == float_to_int(kwargs2["max_value"]) + and kwargs1["allow_nan"] == kwargs2["allow_nan"] + and kwargs1["smallest_nonzero_magnitude"] + == kwargs2["smallest_nonzero_magnitude"] + ) + + @dataclass_transform() @attr.s(slots=True) class ConjectureResult: @@ -1879,9 +1944,10 @@ class ConjectureData: if self.ir_tree_nodes is not None and observe: node = self._pop_ir_tree_node("integer", kwargs) - assert isinstance(node.value, int) - forced = node.value - fake_forced = not node.was_forced + if forced is None: + assert isinstance(node.value, int) + forced = node.value + fake_forced = True value = self.provider.draw_integer( **kwargs, forced=forced, fake_forced=fake_forced @@ -1935,9 +2001,10 @@ class ConjectureData: if self.ir_tree_nodes is not None and observe: node = self._pop_ir_tree_node("float", kwargs) - assert isinstance(node.value, float) - forced = node.value - fake_forced = not node.was_forced + if forced is None: + assert isinstance(node.value, float) + forced = node.value + fake_forced = True value = self.provider.draw_float( **kwargs, forced=forced, fake_forced=fake_forced @@ -1976,9 +2043,10 @@ class ConjectureData: ) if self.ir_tree_nodes is not None and observe: node = self._pop_ir_tree_node("string", kwargs) - assert isinstance(node.value, str) - forced = node.value - fake_forced = not node.was_forced + if forced is None: + assert isinstance(node.value, str) + forced = node.value + fake_forced = True value = self.provider.draw_string( **kwargs, forced=forced, fake_forced=fake_forced @@ -2011,9 +2079,10 @@ class ConjectureData: if self.ir_tree_nodes is not None and observe: node = self._pop_ir_tree_node("bytes", kwargs) - assert isinstance(node.value, bytes) - forced = node.value - fake_forced = not node.was_forced + if forced is None: + assert isinstance(node.value, bytes) + forced = node.value + fake_forced = True value = self.provider.draw_bytes( **kwargs, forced=forced, fake_forced=fake_forced @@ -2052,9 +2121,10 @@ class ConjectureData: if self.ir_tree_nodes is not None and observe: node = self._pop_ir_tree_node("boolean", kwargs) - assert isinstance(node.value, bool) - forced = node.value - fake_forced = not node.was_forced + if forced is None: + assert isinstance(node.value, bool) + forced = node.value + fake_forced = True value = self.provider.draw_boolean( **kwargs, forced=forced, fake_forced=fake_forced diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py index b0cf812298..6791b28e04 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py @@ -239,6 +239,11 @@ class ConjectureRunner: # correct engine. raise + def ir_tree_to_data(self, ir_tree_nodes): + data = ConjectureData.for_ir_tree(ir_tree_nodes) + self.__stoppable_test_function(data) + return data + def test_function(self, data): if self.__pending_call_explanation is not None: self.debug(self.__pending_call_explanation) @@ -273,7 +278,11 @@ class ConjectureRunner: self.debug_data(data) - if self.pareto_front is not None and self.pareto_front.add(data.as_result()): + if ( + data.target_observations + and self.pareto_front is not None + and self.pareto_front.add(data.as_result()) + ): self.save_buffer(data.buffer, sub_key=b"pareto") assert len(data.buffer) <= BUFFER_SIZE @@ -312,8 +321,7 @@ class ConjectureRunner: # drive the ir tree through the test function to convert it # to a buffer - data = ConjectureData.for_ir_tree(data.examples.ir_tree_nodes) - self.__stoppable_test_function(data) + data = self.ir_tree_to_data(data.examples.ir_tree_nodes) self.__data_cache[data.buffer] = data.as_result() key = data.interesting_origin diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/junkdrawer.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/junkdrawer.py index 4a2140eccd..61f9f37e51 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/junkdrawer.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/junkdrawer.py @@ -35,6 +35,8 @@ from hypothesis.errors import HypothesisWarning ARRAY_CODES = ["B", "H", "I", "L", "Q", "O"] +T = TypeVar("T") + def array_or_list( code: str, contents: Iterable[int] @@ -45,25 +47,25 @@ def array_or_list( def replace_all( - buffer: Sequence[int], - replacements: Iterable[Tuple[int, int, Sequence[int]]], -) -> bytes: - """Substitute multiple replacement values into a buffer. + ls: Sequence[T], + replacements: Iterable[Tuple[int, int, Sequence[T]]], +) -> List[T]: + """Substitute multiple replacement values into a list. Replacements is a list of (start, end, value) triples. """ - result = bytearray() + result: List[T] = [] prev = 0 offset = 0 for u, v, r in replacements: - result.extend(buffer[prev:u]) + result.extend(ls[prev:u]) result.extend(r) prev = v offset += len(r) - (v - u) - result.extend(buffer[prev:]) - assert len(result) == len(buffer) + offset - return bytes(result) + result.extend(ls[prev:]) + assert len(result) == len(ls) + offset + return result NEXT_ARRAY_CODE = dict(zip(ARRAY_CODES, ARRAY_CODES[1:])) @@ -190,9 +192,6 @@ def uniform(random: Random, n: int) -> bytes: return random.getrandbits(n * 8).to_bytes(n, "big") -T = TypeVar("T") - - class LazySequenceCopy: """A "copy" of a sequence that works by inserting a mask in front of the underlying sequence, so that you can mutate it without changing diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py index 5746ad6b9f..b67242cc78 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py @@ -376,8 +376,7 @@ class Shrinker: return self.engine.call_count def consider_new_tree(self, tree): - data = ConjectureData.for_ir_tree(tree) - self.engine.test_function(data) + data = self.engine.ir_tree_to_data(tree) return self.consider_new_buffer(data.buffer) @@ -1413,20 +1412,31 @@ class Shrinker: ex = chooser.choose(self.examples) label = chooser.choose(ex.children).label - group = [c for c in ex.children if c.label == label] - if len(group) <= 1: + examples = [c for c in ex.children if c.label == label] + if len(examples) <= 1: return - st = self.shrink_target - pieces = [st.buffer[ex.start : ex.end] for ex in group] - endpoints = [(ex.start, ex.end) for ex in group] + endpoints = [(ex.ir_start, ex.ir_end) for ex in examples] Ordering.shrink( - pieces, - lambda ls: self.consider_new_buffer( - replace_all(st.buffer, [(u, v, r) for (u, v), r in zip(endpoints, ls)]) + range(len(examples)), + lambda indices: self.consider_new_tree( + replace_all( + st.examples.ir_nodes, + [ + ( + u, + v, + st.examples.ir_nodes[ + examples[i].ir_start : examples[i].ir_end + ], + ) + for (u, v), i in zip(endpoints, indices) + ], + ) ), random=self.random, + key=lambda i: st.buffer[examples[i].start : examples[i].end], ) def run_block_program(self, i, description, original, repeats=1): diff --git a/contrib/python/hypothesis/py3/hypothesis/utils/conventions.py b/contrib/python/hypothesis/py3/hypothesis/utils/conventions.py index ec01326b49..ead205adc6 100644 --- a/contrib/python/hypothesis/py3/hypothesis/utils/conventions.py +++ b/contrib/python/hypothesis/py3/hypothesis/utils/conventions.py @@ -8,7 +8,6 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. - class UniqueIdentifier: """A factory for sentinel objects with nice reprs.""" diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py index 56b220d17c..afa2d3040a 100644 --- a/contrib/python/hypothesis/py3/hypothesis/version.py +++ b/contrib/python/hypothesis/py3/hypothesis/version.py @@ -8,5 +8,5 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. -__version_info__ = (6, 99, 6) +__version_info__ = (6, 99, 8) __version__ = ".".join(map(str, __version_info__)) diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make index 5174ace633..117eaa5eb0 100644 --- a/contrib/python/hypothesis/py3/ya.make +++ b/contrib/python/hypothesis/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(6.99.6) +VERSION(6.99.8) LICENSE(MPL-2.0) |