diff options
| author | robot-piglet <[email protected]> | 2025-11-19 10:16:42 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2025-11-19 10:29:21 +0300 |
| commit | ccd5394bd239df01603ee6fa4adb04ea8389cf85 (patch) | |
| tree | 1fb10dba55fbd344904aaf26bd22abcbba1d6faa /contrib/python | |
| parent | 8c1573d7b800bff882ae5a8bb66e8c85dabc1777 (diff) | |
Intermediate changes
commit_hash:a0c75506f0d1cf5a6805d32237dc5b93c517de28
Diffstat (limited to 'contrib/python')
41 files changed, 314 insertions, 222 deletions
diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA index fa535de452c..be7f9497fd0 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.144.0 +Version: 6.145.1 Summary: A library for property-based testing Author-email: "David R. MacIver and Zac Hatfield-Dodds" <[email protected]> License-Expression: MPL-2.0 @@ -33,7 +33,6 @@ Classifier: Typing :: Typed Requires-Python: >=3.10 Description-Content-Type: text/markdown License-File: LICENSE.txt -Requires-Dist: attrs>=22.2.0 Requires-Dist: exceptiongroup>=1.0.0; python_version < "3.11" Requires-Dist: sortedcontainers<3.0.0,>=2.1.0 Provides-Extra: cli diff --git a/contrib/python/hypothesis/py3/hypothesis/core.py b/contrib/python/hypothesis/py3/hypothesis/core.py index 9315b89a8a4..3cc6a4e85ed 100644 --- a/contrib/python/hypothesis/py3/hypothesis/core.py +++ b/contrib/python/hypothesis/py3/hypothesis/core.py @@ -157,7 +157,7 @@ global_force_seed = None threadlocal = ThreadLocal(_hypothesis_global_random=lambda: None) -@dataclass +@dataclass(slots=True, frozen=False) class Example: args: Any kwargs: Any @@ -718,7 +718,7 @@ def get_random_for_wrapped_test(test, wrapped_test): return Random(seed) -@dataclass +@dataclass(slots=True, frozen=False) class Stuff: selfy: Any args: tuple @@ -1622,7 +1622,7 @@ def fake_subTest(self, msg=None, **__): yield -@dataclass +@dataclass(slots=False, frozen=False) class HypothesisHandle: """This object is provided as the .hypothesis attribute on @given tests. diff --git a/contrib/python/hypothesis/py3/hypothesis/extra/pandas/impl.py b/contrib/python/hypothesis/py3/hypothesis/extra/pandas/impl.py index 7160566f62e..4d4c00f1277 100644 --- a/contrib/python/hypothesis/py3/hypothesis/extra/pandas/impl.py +++ b/contrib/python/hypothesis/py3/hypothesis/extra/pandas/impl.py @@ -11,10 +11,10 @@ from collections import OrderedDict, abc from collections.abc import Sequence from copy import copy +from dataclasses import dataclass from datetime import datetime, timedelta from typing import Any, Generic, Union -import attr import numpy as np import pandas @@ -25,7 +25,6 @@ from hypothesis.errors import InvalidArgument from hypothesis.extra import numpy as npst from hypothesis.internal.conjecture import utils as cu from hypothesis.internal.coverage import check, check_function -from hypothesis.internal.reflection import get_pretty_function_description from hypothesis.internal.validation import ( check_type, check_valid_interval, @@ -364,7 +363,7 @@ def series( return result() [email protected](slots=True) +@dataclass(slots=True, frozen=False) class column(Generic[Ex]): """Data object for describing a column in a DataFrame. @@ -382,11 +381,11 @@ class column(Generic[Ex]): * unique: If all values in this column should be distinct. """ - name: str | int | None = attr.ib(default=None) - elements: st.SearchStrategy[Ex] | None = attr.ib(default=None) - dtype: Any = attr.ib(default=None, repr=get_pretty_function_description) - fill: st.SearchStrategy[Ex] | None = attr.ib(default=None) - unique: bool = attr.ib(default=False) + name: str | int | None = None + elements: st.SearchStrategy[Ex] | None = None + dtype: Any = None + fill: st.SearchStrategy[Ex] | None = None + unique: bool = False def columns( diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/cache.py b/contrib/python/hypothesis/py3/hypothesis/internal/cache.py index 73b9ed76d2c..899576f228d 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/cache.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/cache.py @@ -10,22 +10,21 @@ import threading from collections import OrderedDict +from dataclasses import dataclass from typing import Any, Generic, TypeVar -import attr - from hypothesis.errors import InvalidArgument K = TypeVar("K") V = TypeVar("V") [email protected](slots=True) +@dataclass(slots=True, frozen=False) class Entry(Generic[K, V]): - key: K = attr.ib() - value: V = attr.ib() - score: int = attr.ib() - pins: int = attr.ib(default=0) + key: K + value: V + score: int + pins: int = 0 @property def sort_key(self) -> tuple[int, ...]: diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/choice.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/choice.py index ffc08246fa6..b66f7e27537 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/choice.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/choice.py @@ -10,6 +10,7 @@ import math from collections.abc import Callable, Hashable, Iterable, Sequence +from dataclasses import dataclass from typing import ( Literal, TypeAlias, @@ -18,8 +19,6 @@ from typing import ( cast, ) -import attr - from hypothesis.errors import ChoiceTooLarge from hypothesis.internal.conjecture.floats import float_to_lex, lex_to_float from hypothesis.internal.conjecture.utils import identity @@ -72,23 +71,23 @@ ChoiceKeyT: TypeAlias = ( ) [email protected](slots=True) +@dataclass(slots=True, frozen=False) class ChoiceTemplate: - type: Literal["simplest"] = attr.ib() - count: int | None = attr.ib() + type: Literal["simplest"] + count: int | None - def __attrs_post_init__(self) -> None: + def __post_init__(self) -> None: if self.count is not None: assert self.count > 0 [email protected](slots=True, repr=False, eq=False) +@dataclass(slots=True, frozen=False) class ChoiceNode: - type: ChoiceTypeT = attr.ib() - value: ChoiceT = attr.ib() - constraints: ChoiceConstraintsT = attr.ib() - was_forced: bool = attr.ib() - index: int | None = attr.ib(default=None) + type: ChoiceTypeT + value: ChoiceT + constraints: ChoiceConstraintsT + was_forced: bool + index: int | None = None def copy( self, diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py index 6f9d07591bb..4ac53e9dd92 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/data.py @@ -12,6 +12,7 @@ import math import time from collections import defaultdict from collections.abc import Hashable, Iterable, Iterator, Sequence +from dataclasses import dataclass, field from enum import IntEnum from functools import cached_property from random import Random @@ -26,8 +27,6 @@ from typing import ( overload, ) -import attr - from hypothesis.errors import ( CannotProceedScopeT, ChoiceTooLarge, @@ -120,9 +119,9 @@ class Status(IntEnum): return f"Status.{self.name}" [email protected](slots=True, frozen=True) +@dataclass(slots=True, frozen=True) class StructuralCoverageTag: - label: int = attr.ib() + label: int STRUCTURAL_COVERAGE_CACHE: dict[int, StructuralCoverageTag] = {} @@ -568,27 +567,27 @@ class DataObserver: pass [email protected](slots=True) +@dataclass(slots=True, frozen=True) class ConjectureResult: """Result class storing the parts of ConjectureData that we will care about after the original ConjectureData has outlived its usefulness.""" - status: Status = attr.ib() - interesting_origin: InterestingOrigin | None = attr.ib() - nodes: tuple[ChoiceNode, ...] = attr.ib(eq=False, repr=False) - length: int = attr.ib() - output: str = attr.ib() - expected_exception: BaseException | None = attr.ib() - expected_traceback: str | None = attr.ib() - has_discards: bool = attr.ib() - target_observations: TargetObservations = attr.ib() - tags: frozenset[StructuralCoverageTag] = attr.ib() - spans: Spans = attr.ib(repr=False, eq=False) - arg_slices: set[tuple[int, int]] = attr.ib(repr=False) - slice_comments: dict[tuple[int, int], str] = attr.ib(repr=False) - misaligned_at: MisalignedAt | None = attr.ib(repr=False) - cannot_proceed_scope: CannotProceedScopeT | None = attr.ib(repr=False) + status: Status + interesting_origin: InterestingOrigin | None + nodes: tuple[ChoiceNode, ...] = field(repr=False, compare=False) + length: int + output: str + expected_exception: BaseException | None + expected_traceback: str | None + has_discards: bool + target_observations: TargetObservations + tags: frozenset[StructuralCoverageTag] + spans: Spans = field(repr=False, compare=False) + arg_slices: set[tuple[int, int]] = field(repr=False) + slice_comments: dict[tuple[int, int], str] = field(repr=False) + misaligned_at: MisalignedAt | None = field(repr=False) + cannot_proceed_scope: CannotProceedScopeT | None = field(repr=False) def as_result(self) -> "ConjectureResult": return self diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/datatree.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/datatree.py index 54e9b2664db..df02449a917 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/datatree.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/datatree.py @@ -10,11 +10,10 @@ import math from collections.abc import Generator, Set +from dataclasses import dataclass, field from random import Random from typing import TYPE_CHECKING, Final, TypeAlias, cast -import attr - from hypothesis.errors import ( FlakyReplay, FlakyStrategyDefinition, @@ -64,14 +63,14 @@ _FLAKY_STRAT_MSG = ( EMPTY: frozenset[int] = frozenset() [email protected](slots=True) +@dataclass(slots=True, frozen=True) class Killed: """Represents a transition to part of the tree which has been marked as "killed", meaning we want to treat it as not worth exploring, so it will be treated as if it were completely explored for the purposes of exhaustion.""" - next_node: "TreeNode" = attr.ib() + next_node: "TreeNode" def _repr_pretty_(self, p: "RepresentationPrinter", cycle: bool) -> None: assert cycle is False @@ -89,14 +88,14 @@ def _node_pretty( return f"{choice_type} {value!r}{forced_marker} {constraints}" [email protected](slots=True) +@dataclass(slots=True, frozen=False) class Branch: """Represents a transition where multiple choices can be made as to what to drawn.""" - constraints: ChoiceConstraintsT = attr.ib() - choice_type: ChoiceTypeT = attr.ib() - children: dict[ChoiceT, "TreeNode"] = attr.ib(repr=False) + constraints: ChoiceConstraintsT + choice_type: ChoiceTypeT + children: dict[ChoiceT, "TreeNode"] = field(repr=False) @property def max_children(self) -> int: @@ -117,12 +116,12 @@ class Branch: p.pretty(child) [email protected](slots=True, frozen=True) +@dataclass(slots=True, frozen=True) class Conclusion: """Represents a transition to a finished state.""" - status: Status = attr.ib() - interesting_origin: InterestingOrigin | None = attr.ib() + status: Status + interesting_origin: InterestingOrigin | None def _repr_pretty_(self, p: "RepresentationPrinter", cycle: bool) -> None: assert cycle is False @@ -334,7 +333,7 @@ def all_children( yield from _floats_between(min_point, max_value) [email protected](slots=True) +@dataclass(slots=True, frozen=False) class TreeNode: """ A node, or collection of directly descended nodes, in a DataTree. @@ -400,15 +399,15 @@ class TreeNode: # The constraints, value, and choice_types of the nodes stored here. These always # have the same length. The values at index i belong to node i. - constraints: list[ChoiceConstraintsT] = attr.ib(factory=list) - values: list[ChoiceT] = attr.ib(factory=list) - choice_types: list[ChoiceTypeT] = attr.ib(factory=list) + constraints: list[ChoiceConstraintsT] = field(default_factory=list) + values: list[ChoiceT] = field(default_factory=list) + choice_types: list[ChoiceTypeT] = field(default_factory=list) # The indices of nodes which had forced values. # # Stored as None if no indices have been forced, purely for space saving # reasons (we force quite rarely). - __forced: set[int] | None = attr.ib(default=None, init=False) + __forced: set[int] | None = field(default=None, init=False) # What happens next after drawing these nodes. (conceptually, "what is the # child/children of the last node stored here"). @@ -419,14 +418,14 @@ class TreeNode: # - Conclusion (ConjectureData.conclude_test was called here) # - Killed (this branch is valid and may even have children, but should not # be explored when generating novel prefixes) - transition: None | Branch | Conclusion | Killed = attr.ib(default=None) + transition: None | Branch | Conclusion | Killed = None # A tree node is exhausted if every possible sequence of draws below it has # been explored. We only update this when performing operations that could # change the answer. # # See also TreeNode.check_exhausted. - is_exhausted: bool = attr.ib(default=False, init=False) + is_exhausted: bool = field(default=False, init=False) @property def forced(self) -> Set[int]: diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/dfa/lstar.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/dfa/lstar.py index 061cb038253..25e638637b2 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/dfa/lstar.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/dfa/lstar.py @@ -10,8 +10,7 @@ from bisect import bisect_right, insort from collections import Counter - -import attr +from dataclasses import dataclass, field from hypothesis.errors import InvalidState from hypothesis.internal.conjecture.dfa import DFA, cached @@ -81,31 +80,31 @@ learning languages offline that we can record for later use. """ [email protected](slots=True) +@dataclass(slots=True, frozen=False) class DistinguishedState: """Relevant information for a state that we have witnessed as definitely distinct from ones we have previously seen so far.""" # Index of this state in the learner's list of states - index: int = attr.ib() + index: int # A string that witnesses this state (i.e. when starting from the origin # and following this string you will end up in this state). - label: str = attr.ib() + label: str # A boolean as to whether this is an accepting state. - accepting: bool = attr.ib() + accepting: bool # A list of experiments that it is necessary to run to determine whether # a string is in this state. This is stored as a dict mapping experiments # to their expected result. A string is only considered to lead to this # state if ``all(learner.member(s + experiment) == result for experiment, # result in self.experiments.items())``. - experiments: dict = attr.ib() + experiments: dict # A cache of transitions out of this state, mapping bytes to the states # that they lead to. - transitions: dict = attr.ib(factory=dict) + transitions: dict = field(default_factory=dict) class LStar: diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py index a363cdd047a..7af61ac6045 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/engine.py @@ -113,7 +113,7 @@ def shortlex(s): return (len(s), s) -@dataclass +@dataclass(slots=True, frozen=False) class HealthCheckState: valid_examples: int = field(default=0) invalid_examples: int = field(default=0) diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py index 9aad89c6e44..204b794345c 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/conjecture/shrinker.py @@ -89,7 +89,7 @@ def sort_key(nodes: Sequence[ChoiceNode]) -> tuple[int, tuple[int, ...]]: ) -@dataclass +@dataclass(slots=True, frozen=False) class ShrinkPass: function: Any name: str | None = None diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/escalation.py b/contrib/python/hypothesis/py3/hypothesis/internal/escalation.py index c29c846b770..031a99004c0 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/escalation.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/escalation.py @@ -16,7 +16,7 @@ import traceback from collections.abc import Callable from dataclasses import dataclass from functools import partial -from inspect import getframeinfo +from inspect import getfile, getsourcefile from pathlib import Path from types import ModuleType, TracebackType @@ -82,7 +82,7 @@ def get_trimmed_traceback( return tb while tb.tb_next is not None and ( # If the frame is from one of our files, it's been added by Hypothesis. - is_hypothesis_file(getframeinfo(tb.tb_frame).filename) + is_hypothesis_file(getsourcefile(tb.tb_frame) or getfile(tb.tb_frame)) # But our `@proxies` decorator overrides the source location, # so we check for an attribute it injects into the frame too. or tb.tb_frame.f_globals.get("__hypothesistracebackhide__") is True @@ -91,7 +91,7 @@ def get_trimmed_traceback( return tb -@dataclass(frozen=True) +@dataclass(slots=True, frozen=True) class InterestingOrigin: # The `interesting_origin` is how Hypothesis distinguishes between multiple # failures, for reporting and also to replay from the example database (even diff --git a/contrib/python/hypothesis/py3/hypothesis/internal/observability.py b/contrib/python/hypothesis/py3/hypothesis/internal/observability.py index 0310967132a..84d5b51bf49 100644 --- a/contrib/python/hypothesis/py3/hypothesis/internal/observability.py +++ b/contrib/python/hypothesis/py3/hypothesis/internal/observability.py @@ -68,7 +68,7 @@ _callbacks: dict[int | None, list[CallbackThreadT]] = {} _callbacks_all_threads: list[CallbackAllThreadsT] = [] -@dataclass +@dataclass(slots=True, frozen=False) class PredicateCounts: satisfied: int = 0 unsatisfied: int = 0 @@ -167,7 +167,7 @@ def nodes_to_json(nodes: tuple[ChoiceNode, ...]) -> list[dict[str, Any]]: ] -@dataclass +@dataclass(slots=True, frozen=True) class ObservationMetadata: traceback: str | None reproduction_decorator: str | None @@ -221,7 +221,7 @@ class ObservationMetadata: return data -@dataclass +@dataclass(slots=True, frozen=True) class BaseObservation: type: Literal["test_case", "info", "alert", "error"] property: str @@ -232,14 +232,14 @@ InfoObservationType = Literal["info", "alert", "error"] TestCaseStatus = Literal["gave_up", "passed", "failed"] -@dataclass +@dataclass(slots=True, frozen=True) class InfoObservation(BaseObservation): type: InfoObservationType title: str content: str | dict -@dataclass +@dataclass(slots=True, frozen=True) class TestCaseObservation(BaseObservation): __test__ = False # no! bad pytest! diff --git a/contrib/python/hypothesis/py3/hypothesis/stateful.py b/contrib/python/hypothesis/py3/hypothesis/stateful.py index 7c2ef1ccb40..22596158397 100644 --- a/contrib/python/hypothesis/py3/hypothesis/stateful.py +++ b/contrib/python/hypothesis/py3/hypothesis/stateful.py @@ -269,7 +269,7 @@ class StateMachineMeta(type): return super().__setattr__(name, value) -@dataclass +@dataclass(slots=True, frozen=True) class _SetupState: rules: list["Rule"] invariants: list["Invariant"] @@ -492,7 +492,7 @@ class RuleBasedStateMachine(metaclass=StateMachineMeta): return StateMachineTestCase -@dataclass +@dataclass(slots=True, frozen=False) class Rule: targets: Any function: Any @@ -501,9 +501,9 @@ class Rule: bundles: tuple["Bundle", ...] = field(init=False) _cached_hash: int | None = field(init=False, default=None) _cached_repr: str | None = field(init=False, default=None) + arguments_strategies: dict[Any, Any] = field(init=False, default_factory=dict) def __post_init__(self): - self.arguments_strategies = {} bundles = [] for k, v in sorted(self.arguments.items()): assert not isinstance(v, BundleReferenceStrategy) @@ -658,7 +658,7 @@ def consumes(bundle: Bundle[Ex]) -> SearchStrategy[Ex]: return BundleConsumer(bundle) -@dataclass +@dataclass(slots=True, frozen=True) class MultipleResults(Iterable[Ex]): values: tuple[Ex, ...] @@ -941,7 +941,7 @@ def initialize( return accept -@dataclass +@dataclass(slots=True, frozen=True) class VarReference: name: str @@ -1010,7 +1010,7 @@ def precondition(precond: Callable[[Any], bool]) -> Callable[[TestFunc], TestFun return decorator -@dataclass +@dataclass(slots=True, frozen=True) class Invariant: function: Any preconditions: Any diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/attrs.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/attrs.py index 555b7ca09b6..4e057df545c 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/attrs.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/attrs.py @@ -8,6 +8,9 @@ # 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/. +# Since Hypothesis doesn't have a hard dependency on attrs, be careful to only import +# this file when attrs is in sys.modules. + from collections.abc import Collection, Generator, Iterable, Sequence from functools import reduce from itertools import chain diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py index 187be5c78f1..bd3be431a29 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py @@ -45,8 +45,6 @@ from typing import ( ) from uuid import UUID -import attr - from hypothesis._settings import note_deprecation from hypothesis.control import ( cleanup, @@ -172,7 +170,7 @@ def sampled_from( ... -@defines_strategy(try_non_lazy=True) +@defines_strategy(eager="try") def sampled_from( elements: type[enum.Enum] | Sequence[Any], ) -> SearchStrategy[Any]: @@ -1154,7 +1152,11 @@ def builds( required = required_args(target, args, kwargs) to_infer = {k for k, v in kwargs.items() if v is ...} if required or to_infer: - if isinstance(target, type) and attr.has(target): + if ( + isinstance(target, type) + and (attr := sys.modules.get("attr")) is not None + and attr.has(target) + ): # pragma: no cover # covered by our attrs tests in check-niche # Use our custom introspection for attrs classes from hypothesis.strategies._internal.attrs import from_attrs @@ -1188,7 +1190,7 @@ def builds( @cacheable -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def from_type(thing: type[T]) -> SearchStrategy[T]: """Looks up the appropriate search strategy for the given type. @@ -1536,7 +1538,7 @@ def _from_type(thing: type[Ex]) -> SearchStrategy[Ex]: required = required_args(thing) if required and not ( required.issubset(get_type_hints(thing)) - or attr.has(thing) + or ((attr := sys.modules.get("attr")) is not None and attr.has(thing)) or is_typed_named_tuple(thing) # weird enough that we have a specific check ): raise ResolutionFailed( @@ -1826,7 +1828,7 @@ def decimals( return strat | (sampled_from(special) if special else nothing()) -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def recursive( base: SearchStrategy[Ex], extend: Callable[[SearchStrategy[Any]], SearchStrategy[T]], @@ -2171,7 +2173,7 @@ def complex_numbers( return constrained_complex() -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def shared( base: SearchStrategy[Ex], *, @@ -2338,7 +2340,7 @@ class DataStrategy(SearchStrategy): @cacheable -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def data() -> SearchStrategy[DataObject]: """ Provides an object ``data`` with a ``data.draw`` function which acts like @@ -2486,7 +2488,7 @@ def register_type_strategy( @cacheable -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def deferred(definition: Callable[[], SearchStrategy[Ex]]) -> SearchStrategy[Ex]: """A deferred strategy allows you to write a strategy that references other strategies that have not yet been defined. This allows for the easy diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/misc.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/misc.py index 6e453040e42..cbcfa324455 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/misc.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/misc.py @@ -64,7 +64,7 @@ class JustStrategy(SampledFromStrategy[Ex]): return self._transform(self.value) -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def just(value: T) -> SearchStrategy[T]: """Return a strategy which only generates ``value``. @@ -120,7 +120,7 @@ NOTHING = Nothing() @cacheable -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def nothing() -> SearchStrategy["Never"]: """This strategy never successfully draws a value and will always reject on an attempt to draw. diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py index 8ff1d077877..523991c6e72 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/random.py @@ -11,11 +11,10 @@ import abc import inspect import math +from dataclasses import dataclass, field from random import Random from typing import Any -import attr - from hypothesis.control import should_note from hypothesis.internal.conjecture.data import ConjectureData from hypothesis.internal.reflection import define_function_signature @@ -147,10 +146,10 @@ for r in RANDOM_METHODS: define_copy_method(r) [email protected](slots=True) +@dataclass(slots=True, frozen=False) class RandomState: - next_states: dict = attr.ib(factory=dict) - state_id: Any = attr.ib(default=None) + next_states: dict = field(default_factory=dict) + state_id: Any = None def state_for_seed(data, seed): diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py index e5e03145d61..0fd21ea108a 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/strategies.py @@ -271,9 +271,12 @@ class SearchStrategy(Generic[Ex]): def has_reusable_values(self) -> Any: return recursive_property(self, "has_reusable_values", True) - # Whether this strategy is suitable for holding onto in a cache. @property def is_cacheable(self) -> Any: + """ + Whether it is safe to hold on to instances of this strategy in a cache. + See _STRATEGY_CACHE. + """ return recursive_property(self, "is_cacheable", True) def calc_is_cacheable(self, recur: RecurT) -> bool: @@ -918,7 +921,7 @@ def one_of(*args: SearchStrategy[Any]) -> SearchStrategy[Any]: # pragma: no cov ... -@defines_strategy(never_lazy=True) +@defines_strategy(eager=True) def one_of( *args: Sequence[SearchStrategy[Any]] | SearchStrategy[Any], ) -> SearchStrategy[Any]: diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/utils.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/utils.py index 6c5ec635c6a..c9656436c58 100644 --- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/utils.py +++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/utils.py @@ -12,11 +12,10 @@ import dataclasses import sys from collections.abc import Callable from functools import partial -from typing import TypeAlias, TypeVar +from typing import Literal, TypeAlias, TypeVar from weakref import WeakValueDictionary -import attr - +from hypothesis.errors import InvalidArgument from hypothesis.internal.cache import LRUReusedCache from hypothesis.internal.floats import clamp, float_to_int from hypothesis.internal.reflection import proxies @@ -34,13 +33,13 @@ _all_strategies: WeakValueDictionary[str, Callable] = WeakValueDictionary() _STRATEGY_CACHE = LRUReusedCache[StrategyCacheKey, object](1024) -def convert_value(v: object) -> ValueKey: - if isinstance(v, float): - return (float, float_to_int(v)) - return (type(v), v) +def _value_key(value: object) -> ValueKey: + if isinstance(value, float): + return (float, float_to_int(value)) + return (type(value), value) -def clear_cache() -> None: +def clear_strategy_cache() -> None: _STRATEGY_CACHE.clear() @@ -55,64 +54,85 @@ def cacheable(fn: T) -> T: return fn(*args, **kwargs) try: - kwargs_cache_key = {(k, convert_value(v)) for k, v in kwargs.items()} + kwargs_cache_key = {(k, _value_key(v)) for k, v in kwargs.items()} except TypeError: return fn(*args, **kwargs) - cache_key = (fn, tuple(map(convert_value, args)), frozenset(kwargs_cache_key)) + + cache_key = ( + fn, + tuple(_value_key(v) for v in args), + frozenset(kwargs_cache_key), + ) try: - if cache_key in _STRATEGY_CACHE: - return _STRATEGY_CACHE[cache_key] + return _STRATEGY_CACHE[cache_key] + except KeyError: + pass except TypeError: return fn(*args, **kwargs) - else: - result = fn(*args, **kwargs) - if not isinstance(result, SearchStrategy) or result.is_cacheable: - _STRATEGY_CACHE[cache_key] = result - return result - cached_strategy.__clear_cache = clear_cache # type: ignore + result = fn(*args, **kwargs) + if not isinstance(result, SearchStrategy) or result.is_cacheable: + _STRATEGY_CACHE[cache_key] = result + return result + + # note that calling this clears the full _STRATEGY_CACHE for all strategies, + # not just the cache for this strategy. + cached_strategy.__clear_cache = clear_strategy_cache # type: ignore return cached_strategy def defines_strategy( *, force_reusable_values: bool = False, - try_non_lazy: bool = False, - never_lazy: bool = False, + eager: bool | Literal["try"] = False, ) -> Callable[[T], T]: - """Returns a decorator for strategy functions. + """ + Each standard strategy function provided to users by Hypothesis should be + decorated with @defines_strategy. This registers the strategy with _all_strategies, + which is used in our own test suite to check that e.g. we document all strategies + in sphinx. - If ``force_reusable_values`` is True, the returned strategy will be marked - with ``.has_reusable_values == True`` even if it uses maps/filters or - non-reusable strategies internally. This tells our numpy/pandas strategies - that they can implicitly use such strategies as background values. + If you're reading this and are the author of a third-party strategy library: + don't worry, third-party strategies don't need to be decorated with + @defines_strategy. This function is internal to Hypothesis and not intended + for outside use. - If ``try_non_lazy`` is True, attempt to execute the strategy definition - function immediately, so that a LazyStrategy is only returned if this - raises an exception. + Parameters + ---------- + force_reusable_values : bool + If ``True``, strategies returned from the strategy function will have + ``.has_reusable_values == True`` set, even if it uses maps/filters or + non-reusable strategies internally. This tells our numpy/pandas strategies + that they can implicitly use such strategies as background values. + eager : bool | "try" + If ``True``, strategies returned by the strategy function are returned + as-is, and not wrapped in LazyStrategy. - If ``never_lazy`` is True, the decorator performs no lazy-wrapping at all, - and instead returns the original function. + If "try", we first attempt to call the strategy function and return the + resulting strategy. If this throws an exception, we treat it the same as + ``eager = False``, by returning the strategy function wrapped in a + LazyStrategy. """ + if eager is not False and force_reusable_values: # pragma: no cover + # We could support eager + force_reusable_values with a suitable wrapper, + # but there are currently no callers that request this combination. + raise InvalidArgument( + f"Passing both eager={eager} and force_reusable_values=True is " + "currently not supported" + ) + def decorator(strategy_definition): - """A decorator that registers the function as a strategy and makes it - lazily evaluated.""" _all_strategies[strategy_definition.__name__] = strategy_definition - if never_lazy: - assert not try_non_lazy - # We could potentially support never_lazy + force_reusable_values - # with a suitable wrapper, but currently there are no callers that - # request this combination. - assert not force_reusable_values + if eager is True: return strategy_definition - from hypothesis.strategies._internal.lazy import LazyStrategy - @proxies(strategy_definition) def accept(*args, **kwargs): - if try_non_lazy: + from hypothesis.strategies._internal.lazy import LazyStrategy + + if eager == "try": # Why not try this unconditionally? Because we'd end up with very # deep nesting of recursive strategies - better to be lazy unless we # *know* that eager evaluation is the right choice. @@ -178,19 +198,15 @@ def _to_jsonable(obj: object, *, avoid_realization: bool, seen: set[int]) -> obj pass # Special handling for dataclasses, attrs, and pydantic classes - if ( - (dcs := sys.modules.get("dataclasses")) - and dcs.is_dataclass(obj) - and not isinstance(obj, type) - ): + if dataclasses.is_dataclass(obj) and not isinstance(obj, type): # Avoid dataclasses.asdict here to ensure that inner to_json overrides # can get called as well return { field.name: recur(getattr(obj, field.name)) - for field in dataclasses.fields(obj) # type: ignore + for field in dataclasses.fields(obj) } - if attr.has(type(obj)): - return recur(attr.asdict(obj, recurse=False)) # type: ignore + if (attr := sys.modules.get("attr")) is not None and attr.has(type(obj)): + return recur(attr.asdict(obj, recurse=False)) if (pyd := sys.modules.get("pydantic")) and isinstance(obj, pyd.BaseModel): return recur(obj.model_dump()) diff --git a/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py b/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py index 83fab2406d7..af790bbab2c 100644 --- a/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py +++ b/contrib/python/hypothesis/py3/hypothesis/vendor/pretty.py @@ -232,7 +232,7 @@ class RepresentationPrinter: self.type_pprinters[cls] = printer return printer(obj, self, cycle) else: - if hasattr(cls, "__attrs_attrs__"): + if hasattr(cls, "__attrs_attrs__"): # pragma: no cover return pprint_fields( obj, self, diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py index f9daf2ead6b..cee78be632c 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, 144, 0) +__version_info__ = (6, 145, 1) __version__ = ".".join(map(str, __version_info__)) diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make index c392b732384..e0998729d12 100644 --- a/contrib/python/hypothesis/py3/ya.make +++ b/contrib/python/hypothesis/py3/ya.make @@ -2,12 +2,11 @@ PY3_LIBRARY() -VERSION(6.144.0) +VERSION(6.145.1) LICENSE(MPL-2.0) PEERDIR( - contrib/python/attrs contrib/python/sortedcontainers ) diff --git a/contrib/python/lz4/py3/.dist-info/METADATA b/contrib/python/lz4/py3/.dist-info/METADATA index a57e6022a3f..ffde6ce8e50 100644 --- a/contrib/python/lz4/py3/.dist-info/METADATA +++ b/contrib/python/lz4/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: lz4 -Version: 4.4.4 +Version: 4.4.5 Summary: LZ4 Bindings for Python Home-page: https://github.com/python-lz4/python-lz4 Author: Jonathan Underwood diff --git a/contrib/python/lz4/py3/lz4/_version.c b/contrib/python/lz4/py3/lz4/_version.c index c611f0b361d..af606abee19 100644 --- a/contrib/python/lz4/py3/lz4/_version.c +++ b/contrib/python/lz4/py3/lz4/_version.c @@ -113,5 +113,9 @@ PyInit__version(void) if (module == NULL) return NULL; + #ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); + #endif + return module; } diff --git a/contrib/python/lz4/py3/lz4/block/_block.c b/contrib/python/lz4/py3/lz4/block/_block.c index 3e904a03441..993cc44c010 100644 --- a/contrib/python/lz4/py3/lz4/block/_block.c +++ b/contrib/python/lz4/py3/lz4/block/_block.c @@ -518,5 +518,9 @@ PyInit__block(void) Py_INCREF(LZ4BlockError); PyModule_AddObject(module, "LZ4BlockError", LZ4BlockError); + #ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); + #endif + return module; } diff --git a/contrib/python/lz4/py3/lz4/frame/__init__.py b/contrib/python/lz4/py3/lz4/frame/__init__.py index 00f3e64adf3..2a82cd08226 100644 --- a/contrib/python/lz4/py3/lz4/frame/__init__.py +++ b/contrib/python/lz4/py3/lz4/frame/__init__.py @@ -25,9 +25,9 @@ from ._frame import ( # noqa: F401 __doc__ = _doc try: - import _compression # Python 3.6 and later + import compression._common._streams as _compression # Python 3.14 except ImportError: - from . import _compression + import _compression # Python 3.9 - 3.13 BLOCKSIZE_DEFAULT = _BLOCKSIZE_DEFAULT @@ -268,7 +268,7 @@ class LZ4FrameCompressor(object): This returns a ``bytes`` or ``bytearray`` object containing any data stored in the compressor's internal buffers and a frame footer. - The LZ4FrameCompressor instance may be re-used after this method has + The LZ4FrameCompressor instance may be reused after this method has been called to create a new frame of compressed data. Returns: @@ -287,7 +287,7 @@ class LZ4FrameCompressor(object): def reset(self): """Reset the `LZ4FrameCompressor` instance. - This allows the `LZ4FrameCompression` instance to be re-used after an + This allows the `LZ4FrameCompression` instance to be reused after an error. """ @@ -360,7 +360,7 @@ class LZ4FrameDecompressor(object): def reset(self): """Reset the decompressor state. - This is useful after an error occurs, allowing re-use of the instance. + This is useful after an error occurs, allowing reuse of the instance. """ reset_decompression_context(self._context) diff --git a/contrib/python/lz4/py3/lz4/frame/_frame.c b/contrib/python/lz4/py3/lz4/frame/_frame.c index 34606653b0e..440b0b50593 100644 --- a/contrib/python/lz4/py3/lz4/frame/_frame.c +++ b/contrib/python/lz4/py3/lz4/frame/_frame.c @@ -1330,7 +1330,7 @@ PyDoc_STRVAR( ); #define COMPRESS_KWARGS_DOCSTRING \ - " block_size (int): Sepcifies the maximum blocksize to use.\n" \ + " block_size (int): Specifies the maximum blocksize to use.\n" \ " Options:\n\n" \ " - `lz4.frame.BLOCKSIZE_DEFAULT`: the lz4 library default\n" \ " - `lz4.frame.BLOCKSIZE_MAX64KB`: 64 kB\n" \ @@ -1466,7 +1466,7 @@ PyDoc_STRVAR "data will also be included in the returned data.\n" \ "\n" \ "If the ``end_frame`` argument is ``True``, the compression context will be\n" \ - "reset and can be re-used.\n" \ + "reset and can be reused.\n" \ "\n" \ "Args:\n" \ " context (cCtx): Compression context\n" \ @@ -1677,5 +1677,9 @@ PyInit__frame(void) PyModule_AddIntConstant (module, "BLOCKSIZE_MAX1MB", LZ4F_max1MB); PyModule_AddIntConstant (module, "BLOCKSIZE_MAX4MB", LZ4F_max4MB); + #ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); + #endif + return module; } diff --git a/contrib/python/lz4/py3/lz4/stream/__init__.py b/contrib/python/lz4/py3/lz4/stream/__init__.py index 4b0074648dc..58ce298ade5 100644 --- a/contrib/python/lz4/py3/lz4/stream/__init__.py +++ b/contrib/python/lz4/py3/lz4/stream/__init__.py @@ -32,7 +32,7 @@ class LZ4StreamDecompressor: perform decompression using this initial dictionary. Raises: - Exceptions occuring during the context initialization. + Exceptions occurring during the context initialization. OverflowError: raised if the ``dictionary`` parameter is too large for the LZ4 context. @@ -73,7 +73,7 @@ class LZ4StreamDecompressor: bytes or bytearray: Decompressed data. Raises: - Exceptions occuring during decompression. + Exceptions occurring during decompression. ValueError: raised if the source is inconsistent with a finite LZ4 stream block chain. @@ -96,7 +96,7 @@ class LZ4StreamDecompressor: bytes or bytearray: LZ4 compressed data block. Raises: - Exceptions occuring while getting the first block from ``stream``. + Exceptions occurring while getting the first block from ``stream``. BufferError: raised if the function cannot return a complete LZ4 compressed block from the stream (i.e. the stream does not hold @@ -150,7 +150,7 @@ class LZ4StreamCompressor: perform compression using this initial dictionary. Raises: - Exceptions occuring during the context initialization. + Exceptions occurring during the context initialization. OverflowError: raised if the ``dictionary`` parameter is too large for the LZ4 context. @@ -194,7 +194,7 @@ class LZ4StreamCompressor: bytes or bytearray: Compressed data. Raises: - Exceptions occuring during compression. + Exceptions occurring during compression. OverflowError: raised if the source is too large for being compressed in the given context. diff --git a/contrib/python/lz4/py3/lz4/stream/_stream.c b/contrib/python/lz4/py3/lz4/stream/_stream.c index 522fdedacde..4c51d89dae5 100644 --- a/contrib/python/lz4/py3/lz4/stream/_stream.c +++ b/contrib/python/lz4/py3/lz4/stream/_stream.c @@ -931,7 +931,7 @@ _create_context (PyObject * Py_UNUSED (self), PyObject * args, PyObject * kwds) context->output.len = buffer_size; total_size = context->output.len; - /* Here we cannot assert the maximal theorical decompressed chunk length + /* Here we cannot assert the maximal theoretical decompressed chunk length * will fit in one page of the double_buffer, i.e.: * assert( !(double_buffer.page_size < _LZ4_inputBound(store_max_size)) ) * @@ -1649,5 +1649,9 @@ PyInit__stream(void) Py_INCREF (LZ4StreamError); PyModule_AddObject (module, "LZ4StreamError", LZ4StreamError); + #ifdef Py_GIL_DISABLED + PyUnstable_Module_SetGIL(module, Py_MOD_GIL_NOT_USED); + #endif + return module; } diff --git a/contrib/python/lz4/py3/lz4/version.py b/contrib/python/lz4/py3/lz4/version.py index 2808f61053d..ee639d55b29 100644 --- a/contrib/python/lz4/py3/lz4/version.py +++ b/contrib/python/lz4/py3/lz4/version.py @@ -1,7 +1,14 @@ # file generated by setuptools-scm # don't change, don't track in version control -__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"] +__all__ = [ + "__version__", + "__version_tuple__", + "version", + "version_tuple", + "__commit_id__", + "commit_id", +] TYPE_CHECKING = False if TYPE_CHECKING: @@ -9,13 +16,19 @@ if TYPE_CHECKING: from typing import Union VERSION_TUPLE = Tuple[Union[int, str], ...] + COMMIT_ID = Union[str, None] else: VERSION_TUPLE = object + COMMIT_ID = object version: str __version__: str __version_tuple__: VERSION_TUPLE version_tuple: VERSION_TUPLE +commit_id: COMMIT_ID +__commit_id__: COMMIT_ID -__version__ = version = '4.4.4' -__version_tuple__ = version_tuple = (4, 4, 4) +__version__ = version = '4.4.5' +__version_tuple__ = version_tuple = (4, 4, 5) + +__commit_id__ = commit_id = 'g59b2d8176' diff --git a/contrib/python/lz4/py3/tests/block/test_block_0.py b/contrib/python/lz4/py3/tests/block/test_block_0.py index 8fc0f488877..a7731c3a0bc 100644 --- a/contrib/python/lz4/py3/tests/block/test_block_0.py +++ b/contrib/python/lz4/py3/tests/block/test_block_0.py @@ -1,6 +1,8 @@ import lz4.block from multiprocessing.pool import ThreadPool import sys +import copy +import pytest from functools import partial if sys.version_info <= (3, 2): import struct @@ -68,6 +70,13 @@ def setup_kwargs(mode, store_size, c_return_bytearray=None, d_return_bytearray=N # Test single threaded usage with all valid variations of input def test_1(data, mode, store_size, c_return_bytearray, d_return_bytearray, dictionary): + if isinstance(data, memoryview): + data = memoryview(copy.deepcopy(data.obj)) + elif isinstance(data, bytearray): + data_x = bytearray() + data_x[:] = data + data = data_x + (c_kwargs, d_kwargs) = setup_kwargs( mode, store_size, c_return_bytearray, d_return_bytearray) @@ -79,10 +88,21 @@ def test_1(data, mode, store_size, c_return_bytearray, d_return_bytearray, dicti # Test multi threaded usage with all valid variations of input [email protected]_unsafe def test_2(data, mode, store_size, dictionary): (c_kwargs, d_kwargs) = setup_kwargs(mode, store_size) - data_in = [data for i in range(32)] + def copy_buf(data): + if isinstance(data, memoryview): + data_x = memoryview(copy.deepcopy(data.obj)) + elif isinstance(data, bytearray): + data_x = bytearray() + data_x[:] = data + else: + data_x = data + return data_x + + data_in = [copy_buf(data) for i in range(32)] pool = ThreadPool(2) rt = partial(roundtrip, c_kwargs=c_kwargs, diff --git a/contrib/python/lz4/py3/tests/block/test_block_3.py b/contrib/python/lz4/py3/tests/block/test_block_3.py index 3fcb175b3b5..88461b7a231 100644 --- a/contrib/python/lz4/py3/tests/block/test_block_3.py +++ b/contrib/python/lz4/py3/tests/block/test_block_3.py @@ -18,6 +18,7 @@ def data(request): return request.param [email protected]_unsafe def test_block_decompress_mem_usage(data): tracemalloc = pytest.importorskip('tracemalloc') diff --git a/contrib/python/lz4/py3/tests/frame/test_frame_2.py b/contrib/python/lz4/py3/tests/frame/test_frame_2.py index 80b44b87ff5..230867e6545 100644 --- a/contrib/python/lz4/py3/tests/frame/test_frame_2.py +++ b/contrib/python/lz4/py3/tests/frame/test_frame_2.py @@ -1,6 +1,7 @@ import lz4.frame as lz4frame import pytest import os +import copy import sys from . helpers import ( get_chunked, @@ -41,6 +42,13 @@ def test_roundtrip_chunked(data, block_size, block_linked, data, c_chunks, d_chunks = data + if isinstance(data, memoryview): + data = memoryview(copy.deepcopy(data.obj)) + elif isinstance(data, bytearray): + data_2 = bytearray() + data_2[:] = data + data = data_2 + c_context = lz4frame.create_compression_context() kwargs = {} diff --git a/contrib/python/lz4/py3/tests/frame/test_frame_5.py b/contrib/python/lz4/py3/tests/frame/test_frame_5.py index 05daf283f93..dcbe4aead10 100644 --- a/contrib/python/lz4/py3/tests/frame/test_frame_5.py +++ b/contrib/python/lz4/py3/tests/frame/test_frame_5.py @@ -8,6 +8,8 @@ test_data = [ (b'a' * 1024 * 1024), ] +pytestmark = pytest.mark.thread_unsafe + @pytest.fixture( params=test_data, diff --git a/contrib/python/lz4/py3/tests/frame/test_frame_6.py b/contrib/python/lz4/py3/tests/frame/test_frame_6.py index c20a4f31316..4f4185ee082 100644 --- a/contrib/python/lz4/py3/tests/frame/test_frame_6.py +++ b/contrib/python/lz4/py3/tests/frame/test_frame_6.py @@ -1,5 +1,6 @@ import os import pytest +import threading import lz4.frame as lz4frame test_data = [ @@ -33,40 +34,45 @@ def compression_level(request): return request.param -def test_lz4frame_open_write(data): - with lz4frame.open('testfile', mode='wb') as fp: +def test_lz4frame_open_write(tmp_path, data): + thread_id = threading.get_native_id() + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='wb') as fp: fp.write(data) -def test_lz4frame_open_write_read_defaults(data): - with lz4frame.open('testfile', mode='wb') as fp: +def test_lz4frame_open_write_read_defaults(tmp_path, data): + thread_id = threading.get_native_id() + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='wb') as fp: fp.write(data) - with lz4frame.open('testfile', mode='r') as fp: + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='r') as fp: data_out = fp.read() assert data_out == data -def test_lz4frame_open_write_read_text(): +def test_lz4frame_open_write_read_text(tmp_path): data = u'This is a test string' - with lz4frame.open('testfile', mode='wt') as fp: + thread_id = threading.get_native_id() + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='wt') as fp: fp.write(data) - with lz4frame.open('testfile', mode='rt') as fp: + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='rt') as fp: data_out = fp.read() assert data_out == data -def test_lz4frame_open_write_read_text_iter(): +def test_lz4frame_open_write_read_text_iter(tmp_path): data = u'This is a test string' - with lz4frame.open('testfile', mode='wt') as fp: + thread_id = threading.get_native_id() + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='wt') as fp: fp.write(data) data_out = '' - with lz4frame.open('testfile', mode='rt') as fp: + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='rt') as fp: for line in fp: data_out += line assert data_out == data def test_lz4frame_open_write_read( + tmp_path, data, compression_level, block_linked, @@ -91,29 +97,31 @@ def test_lz4frame_open_write_read( kwargs['return_bytearray'] = return_bytearray kwargs['mode'] = 'wb' - with lz4frame.open('testfile', **kwargs) as fp: + thread_id = threading.get_native_id() + with lz4frame.open(tmp_path / f'testfile_{thread_id}', **kwargs) as fp: fp.write(data) - with lz4frame.open('testfile', mode='r') as fp: + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='r') as fp: data_out = fp.read() assert data_out == data -def test_lz4frame_flush(): +def test_lz4frame_flush(tmp_path): data_1 = b"This is a..." data_2 = b" test string!" + thread_id = threading.get_native_id() - with lz4frame.open("testfile", mode="w") as fp_write: + with lz4frame.open(tmp_path / f"testfile_{thread_id}", mode="w") as fp_write: fp_write.write(data_1) fp_write.flush() fp_write.write(data_2) - with lz4frame.open("testfile", mode="r") as fp_read: + with lz4frame.open(tmp_path / f"testfile_{thread_id}", mode="r") as fp_read: assert fp_read.read() == data_1 fp_write.flush() - with lz4frame.open("testfile", mode="r") as fp_read: + with lz4frame.open(tmp_path / f"testfile_{thread_id}", mode="r") as fp_read: assert fp_read.read() == data_1 + data_2 diff --git a/contrib/python/lz4/py3/tests/frame/test_frame_8.py b/contrib/python/lz4/py3/tests/frame/test_frame_8.py index 159534aefec..cfaeaace600 100644 --- a/contrib/python/lz4/py3/tests/frame/test_frame_8.py +++ b/contrib/python/lz4/py3/tests/frame/test_frame_8.py @@ -1,12 +1,14 @@ +import threading import lz4.frame as lz4frame -def test_lz4frame_open_write_read_text_iter(): +def test_lz4frame_open_write_read_text_iter(tmp_path): data = u'This is a test string' - with lz4frame.open('testfile', mode='wt') as fp: + thread_id = threading.get_native_id() + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='wt') as fp: fp.write(data) data_out = '' - with lz4frame.open('testfile', mode='rt') as fp: + with lz4frame.open(tmp_path / f'testfile_{thread_id}', mode='rt') as fp: for line in fp: data_out += line assert data_out == data diff --git a/contrib/python/lz4/py3/tests/frame/test_frame_9.py b/contrib/python/lz4/py3/tests/frame/test_frame_9.py index 51433934176..6f7fc0dba85 100644 --- a/contrib/python/lz4/py3/tests/frame/test_frame_9.py +++ b/contrib/python/lz4/py3/tests/frame/test_frame_9.py @@ -3,11 +3,12 @@ import os import io import pickle import sys +import threading import lz4.frame import pytest -def test_issue_172_1(): +def test_issue_172_1(tmp_path): """Test reproducer for issue 172 Issue 172 is a reported failure occurring on Windows 10 only. This bug was @@ -16,34 +17,38 @@ def test_issue_172_1(): """ input_data = 8 * os.urandom(1024) - with lz4.frame.open('testfile_small', 'wb') as fp: + thread_id = threading.get_native_id() + + with lz4.frame.open(tmp_path / f'testfile_small_{thread_id}', 'wb') as fp: bytes_written = fp.write(input_data) # noqa: F841 - with lz4.frame.open('testfile_small', 'rb') as fp: + with lz4.frame.open(tmp_path / f'testfile_small_{thread_id}', 'rb') as fp: data = fp.read(10) assert len(data) == 10 -def test_issue_172_2(): +def test_issue_172_2(tmp_path): input_data = 9 * os.urandom(1024) - with lz4.frame.open('testfile_small', 'w') as fp: + thread_id = threading.get_native_id() + with lz4.frame.open(tmp_path / f'testfile_small_{thread_id}', 'w') as fp: bytes_written = fp.write(input_data) # noqa: F841 - with lz4.frame.open('testfile_small', 'r') as fp: + with lz4.frame.open(tmp_path / f'testfile_small_{thread_id}', 'r') as fp: data = fp.read(10) assert len(data) == 10 -def test_issue_172_3(): +def test_issue_172_3(tmp_path): input_data = 9 * os.urandom(1024) - with lz4.frame.open('testfile_small', 'wb') as fp: + thread_id = threading.get_native_id() + with lz4.frame.open(tmp_path / f'testfile_small_{thread_id}', 'wb') as fp: bytes_written = fp.write(input_data) # noqa: F841 - with lz4.frame.open('testfile_small', 'rb') as fp: + with lz4.frame.open(tmp_path / f'testfile_small_{thread_id}', 'rb') as fp: data = fp.read(10) assert len(data) == 10 - with lz4.frame.open('testfile_small', 'rb') as fp: + with lz4.frame.open(tmp_path / f'testfile_small_{thread_id}', 'rb') as fp: data = fp.read(16 * 1024 - 1) assert len(data) == 9 * 1024 assert data == input_data @@ -60,7 +65,7 @@ def test_issue_227_1(): @pytest.mark.skipif( sys.version_info < (3, 8), - reason="PickleBuffer only availiable in Python 3.8 or greater" + reason="PickleBuffer only available in Python 3.8 or greater" ) def test_issue_227_2(): q = array.array('Q', [1, 2, 3, 4, 5]) diff --git a/contrib/python/lz4/py3/tests/stream/test_stream_0.py b/contrib/python/lz4/py3/tests/stream/test_stream_0.py index 03b19f3f424..3cd05d6f511 100644 --- a/contrib/python/lz4/py3/tests/stream/test_stream_0.py +++ b/contrib/python/lz4/py3/tests/stream/test_stream_0.py @@ -96,6 +96,7 @@ def setup_kwargs(strategy, mode, buffer_size, store_comp_size, # Test single threaded usage with all valid variations of input [email protected]_unsafe def test_1(data, strategy, mode, buffer_size, store_comp_size, c_return_bytearray, d_return_bytearray, dictionary): if buffer_size >= (1 << (8 * store_comp_size['store_comp_size'])): @@ -111,6 +112,6 @@ def test_1(data, strategy, mode, buffer_size, store_comp_size, # Test multi threaded: # Not relevant in the lz4.stream case (the process is highly sequential, -# and re-use/share the same context from one input chunk to the next one). +# and reuse/share the same context from one input chunk to the next one). def test_2(data, strategy, mode, buffer_size, store_comp_size, dictionary): # noqa pass diff --git a/contrib/python/lz4/py3/tests/stream/test_stream_1.py b/contrib/python/lz4/py3/tests/stream/test_stream_1.py index 6b49267e262..481de8aa5b5 100644 --- a/contrib/python/lz4/py3/tests/stream/test_stream_1.py +++ b/contrib/python/lz4/py3/tests/stream/test_stream_1.py @@ -136,7 +136,7 @@ def test_invalid_config_c_4(store_comp_size): c_kwargs.update(store_comp_size) if store_comp_size['store_comp_size'] >= 4: - # No need for skiping this test case, since arguments check is + # No need for skipping this test case, since arguments check is # expecting to raise an error. # Make sure the page size is larger than what the input bound will be, @@ -169,7 +169,7 @@ def test_invalid_config_d_4(store_comp_size): # but still fit in 4 bytes d_kwargs['buffer_size'] -= 1 - # No failure expected during instanciation/initialization + # No failure expected during instantiation/initialization lz4.stream.LZ4StreamDecompressor(**d_kwargs) @@ -199,7 +199,7 @@ def test_invalid_config_d_5(): d_kwargs = {} d_kwargs['strategy'] = "double_buffer" - # No failure expected during instanciation/initialization + # No failure expected during instantiation/initialization d_kwargs['buffer_size'] = lz4.stream.LZ4_MAX_INPUT_SIZE if sys.maxsize < 0xffffffff: @@ -207,7 +207,7 @@ def test_invalid_config_d_5(): lz4.stream.LZ4StreamDecompressor(**d_kwargs) - # No failure expected during instanciation/initialization + # No failure expected during instantiation/initialization d_kwargs['buffer_size'] = lz4.stream.LZ4_MAX_INPUT_SIZE + 1 if sys.maxsize < 0xffffffff: @@ -215,7 +215,7 @@ def test_invalid_config_d_5(): lz4.stream.LZ4StreamDecompressor(**d_kwargs) - # No failure expected during instanciation/initialization + # No failure expected during instantiation/initialization d_kwargs['buffer_size'] = _4GB - 1 # 4GB - 1 (to fit in 4 bytes) if sys.maxsize < 0xffffffff: diff --git a/contrib/python/lz4/py3/tests/stream/test_stream_3.py b/contrib/python/lz4/py3/tests/stream/test_stream_3.py index 2b52d6b5494..fed93d2c4a7 100644 --- a/contrib/python/lz4/py3/tests/stream/test_stream_3.py +++ b/contrib/python/lz4/py3/tests/stream/test_stream_3.py @@ -71,6 +71,7 @@ def data(request): return request.param [email protected]_unsafe def test_block_decompress_mem_usage(data, buffer_size): kwargs = { 'strategy': "double_buffer", diff --git a/contrib/python/lz4/py3/ya.make b/contrib/python/lz4/py3/ya.make index 90442055a36..4fd0725b1ee 100644 --- a/contrib/python/lz4/py3/ya.make +++ b/contrib/python/lz4/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(4.4.4) +VERSION(4.4.5) LICENSE(BSD-3-Clause) |
