diff options
| author | robot-piglet <[email protected]> | 2026-01-27 19:49:57 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2026-01-27 20:05:06 +0300 |
| commit | 16640372fcf3116ecc90e1b7803259ffe9ea15c7 (patch) | |
| tree | 6781488f1126fc199395aeacde9293bb25b05e82 /contrib/python/hypothesis | |
| parent | 8bf05dead435a8f34dbbf361ddbaa0c3a3dfc6ab (diff) | |
Intermediate changes
commit_hash:be732149e5a1dae2b48ade4b97e3d3472f6a479c
Diffstat (limited to 'contrib/python/hypothesis')
7 files changed, 62 insertions, 37 deletions
diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA index 5ad4e36bad2..d35d0315bd9 100644 --- a/contrib/python/hypothesis/py3/.dist-info/METADATA +++ b/contrib/python/hypothesis/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: hypothesis -Version: 6.150.0 +Version: 6.150.1 Summary: The property-based testing library for Python Author-email: "David R. MacIver and Zac Hatfield-Dodds" <[email protected]> License-Expression: MPL-2.0 diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py index 9ac26e1cbaf..8c6ea5c4f1e 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py @@ -646,12 +646,12 @@ class ConjectureData: self.overdraw = 0 self._random = random - self.length = 0 - self.index = 0 - self.output = "" - self.status = Status.VALID - self.frozen = False - self.testcounter = threadlocal.global_test_counter + self.length: int = 0 + self.index: int = 0 + self.output: str = "" + self.status: Status = Status.VALID + self.frozen: bool = False + self.testcounter: int = threadlocal.global_test_counter threadlocal.global_test_counter += 1 self.start_time = time.perf_counter() self.gc_start_time = gc_cumulative_time() @@ -659,8 +659,8 @@ class ConjectureData: self.interesting_origin: InterestingOrigin | None = None self.draw_times: dict[str, float] = {} self._stateful_run_times: dict[str, float] = defaultdict(float) - self.max_depth = 0 - self.has_discards = False + self.max_depth: int = 0 + self.has_discards: bool = False self.provider: PrimitiveProvider = ( provider(self, **provider_kw) if isinstance(provider, type) else provider @@ -683,9 +683,8 @@ class ConjectureData: # examples for reporting purposes. self.__spans: Spans | None = None - # We want the top level span to have depth 0, so we start - # at -1. - self.depth = -1 + # We want the top level span to have depth 0, so we start at -1. + self.depth: int = -1 self.__span_record = SpanRecord() # Slice indices for discrete reportable parts that which-parts-matter can diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py index 3a1c1944b4c..531797c7ab0 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py @@ -911,10 +911,14 @@ class ConjectureRunner: status = repr(data.status) if data.status == Status.INTERESTING: status = f"{status} ({data.interesting_origin!r})" + elif data.status == Status.INVALID and isinstance(data, ConjectureData): + assert isinstance(data, ConjectureData) # mypy is silly + status = f"{status} ({data.events.get('invalid because', '?')})" + newline_tab = "\n\t" self.debug( - f"{len(data.choices)} choices {data.choices} -> {status}" - f"{', ' + data.output if data.output else ''}" + f"{len(data.choices)} choices -> {status}\n\t{data.choices}" + f"{newline_tab + data.output if data.output else ''}" ) def observe_for_provider(self) -> AbstractContextManager: diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py index 1006fc792d6..a9fbc392a9c 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py @@ -1857,18 +1857,16 @@ def recursive( base: SearchStrategy[Ex], extend: Callable[[SearchStrategy[Any]], SearchStrategy[T]], *, - min_leaves: int = 1, + min_leaves: int | None = None, max_leaves: int = 100, ) -> SearchStrategy[T | Ex]: """base: A strategy to start from. extend: A function which takes a strategy and returns a new strategy. - min_leaves: The minimum number of elements to be drawn from base on a given - run. + min_leaves: The minimum number of elements to be drawn from base on a given run. - max_leaves: The maximum number of elements to be drawn from base on a given - run. + max_leaves: The maximum number of elements to be drawn from base on a given run. This returns a strategy ``S`` such that ``S = extend(base | S)``. That is, values may be drawn from base, or from any strategy reachable by mixing @@ -1882,9 +1880,7 @@ def recursive( Examples from this strategy shrink by trying to reduce the amount of recursion and by shrinking according to the shrinking behaviour of base and the result of extend. - """ - return RecursiveStrategy(base, extend, min_leaves, max_leaves) diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/recursive.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/recursive.py index 2621600cc40..e9af4c063b0 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/recursive.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/recursive.py @@ -10,11 +10,13 @@ import threading import warnings +from collections.abc import Callable from contextlib import contextmanager from hypothesis.errors import HypothesisWarning, InvalidArgument from hypothesis.internal.reflection import ( get_pretty_function_description, + is_first_param_referenced_in_function, is_identity_function, ) from hypothesis.internal.validation import check_type @@ -23,6 +25,7 @@ from hypothesis.strategies._internal.strategies import ( SearchStrategy, check_strategy, ) +from hypothesis.utils.deprecation import note_deprecation class LimitReached(BaseException): @@ -76,7 +79,13 @@ class LimitedStrategy(SearchStrategy): class RecursiveStrategy(SearchStrategy): - def __init__(self, base, extend, min_leaves, max_leaves): + def __init__( + self, + base: SearchStrategy, + extend: Callable[[SearchStrategy], SearchStrategy], + min_leaves: int | None, + max_leaves: int, + ): super().__init__() self.min_leaves = min_leaves self.max_leaves = max_leaves @@ -84,19 +93,11 @@ class RecursiveStrategy(SearchStrategy): self.limited_base = LimitedStrategy(base) self.extend = extend - if is_identity_function(extend): - warnings.warn( - "extend=lambda x: x is a no-op; you probably want to use a " - "different extend function, or just use the base strategy directly.", - HypothesisWarning, - stacklevel=5, - ) - strategies = [self.limited_base, self.extend(self.limited_base)] while 2 ** (len(strategies) - 1) <= max_leaves: strategies.append(extend(OneOfStrategy(tuple(strategies)))) # If min_leaves > 1, we can never draw from base directly - if min_leaves > 1: + if min_leaves is not None and min_leaves > 1: strategies = strategies[1:] self.strategy = OneOfStrategy(strategies) @@ -115,9 +116,34 @@ class RecursiveStrategy(SearchStrategy): check_strategy(extended, f"extend({self.limited_base!r})") self.limited_base.validate() extended.validate() - check_type(int, self.min_leaves, "min_leaves") + + if is_identity_function(self.extend): + warnings.warn( + "extend=lambda x: x is a no-op; you probably want to use a " + "different extend function, or just use the base strategy directly.", + HypothesisWarning, + stacklevel=5, + ) + + if not is_first_param_referenced_in_function(self.extend): + msg = ( + f"extend={get_pretty_function_description(self.extend)} doesn't use " + "it's argument, and thus can't actually recurse!" + ) + if self.min_leaves is None: + note_deprecation( + msg, + since="2026-01-12", + has_codemod=False, + stacklevel=1, + ) + else: + raise InvalidArgument(msg) + + if self.min_leaves is not None: + check_type(int, self.min_leaves, "min_leaves") check_type(int, self.max_leaves, "max_leaves") - if self.min_leaves <= 0: + if self.min_leaves is not None and self.min_leaves <= 0: raise InvalidArgument( f"min_leaves={self.min_leaves!r} must be greater than zero" ) @@ -125,7 +151,7 @@ class RecursiveStrategy(SearchStrategy): raise InvalidArgument( f"max_leaves={self.max_leaves!r} must be greater than zero" ) - if self.min_leaves > self.max_leaves: + if (self.min_leaves or 1) > self.max_leaves: raise InvalidArgument( f"min_leaves={self.min_leaves!r} must be less than or equal to " f"max_leaves={self.max_leaves!r}" @@ -138,7 +164,7 @@ class RecursiveStrategy(SearchStrategy): with self.limited_base.capped(self.max_leaves): result = data.draw(self.strategy) leaves_drawn = self.max_leaves - self.limited_base.marker - if leaves_drawn < self.min_leaves: + if self.min_leaves and leaves_drawn < self.min_leaves: data.events[ f"Draw for {self!r} had fewer than " f"min_leaves={self.min_leaves} and had to be retried" diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py index 2ac8a20a828..7b87895ce34 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, 150, 0) +__version_info__ = (6, 150, 1) __version__ = ".".join(map(str, __version_info__)) diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make index e949f9b0fa8..b003a5080ff 100644 --- a/contrib/python/hypothesis/py3/ya.make +++ b/contrib/python/hypothesis/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(6.150.0) +VERSION(6.150.1) LICENSE(MPL-2.0) |
