diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-10-21 08:31:52 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-10-21 08:43:19 +0300 |
commit | b5e6a1542676ac2636493eb78803c57d37fdeb1c (patch) | |
tree | 99120ac267a31afd36d8fbbbab0c0c357bf811e4 | |
parent | e7e3842c488b522105e8cdb33bd099e2747823ef (diff) | |
download | ydb-b5e6a1542676ac2636493eb78803c57d37fdeb1c.tar.gz |
Intermediate changes
commit_hash:04a153065be0050f5e911b9ff8b6dccbfe1b3cc8
23 files changed, 169 insertions, 85 deletions
diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA index a0ba8f627f..418a478f2c 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.112.3 +Version: 6.112.4 Summary: A library for property-based testing Home-page: https://hypothesis.works Author: David R. MacIver and Zac Hatfield-Dodds diff --git a/contrib/python/hypothesis/py3/_hypothesis_ftz_detector.py b/contrib/python/hypothesis/py3/_hypothesis_ftz_detector.py index abc1d65655..2c73530c9a 100644 --- a/contrib/python/hypothesis/py3/_hypothesis_ftz_detector.py +++ b/contrib/python/hypothesis/py3/_hypothesis_ftz_detector.py @@ -18,6 +18,14 @@ import of Hypothesis itself from each subprocess which must import the worker fu import importlib import sys +from typing import TYPE_CHECKING, Callable, Optional, Set, Tuple + +if TYPE_CHECKING: + from multiprocessing import Queue + from typing import TypeAlias + +FTZCulprits: "TypeAlias" = Tuple[Optional[bool], Set[str]] + KNOWN_EVER_CULPRITS = ( # https://moyix.blogspot.com/2022/09/someones-been-messing-with-my-subnormals.html @@ -35,16 +43,16 @@ KNOWN_EVER_CULPRITS = ( ) -def flush_to_zero(): +def flush_to_zero() -> bool: # If this subnormal number compares equal to zero we have a problem return 2.0**-1073 == 0 -def run_in_process(fn, *args): +def run_in_process(fn: Callable[..., FTZCulprits], *args: object) -> FTZCulprits: import multiprocessing as mp mp.set_start_method("spawn", force=True) - q = mp.Queue() + q: "Queue[FTZCulprits]" = mp.Queue() p = mp.Process(target=target, args=(q, fn, *args)) p.start() retval = q.get() @@ -52,15 +60,17 @@ def run_in_process(fn, *args): return retval -def target(q, fn, *args): +def target( + q: "Queue[FTZCulprits]", fn: Callable[..., FTZCulprits], *args: object +) -> None: q.put(fn(*args)) -def always_imported_modules(): +def always_imported_modules() -> FTZCulprits: return flush_to_zero(), set(sys.modules) -def modules_imported_by(mod): +def modules_imported_by(mod: str) -> FTZCulprits: """Return the set of modules imported transitively by mod.""" before = set(sys.modules) try: @@ -77,7 +87,7 @@ KNOWN_FTZ = None CHECKED_CACHE = set() -def identify_ftz_culprits(): +def identify_ftz_culprits() -> str: """Find the modules in sys.modules which cause "mod" to be imported.""" # If we've run this function before, return the same result. global KNOWN_FTZ @@ -94,7 +104,7 @@ def identify_ftz_culprits(): # that importing them in a new process sets the FTZ state. As a heuristic, we'll # start with packages known to have ever enabled FTZ, then top-level packages as # a way to eliminate large fractions of the search space relatively quickly. - def key(name): + def key(name: str) -> Tuple[bool, int, str]: """Prefer known-FTZ modules, then top-level packages, then alphabetical.""" return (name not in KNOWN_EVER_CULPRITS, name.count("."), name) diff --git a/contrib/python/hypothesis/py3/hypothesis/configuration.py b/contrib/python/hypothesis/py3/hypothesis/configuration.py index b7bc8879ce..cd9115533a 100644 --- a/contrib/python/hypothesis/py3/hypothesis/configuration.py +++ b/contrib/python/hypothesis/py3/hypothesis/configuration.py @@ -12,22 +12,22 @@ import os import sys import warnings from pathlib import Path +from typing import Union import _hypothesis_globals from hypothesis.errors import HypothesisSideeffectWarning __hypothesis_home_directory_default = Path.cwd() / ".hypothesis" - __hypothesis_home_directory = None -def set_hypothesis_home_dir(directory): +def set_hypothesis_home_dir(directory: Union[str, Path, None]) -> None: global __hypothesis_home_directory __hypothesis_home_directory = None if directory is None else Path(directory) -def storage_directory(*names, intent_to_write=True): +def storage_directory(*names: str, intent_to_write: bool = True) -> Path: if intent_to_write: check_sideeffect_during_initialization( "accessing storage for {}", "/".join(names) diff --git a/contrib/python/hypothesis/py3/hypothesis/errors.py b/contrib/python/hypothesis/py3/hypothesis/errors.py index 1dcf4493b2..7da59ebd90 100644 --- a/contrib/python/hypothesis/py3/hypothesis/errors.py +++ b/contrib/python/hypothesis/py3/hypothesis/errors.py @@ -214,7 +214,7 @@ class StopTest(BaseException): the Hypothesis engine, which should then continue normally. """ - def __init__(self, testcounter): + def __init__(self, testcounter: int) -> None: super().__init__(repr(testcounter)) self.testcounter = testcounter @@ -230,7 +230,7 @@ class Found(HypothesisException): class RewindRecursive(Exception): """Signal that the type inference should be rewound due to recursive types. Internal use only.""" - def __init__(self, target): + def __init__(self, target: object) -> None: self.target = target diff --git a/contrib/python/hypothesis/py3/hypothesis/extra/_patching.py b/contrib/python/hypothesis/py3/hypothesis/extra/_patching.py index b8fbfa3c7a..b508f199d6 100644 --- a/contrib/python/hypothesis/py3/hypothesis/extra/_patching.py +++ b/contrib/python/hypothesis/py3/hypothesis/extra/_patching.py @@ -18,11 +18,13 @@ discovered during testing, and by HypoFuzz for _covering_ examples discovered during fuzzing. """ +import ast import difflib import hashlib import inspect import re import sys +import types from ast import literal_eval from contextlib import suppress from datetime import date, datetime, timedelta, timezone @@ -31,6 +33,7 @@ from pathlib import Path import libcst as cst from libcst import matchers as m from libcst.codemod import CodemodContext, VisitorBasedCodemodCommand +from libcst.metadata import ExpressionContext, ExpressionContextProvider from hypothesis.configuration import storage_directory from hypothesis.version import __version__ @@ -148,18 +151,64 @@ def get_patch_for(func, failing_examples, *, strip_via=()): except Exception: return None + modules_in_test_scope = sorted( + ( + (k, v) + for (k, v) in module.__dict__.items() + if isinstance(v, types.ModuleType) + ), + key=lambda kv: len(kv[1].__name__), + ) + # The printed examples might include object reprs which are invalid syntax, # so we parse here and skip over those. If _none_ are valid, there's no patch. call_nodes = [] for ex, via in set(failing_examples): with suppress(Exception): - node = cst.parse_expression(ex) - assert isinstance(node, cst.Call), node + node = cst.parse_module(ex) + the_call = node.body[0].body[0].value + assert isinstance(the_call, cst.Call), the_call # Check for st.data(), which doesn't support explicit examples data = m.Arg(m.Call(m.Name("data"), args=[m.Arg(m.Ellipsis())])) - if m.matches(node, m.Call(args=[m.ZeroOrMore(), data, m.ZeroOrMore()])): + if m.matches(the_call, m.Call(args=[m.ZeroOrMore(), data, m.ZeroOrMore()])): return None + + # Many reprs use the unqualified name of the type, e.g. np.array() + # -> array([...]), so here we find undefined names and look them up + # on each module which was in the test's global scope. + names = {} + for anode in ast.walk(ast.parse(ex, "eval")): + if ( + isinstance(anode, ast.Name) + and isinstance(anode.ctx, ast.Load) + and anode.id not in names + and anode.id not in module.__dict__ + ): + for k, v in modules_in_test_scope: + if anode.id in v.__dict__: + names[anode.id] = cst.parse_expression(f"{k}.{anode.id}") + break + + # LibCST doesn't track Load()/Store() state of names by default, so we have + # to do a bit of a dance here, *and* explicitly handle keyword arguments + # which are treated as Load() context - but even if that's fixed later + # we'll still want to support older versions. + with suppress(Exception): + wrapper = cst.metadata.MetadataWrapper(node) + kwarg_names = { + a.keyword for a in m.findall(wrapper, m.Arg(keyword=m.Name())) + } + node = m.replace( + wrapper, + m.Name(value=m.MatchIfTrue(names.__contains__)) + & m.MatchMetadata(ExpressionContextProvider, ExpressionContext.LOAD) + & m.MatchIfTrue(lambda n, k=kwarg_names: n not in k), + replacement=lambda node, _, ns=names: ns[node.value], + ) + node = node.body[0].body[0].value + assert isinstance(node, cst.Call), node call_nodes.append((node, via)) + if not call_nodes: return None @@ -205,8 +254,8 @@ def make_patch(triples, *, msg="Hypothesis: add explicit examples", when=None): ud = difflib.unified_diff( source_before.splitlines(keepends=True), source_after.splitlines(keepends=True), - fromfile=str(fname), - tofile=str(fname), + fromfile=f"./{fname}", # git strips the first part of the path by default + tofile=f"./{fname}", ) diffs.append("".join(ud)) return "".join(diffs) diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/cache.py b/contrib/python/hypothesis/py3/hypothesis/internal/cache.py index a41cdb0549..8eb1bdba7e 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/cache.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/cache.py @@ -307,7 +307,7 @@ class LRUCache: # Anecdotally, OrderedDict seems quite competitive with lru_cache, but perhaps # that is localized to our access patterns. - def __init__(self, max_size): + def __init__(self, max_size: int) -> None: assert max_size > 0 self.max_size = max_size self._threadlocal = threading.local() diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/cathetus.py b/contrib/python/hypothesis/py3/hypothesis/internal/cathetus.py index 1f8f2fe82b..2012df4cdd 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/cathetus.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/cathetus.py @@ -12,7 +12,7 @@ from math import fabs, inf, isinf, isnan, nan, sqrt from sys import float_info -def cathetus(h, a): +def cathetus(h: float, a: float) -> float: """Given the lengths of the hypotenuse and a side of a right triangle, return the length of the other side. diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/compat.py b/contrib/python/hypothesis/py3/hypothesis/internal/compat.py index 4a3a94a084..df1ba067e9 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/compat.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/compat.py @@ -110,7 +110,7 @@ def int_to_byte(i: int) -> bytes: return bytes([i]) -def is_typed_named_tuple(cls): +def is_typed_named_tuple(cls: type) -> bool: """Return True if cls is probably a subtype of `typing.NamedTuple`. Unfortunately types created with `class T(NamedTuple):` actually diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py index 0f4f1138f3..2d24f984e5 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py @@ -271,7 +271,7 @@ class Example: return self.owner.labels[self.owner.label_indices[self.index]] @property - def parent(self): + def parent(self) -> Optional[int]: """The index of the example that this one is nested directly within.""" if self.index == 0: return None @@ -298,13 +298,13 @@ class Example: return self.owner.ir_ends[self.index] @property - def depth(self): + def depth(self) -> int: """Depth of this example in the example tree. The top-level example has a depth of 0.""" return self.owner.depths[self.index] @property - def trivial(self): + def trivial(self) -> bool: """An example is "trivial" if it only contains forced bytes and zero bytes. All examples start out as trivial, and then get marked non-trivial when we see a byte that is neither forced nor zero.""" @@ -352,6 +352,7 @@ class ExampleProperty: self.example_count = 0 self.block_count = 0 self.ir_node_count = 0 + self.result: Any = None def run(self) -> Any: """Rerun the test case with this visitor and return the @@ -425,7 +426,7 @@ def calculated_example_property(cls: Type[ExampleProperty]) -> Any: name = cls.__name__ cache_name = "__" + name - def lazy_calculate(self: "Examples") -> IntList: + def lazy_calculate(self: "Examples") -> Any: result = getattr(self, cache_name, None) if result is None: result = cls(self).run() @@ -465,7 +466,14 @@ class ExampleRecord: def freeze(self) -> None: self.__index_of_labels = None - def record_ir_draw(self, ir_type, value, *, kwargs, was_forced): + def record_ir_draw( + self, + ir_type: IRTypeName, + value: IRType, + *, + kwargs: IRKWargsType, + was_forced: bool, + ) -> None: self.trail.append(IR_NODE_RECORD) node = IRNode( ir_type=ir_type, @@ -517,7 +525,7 @@ class Examples: self.__children: "Optional[List[Sequence[int]]]" = None class _starts_and_ends(ExampleProperty): - def begin(self): + def begin(self) -> None: self.starts = IntList.of_length(len(self.examples)) self.ends = IntList.of_length(len(self.examples)) @@ -543,7 +551,7 @@ class Examples: return self.starts_and_ends[1] class _ir_starts_and_ends(ExampleProperty): - def begin(self): + def begin(self) -> None: self.starts = IntList.of_length(len(self.examples)) self.ends = IntList.of_length(len(self.examples)) @@ -570,7 +578,7 @@ class Examples: class _discarded(ExampleProperty): def begin(self) -> None: - self.result: "Set[int]" = set() # type: ignore # IntList in parent class + self.result: "Set[int]" = set() def finish(self) -> FrozenSet[int]: return frozenset(self.result) @@ -584,7 +592,7 @@ class Examples: class _trivial(ExampleProperty): def begin(self) -> None: self.nontrivial = IntList.of_length(len(self.examples)) - self.result: "Set[int]" = set() # type: ignore # IntList in parent class + self.result: "Set[int]" = set() def block(self, i: int) -> None: if not self.examples.blocks.trivial(i): @@ -610,7 +618,7 @@ class Examples: parentage: IntList = calculated_example_property(_parentage) class _depths(ExampleProperty): - def begin(self): + def begin(self) -> None: self.result = IntList.of_length(len(self.examples)) def start_example(self, i: int, label_index: int) -> None: @@ -619,10 +627,10 @@ class Examples: depths: IntList = calculated_example_property(_depths) class _ir_tree_nodes(ExampleProperty): - def begin(self): + def begin(self) -> None: self.result = [] - def ir_node(self, ir_node): + def ir_node(self, ir_node: "IRNode") -> None: self.result.append(ir_node) ir_tree_nodes: "List[IRNode]" = calculated_example_property(_ir_tree_nodes) @@ -788,7 +796,7 @@ class Blocks: prev = e @property - def last_block_length(self): + def last_block_length(self) -> int: return self.end(-1) - self.start(-1) def __len__(self) -> int: @@ -869,7 +877,7 @@ class Blocks: return result - def __check_completion(self): + def __check_completion(self) -> None: """The list of blocks is complete if we have created every ``Block`` object that we currently good and know that no more will be created. @@ -899,7 +907,7 @@ class Blocks: class _Overrun: status = Status.OVERRUN - def __repr__(self): + def __repr__(self) -> str: return "Overrun" @@ -1052,7 +1060,7 @@ class IRNode: and self.was_forced == other.was_forced ) - def __hash__(self): + def __hash__(self) -> int: return hash( ( self.ir_type, @@ -1062,7 +1070,7 @@ class IRNode: ) ) - def __repr__(self): + def __repr__(self) -> str: # 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}" @@ -1911,8 +1919,7 @@ class HypothesisProvider(PrimitiveProvider): "writeup - and good luck!" ) - def permitted(f): - assert isinstance(f, float) + def permitted(f: float) -> bool: if math.isnan(f): return allow_nan if 0 < abs(f) < smallest_nonzero_magnitude: @@ -2080,7 +2087,7 @@ class ConjectureData: self._node_index = 0 self.start_example(TOP_LABEL) - def __repr__(self): + def __repr__(self) -> str: return "ConjectureData(%s, %d bytes%s)" % ( self.status.name, len(self.buffer), diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py index 7126918736..8c8fd18add 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py @@ -197,6 +197,7 @@ StatisticsDict = TypedDict( "shrink-phase": NotRequired[PhaseStatistics], "stopped-because": NotRequired[str], "targets": NotRequired[Dict[str, float]], + "nodeid": NotRequired[str], }, ) diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/detection.py b/contrib/python/hypothesis/py3/hypothesis/internal/detection.py index 9d3496176a..8ce11808c3 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/detection.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/detection.py @@ -11,7 +11,7 @@ from types import MethodType -def is_hypothesis_test(test): +def is_hypothesis_test(test: object) -> bool: if isinstance(test, MethodType): return is_hypothesis_test(test.__func__) return getattr(test, "is_hypothesis_test", False) diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py b/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py index f352e9cb6d..bfe858ccfe 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/filtering.py @@ -331,9 +331,9 @@ def get_float_predicate_bounds(predicate: Predicate) -> ConstructivePredicate: return ConstructivePredicate(kwargs, predicate) -def max_len(size: int, element: Collection) -> bool: +def max_len(size: int, element: Collection[object]) -> bool: return len(element) <= size -def min_len(size: int, element: Collection) -> bool: +def min_len(size: int, element: Collection[object]) -> bool: return size <= len(element) diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/scrutineer.py b/contrib/python/hypothesis/py3/hypothesis/internal/scrutineer.py index 0cd760cf17..8f7aa4c503 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/scrutineer.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/scrutineer.py @@ -18,7 +18,7 @@ from collections import defaultdict from functools import lru_cache, reduce from os import sep from pathlib import Path -from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple +from typing import TYPE_CHECKING, Dict, Iterable, List, Optional, Set, Tuple from hypothesis._settings import Phase, Verbosity from hypothesis.internal.compat import PYPY @@ -35,7 +35,7 @@ Trace: TypeAlias = Set[Branch] @lru_cache(maxsize=None) -def should_trace_file(fname): +def should_trace_file(fname: str) -> bool: # fname.startswith("<") indicates runtime code-generation via compile, # e.g. compile("def ...", "<string>", "exec") in e.g. attrs methods. return not (is_hypothesis_file(fname) or fname.startswith("<")) @@ -55,12 +55,12 @@ class Tracer: __slots__ = ("branches", "_previous_location") - def __init__(self): + def __init__(self) -> None: self.branches: Trace = set() - self._previous_location = None + self._previous_location: Optional[Location] = None @staticmethod - def can_trace(): + def can_trace() -> bool: return ( (sys.version_info[:2] < (3, 12) and sys.gettrace() is None) or ( @@ -138,7 +138,7 @@ UNHELPFUL_LOCATIONS = ( ) -def _glob_to_re(locs): +def _glob_to_re(locs: Iterable[str]) -> str: """Translate a list of glob patterns to a combined regular expression. Only the * wildcard is supported, and patterns including special characters will only work by chance.""" diff --git a/contrib/python/hypothesis/py3/hypothesis/provisional.py b/contrib/python/hypothesis/py3/hypothesis/provisional.py index a6f1c4afc5..aac93b6a0e 100644 --- a/contrib/python/hypothesis/py3/hypothesis/provisional.py +++ b/contrib/python/hypothesis/py3/hypothesis/provisional.py @@ -20,6 +20,7 @@ definitions it links to. If not, report the bug! import string from importlib import resources +from typing import Optional from hypothesis import strategies as st from hypothesis.errors import InvalidArgument @@ -48,7 +49,9 @@ TOP_LEVEL_DOMAINS = ["COM", *sorted((d for d in _tlds if d != "ARPA"), key=len)] class DomainNameStrategy(st.SearchStrategy): @staticmethod - def clean_inputs(minimum, maximum, value, variable_name): + def clean_inputs( + minimum: int, maximum: int, value: Optional[int], variable_name: str + ) -> int: if value is None: value = maximum elif not isinstance(value, int): @@ -61,7 +64,9 @@ class DomainNameStrategy(st.SearchStrategy): ) return value - def __init__(self, max_length=None, max_element_length=None): + def __init__( + self, max_length: Optional[int] = None, max_element_length: Optional[int] = None + ) -> None: """ A strategy for :rfc:`1035` fully qualified domain names. @@ -165,7 +170,7 @@ _url_fragments_strategy = ( def urls() -> st.SearchStrategy[str]: """A strategy for :rfc:`3986`, generating http/https URLs.""" - def url_encode(s): + def url_encode(s: str) -> str: return "".join(c if c in URL_SAFE_CHARACTERS else "%%%02X" % ord(c) for c in s) schemes = st.sampled_from(["http", "https"]) diff --git a/contrib/python/hypothesis/py3/hypothesis/stateful.py b/contrib/python/hypothesis/py3/hypothesis/stateful.py index 711762d252..06e97b7ba5 100644 --- a/contrib/python/hypothesis/py3/hypothesis/stateful.py +++ b/contrib/python/hypothesis/py3/hypothesis/stateful.py @@ -1004,6 +1004,10 @@ class RuleStrategy(SearchStrategy): return (rule, arguments) def is_valid(self, rule): + for b in rule.bundles: + if not self.machine.bundle(b.name): + return False + predicates = self.machine._observability_predicates desc = f"{self.machine.__class__.__qualname__}, rule {rule.function.__name__}," for pred in rule.preconditions: @@ -1013,8 +1017,4 @@ class RuleStrategy(SearchStrategy): if not meets_precond: return False - for b in rule.bundles: - bundle = self.machine.bundle(b.name) - if not bundle: - return False return True diff --git a/contrib/python/hypothesis/py3/hypothesis/statistics.py b/contrib/python/hypothesis/py3/hypothesis/statistics.py index 465c92e9c1..bd3f4e3e30 100644 --- a/contrib/python/hypothesis/py3/hypothesis/statistics.py +++ b/contrib/python/hypothesis/py3/hypothesis/statistics.py @@ -10,20 +10,24 @@ import math from collections import Counter +from typing import TYPE_CHECKING, Dict, Iterable, List, cast from hypothesis._settings import Phase from hypothesis.utils.dynamicvariables import DynamicVariable +if TYPE_CHECKING: + from hypothesis.internal.conjecture.engine import PhaseStatistics, StatisticsDict + collector = DynamicVariable(None) -def note_statistics(stats_dict): +def note_statistics(stats_dict: "StatisticsDict") -> None: callback = collector.value if callback is not None: callback(stats_dict) -def describe_targets(best_targets): +def describe_targets(best_targets: Dict[str, float]) -> List[str]: """Return a list of lines describing the results of `target`, if any.""" # These lines are included in the general statistics description below, # but also printed immediately below failing examples to alleviate the @@ -41,7 +45,7 @@ def describe_targets(best_targets): return lines -def format_ms(times): +def format_ms(times: Iterable[float]) -> str: """Format `times` into a string representing approximate milliseconds. `times` is a collection of durations in seconds. @@ -60,7 +64,7 @@ def format_ms(times): return f"~ {lower}-{upper} ms" -def describe_statistics(stats_dict): +def describe_statistics(stats_dict: "StatisticsDict") -> str: """Return a multi-line string describing the passed run statistics. `stats_dict` must be a dictionary of data in the format collected by @@ -76,7 +80,7 @@ def describe_statistics(stats_dict): lines = [stats_dict["nodeid"] + ":\n"] if "nodeid" in stats_dict else [] prev_failures = 0 for phase in (p.name for p in list(Phase)[1:]): - d = stats_dict.get(phase + "-phase", {}) + d = cast("PhaseStatistics", stats_dict.get(phase + "-phase", {})) # Basic information we report for every phase cases = d.get("test-cases", []) if not cases: diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py index 41c9feb523..30de91e234 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py @@ -364,30 +364,31 @@ def convert_kwargs(name, kwargs): kwargs = dict(kwargs) signature = sig_of(name) + params = signature.parameters bound = signature.bind(DUMMY_RANDOM, **kwargs) bound.apply_defaults() for k in list(kwargs): if ( - kwargs[k] is signature.parameters[k].default - or signature.parameters[k].kind != inspect.Parameter.KEYWORD_ONLY + kwargs[k] is params[k].default + or params[k].kind != inspect.Parameter.KEYWORD_ONLY ): kwargs.pop(k) - arg_names = list(signature.parameters)[1:] + arg_names = list(params)[1:] args = [] for a in arg_names: - if signature.parameters[a].kind == inspect.Parameter.KEYWORD_ONLY: + if params[a].kind == inspect.Parameter.KEYWORD_ONLY: break args.append(bound.arguments[a]) kwargs.pop(a, None) while args: name = arg_names[len(args) - 1] - if args[-1] is signature.parameters[name].default: + if args[-1] is params[name].default: args.pop() else: break @@ -402,9 +403,13 @@ class TrueRandom(HypothesisRandom): self.__random = Random(seed) def _hypothesis_do_random(self, method, kwargs): + fn = getattr(self.__random, method) + try: + return fn(**kwargs) + except TypeError: + pass args, kwargs = convert_kwargs(method, kwargs) - - return getattr(self.__random, method)(*args, **kwargs) + return fn(*args, **kwargs) def __copy__(self): result = TrueRandom( diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/regex.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/regex.py index 8de137a422..b51e90ec0c 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/regex.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/regex.py @@ -39,8 +39,8 @@ UNICODE_CATEGORIES = set(categories()) SPACE_CHARS = set(" \t\n\r\f\v") UNICODE_SPACE_CHARS = SPACE_CHARS | set("\x1c\x1d\x1e\x1f\x85") UNICODE_DIGIT_CATEGORIES = {"Nd"} -UNICODE_SPACE_CATEGORIES = set(as_general_categories("Z")) -UNICODE_LETTER_CATEGORIES = set(as_general_categories("L")) +UNICODE_SPACE_CATEGORIES = set(as_general_categories(["Z"])) +UNICODE_LETTER_CATEGORIES = set(as_general_categories(["L"])) UNICODE_WORD_CATEGORIES = set(as_general_categories(["L", "N"])) # This is verbose, but correct on all versions of Python diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py index 53bee1fe22..dc7a129d06 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py @@ -29,7 +29,7 @@ from typing import ( ) from hypothesis._settings import HealthCheck, Phase, Verbosity, settings -from hypothesis.control import _current_build_context +from hypothesis.control import _current_build_context, current_build_context from hypothesis.errors import ( HypothesisException, HypothesisWarning, @@ -843,7 +843,7 @@ class MappedStrategy(SearchStrategy[Ex]): x = data.draw(self.mapped_strategy) result = self.pack(x) # type: ignore data.stop_example() - _current_build_context.value.record_call(result, self.pack, [x], {}) + current_build_context().record_call(result, self.pack, [x], {}) return result except UnsatisfiedAssumption: data.stop_example(discard=True) diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/types.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/types.py index 13e01b0b05..7288d8b73a 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/types.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/types.py @@ -304,24 +304,24 @@ def is_a_new_type(thing): return isinstance(thing, typing.NewType) -def is_a_union(thing): +def is_a_union(thing: object) -> bool: """Return True if thing is a typing.Union or types.UnionType (in py310).""" return isinstance(thing, UnionType) or get_origin(thing) is typing.Union -def is_a_type(thing): +def is_a_type(thing: object) -> bool: """Return True if thing is a type or a generic type like thing.""" return isinstance(thing, type) or is_generic_type(thing) or is_a_new_type(thing) -def is_typing_literal(thing): +def is_typing_literal(thing: object) -> bool: return get_origin(thing) in ( typing.Literal, getattr(typing_extensions, "Literal", object()), ) -def is_annotated_type(thing): +def is_annotated_type(thing: object) -> bool: return ( isinstance(thing, _AnnotatedAlias) and getattr(thing, "__args__", None) is not None diff --git a/contrib/python/hypothesis/py3/hypothesis/utils/dynamicvariables.py b/contrib/python/hypothesis/py3/hypothesis/utils/dynamicvariables.py index ad00cc8b48..cb823628b2 100644 --- a/contrib/python/hypothesis/py3/hypothesis/utils/dynamicvariables.py +++ b/contrib/python/hypothesis/py3/hypothesis/utils/dynamicvariables.py @@ -10,23 +10,26 @@ import threading from contextlib import contextmanager +from typing import Generator, Generic, TypeVar +T = TypeVar("T") -class DynamicVariable: - def __init__(self, default): + +class DynamicVariable(Generic[T]): + def __init__(self, default: T) -> None: self.default = default self.data = threading.local() @property - def value(self): + def value(self) -> T: return getattr(self.data, "value", self.default) @value.setter - def value(self, value): + def value(self, value: T) -> None: self.data.value = value @contextmanager - def with_value(self, value): + def with_value(self, value: T) -> Generator[None, None, None]: old_value = self.value try: self.data.value = value diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py index 59f3d40b73..a2112a2f36 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, 112, 3) +__version_info__ = (6, 112, 4) __version__ = ".".join(map(str, __version_info__)) diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make index d735c78f1a..7dc523a75e 100644 --- a/contrib/python/hypothesis/py3/ya.make +++ b/contrib/python/hypothesis/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(6.112.3) +VERSION(6.112.4) LICENSE(MPL-2.0) |