aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-01-31 11:50:40 +0300
committerAlexander Smirnov <alex@ydb.tech>2024-01-31 14:24:23 +0300
commit24224c8cb74d4d8a6cc0fe7ecb4e78e315e0d945 (patch)
tree67f82419968d3906da780c7a4cc7b6cb68e50050
parent636f483b4d31b42e989912db9acb7b451ce0b477 (diff)
downloadydb-24224c8cb74d4d8a6cc0fe7ecb4e78e315e0d945.tar.gz
Intermediate changes
-rw-r--r--contrib/python/hypothesis/py3/.dist-info/METADATA2
-rw-r--r--contrib/python/hypothesis/py3/.dist-info/top_level.txt1
-rw-r--r--contrib/python/hypothesis/py3/_hypothesis_globals.py28
-rw-r--r--contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py25
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/__init__.py5
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/configuration.py62
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/database.py4
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/errors.py7
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py20
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/strategies/_internal/deferred.py3
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/strategies/_internal/lazy.py3
-rw-r--r--contrib/python/hypothesis/py3/hypothesis/version.py2
-rw-r--r--contrib/python/hypothesis/py3/ya.make3
-rw-r--r--yt/yt/client/table_client/schema.cpp1
14 files changed, 157 insertions, 9 deletions
diff --git a/contrib/python/hypothesis/py3/.dist-info/METADATA b/contrib/python/hypothesis/py3/.dist-info/METADATA
index fd179215d8..c94200ebd3 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.93.2
+Version: 6.94.0
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/.dist-info/top_level.txt b/contrib/python/hypothesis/py3/.dist-info/top_level.txt
index 93b8370b8d..77a969c858 100644
--- a/contrib/python/hypothesis/py3/.dist-info/top_level.txt
+++ b/contrib/python/hypothesis/py3/.dist-info/top_level.txt
@@ -1,3 +1,4 @@
_hypothesis_ftz_detector
+_hypothesis_globals
_hypothesis_pytestplugin
hypothesis
diff --git a/contrib/python/hypothesis/py3/_hypothesis_globals.py b/contrib/python/hypothesis/py3/_hypothesis_globals.py
new file mode 100644
index 0000000000..e97e091879
--- /dev/null
+++ b/contrib/python/hypothesis/py3/_hypothesis_globals.py
@@ -0,0 +1,28 @@
+# This file is part of Hypothesis, which may be found at
+# https://github.com/HypothesisWorks/hypothesis/
+#
+# Copyright the Hypothesis Authors.
+# Individual contributors are listed in AUTHORS.rst and the git log.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public License,
+# 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/.
+
+"""
+Module for globals shared between plugin(s) and the main hypothesis module, without
+depending on either. This file should have no imports outside of stdlib.
+"""
+
+import os
+
+in_initialization = 1
+"""If nonzero, indicates that hypothesis is still initializing (importing or loading
+the test environment). `import hypothesis` will cause this number to be decremented,
+and the pytest plugin increments at load time, then decrements it just before the test
+session starts. However, this leads to a hole in coverage if another pytest plugin
+imports hypothesis before our plugin is loaded. HYPOTHESIS_EXTEND_INITIALIZATION may
+be set to pre-increment the value on behalf of _hypothesis_pytestplugin, plugging the
+hole."""
+
+if os.environ.get("HYPOTHESIS_EXTEND_INITIALIZATION"):
+ in_initialization += 1
diff --git a/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py b/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py
index 9875e067f5..944304ccdb 100644
--- a/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py
+++ b/contrib/python/hypothesis/py3/_hypothesis_pytestplugin.py
@@ -21,9 +21,12 @@ See https://github.com/HypothesisWorks/hypothesis/issues/3140 for details.
import base64
import json
+import os
import sys
+import warnings
from inspect import signature
+import _hypothesis_globals
import pytest
try:
@@ -94,6 +97,19 @@ if tuple(map(int, pytest.__version__.split(".")[:2])) < (4, 6): # pragma: no co
warnings.warn(PYTEST_TOO_OLD_MESSAGE % (pytest.__version__,), stacklevel=1)
else:
+ # Restart side-effect detection as early as possible, to maximize coverage. We
+ # need balanced increment/decrement in configure/sessionstart to support nested
+ # pytest (e.g. runpytest_inprocess), so this early increment in effect replaces
+ # the first one in pytest_configure.
+ _configured = False
+ if not os.environ.get("HYPOTHESIS_EXTEND_INITIALIZATION"):
+ _hypothesis_globals.in_initialization += 1
+ if "hypothesis" in sys.modules:
+ # Some other plugin has imported hypothesis, so we'll check if there
+ # have been undetected side-effects and warn if so.
+ from hypothesis.configuration import notice_initialization_restarted
+
+ notice_initialization_restarted()
def pytest_addoption(parser):
group = parser.getgroup("hypothesis", "Hypothesis")
@@ -147,6 +163,12 @@ else:
return f"hypothesis profile {settings._current_profile!r}{settings_str}"
def pytest_configure(config):
+ global _configured
+ # skip first increment because we pre-incremented at import time
+ if _configured:
+ _hypothesis_globals.in_initialization += 1
+ _configured = True
+
config.addinivalue_line("markers", "hypothesis: Tests which use hypothesis.")
if not _any_hypothesis_option(config):
return
@@ -407,6 +429,9 @@ else:
if isinstance(item, pytest.Function) and is_hypothesis_test(item.obj):
item.add_marker("hypothesis")
+ def pytest_sessionstart(session):
+ _hypothesis_globals.in_initialization -= 1
+
# Monkeypatch some internals to prevent applying @pytest.fixture() to a
# function which has already been decorated with @hypothesis.given().
# (the reverse case is already an explicit error in Hypothesis)
diff --git a/contrib/python/hypothesis/py3/hypothesis/__init__.py b/contrib/python/hypothesis/py3/hypothesis/__init__.py
index db140b8165..cfb55119f7 100644
--- a/contrib/python/hypothesis/py3/hypothesis/__init__.py
+++ b/contrib/python/hypothesis/py3/hypothesis/__init__.py
@@ -15,6 +15,8 @@ It verifies your code against a wide range of input and minimizes any
failing examples it finds.
"""
+import _hypothesis_globals
+
from hypothesis._settings import HealthCheck, Phase, Verbosity, settings
from hypothesis.control import (
assume,
@@ -54,3 +56,6 @@ __all__ = [
run()
del run
+
+_hypothesis_globals.in_initialization -= 1
+del _hypothesis_globals
diff --git a/contrib/python/hypothesis/py3/hypothesis/configuration.py b/contrib/python/hypothesis/py3/hypothesis/configuration.py
index 6e6ab29516..2586c729f7 100644
--- a/contrib/python/hypothesis/py3/hypothesis/configuration.py
+++ b/contrib/python/hypothesis/py3/hypothesis/configuration.py
@@ -9,8 +9,13 @@
# obtain one at https://mozilla.org/MPL/2.0/.
import os
+import warnings
from pathlib import Path
+import _hypothesis_globals
+
+from hypothesis.errors import HypothesisSideeffectWarning
+
__hypothesis_home_directory_default = Path.cwd() / ".hypothesis"
__hypothesis_home_directory = None
@@ -21,7 +26,12 @@ def set_hypothesis_home_dir(directory):
__hypothesis_home_directory = None if directory is None else Path(directory)
-def storage_directory(*names):
+def storage_directory(*names, intent_to_write=True):
+ if intent_to_write:
+ check_sideeffect_during_initialization(
+ "accessing storage for {}", "/".join(names)
+ )
+
global __hypothesis_home_directory
if not __hypothesis_home_directory:
if where := os.getenv("HYPOTHESIS_STORAGE_DIRECTORY"):
@@ -29,3 +39,53 @@ def storage_directory(*names):
if not __hypothesis_home_directory:
__hypothesis_home_directory = __hypothesis_home_directory_default
return __hypothesis_home_directory.joinpath(*names)
+
+
+_first_postinit_what = None
+
+
+def check_sideeffect_during_initialization(
+ what: str, *fmt_args: object, extra: str = ""
+) -> None:
+ """Called from locations that should not be executed during initialization, for example
+ touching disk or materializing lazy/deferred strategies from plugins. If initialization
+ is in progress, a warning is emitted.
+
+ Note that computing the repr can take nontrivial time or memory, so we avoid doing so
+ unless (and until) we're actually emitting the warning.
+ """
+ global _first_postinit_what
+ # This is not a particularly hot path, but neither is it doing productive work, so we want to
+ # minimize the cost by returning immediately. The drawback is that we require
+ # notice_initialization_restarted() to be called if in_initialization changes away from zero.
+ if _first_postinit_what is not None:
+ return
+ elif _hypothesis_globals.in_initialization:
+ # Note: -Werror is insufficient under pytest, as doesn't take effect until
+ # test session start.
+ msg = what.format(*fmt_args)
+ warnings.warn(
+ f"Slow code in plugin: avoid {msg} at import time! Set PYTHONWARNINGS=error "
+ "to get a traceback and show which plugin is responsible." + extra,
+ HypothesisSideeffectWarning,
+ stacklevel=3,
+ )
+ else:
+ _first_postinit_what = (what, fmt_args)
+
+
+def notice_initialization_restarted(*, warn: bool = True) -> None:
+ """Reset _first_postinit_what, so that we don't think we're in post-init. Additionally, if it
+ was set that means that there has been a sideeffect that we haven't warned about, so do that
+ now (the warning text will be correct, and we also hint that the stacktrace can be improved).
+ """
+ global _first_postinit_what
+ if _first_postinit_what is not None:
+ what, *fmt_args = _first_postinit_what
+ _first_postinit_what = None
+ if warn:
+ check_sideeffect_during_initialization(
+ what,
+ *fmt_args,
+ extra=" Additionally, set HYPOTHESIS_EXTEND_INITIALIZATION=1 to pinpoint the exact location.",
+ )
diff --git a/contrib/python/hypothesis/py3/hypothesis/database.py b/contrib/python/hypothesis/py3/hypothesis/database.py
index 4abce10c01..9fbdd31597 100644
--- a/contrib/python/hypothesis/py3/hypothesis/database.py
+++ b/contrib/python/hypothesis/py3/hypothesis/database.py
@@ -59,7 +59,7 @@ def _db_for_path(path=None):
"https://hypothesis.readthedocs.io/en/latest/settings.html#settings-profiles"
)
- path = storage_directory("examples")
+ path = storage_directory("examples", intent_to_write=False)
if not _usable_dir(path): # pragma: no cover
warnings.warn(
"The database setting is not configured, and the default "
@@ -495,6 +495,8 @@ class GitHubArtifactDatabase(ExampleDatabase):
self._initialized = True
def _initialize_db(self) -> None:
+ # Trigger warning that we suppressed earlier by intent_to_write=False
+ storage_directory(self.path.name)
# Create the cache directory if it doesn't exist
self.path.mkdir(exist_ok=True, parents=True)
diff --git a/contrib/python/hypothesis/py3/hypothesis/errors.py b/contrib/python/hypothesis/py3/hypothesis/errors.py
index 8387a87586..0d376a7493 100644
--- a/contrib/python/hypothesis/py3/hypothesis/errors.py
+++ b/contrib/python/hypothesis/py3/hypothesis/errors.py
@@ -117,6 +117,13 @@ class HypothesisDeprecationWarning(HypothesisWarning, FutureWarning):
"""
+class HypothesisSideeffectWarning(HypothesisWarning):
+ """A warning issued by Hypothesis when it sees actions that are
+ discouraged at import or initialization time because they are
+ slow or have user-visible side effects.
+ """
+
+
class Frozen(HypothesisException):
"""Raised when a mutation method has been called on a ConjectureData object
after freeze() has been called."""
diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py
index 804901268b..028d8405c7 100644
--- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py
+++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/core.py
@@ -55,6 +55,7 @@ import attr
from hypothesis._settings import note_deprecation
from hypothesis.control import cleanup, current_build_context, note
from hypothesis.errors import (
+ HypothesisSideeffectWarning,
HypothesisWarning,
InvalidArgument,
ResolutionFailed,
@@ -2196,14 +2197,25 @@ def register_type_strategy(
f"{custom_type=} is not allowed to be registered, "
f"because there is no such thing as a runtime instance of {custom_type!r}"
)
- elif not (isinstance(strategy, SearchStrategy) or callable(strategy)):
+ if not (isinstance(strategy, SearchStrategy) or callable(strategy)):
raise InvalidArgument(
f"{strategy=} must be a SearchStrategy, or a function that takes "
"a generic type and returns a specific SearchStrategy"
)
- elif isinstance(strategy, SearchStrategy) and strategy.is_empty:
- raise InvalidArgument(f"{strategy=} must not be empty")
- elif types.has_type_arguments(custom_type):
+ if isinstance(strategy, SearchStrategy):
+ with warnings.catch_warnings():
+ warnings.simplefilter("error", HypothesisSideeffectWarning)
+
+ # Calling is_empty forces materialization of lazy strategies. If this is done at import
+ # time, lazy strategies will warn about it; here, we force that warning to raise to
+ # avoid the materialization. Ideally, we'd just check if the strategy is lazy, but the
+ # lazy strategy may be wrapped underneath another strategy so that's complicated.
+ try:
+ if strategy.is_empty:
+ raise InvalidArgument(f"{strategy=} must not be empty")
+ except HypothesisSideeffectWarning: # pragma: no cover
+ pass
+ if types.has_type_arguments(custom_type):
raise InvalidArgument(
f"Cannot register generic type {custom_type!r}, because it has type "
"arguments which would not be handled. Instead, register a function "
diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/deferred.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/deferred.py
index 489b4d7b7a..f7dae9a1e5 100644
--- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/deferred.py
+++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/deferred.py
@@ -10,6 +10,7 @@
import inspect
+from hypothesis.configuration import check_sideeffect_during_initialization
from hypothesis.errors import InvalidArgument
from hypothesis.internal.reflection import get_pretty_function_description
from hypothesis.strategies._internal.strategies import SearchStrategy, check_strategy
@@ -27,6 +28,8 @@ class DeferredStrategy(SearchStrategy):
@property
def wrapped_strategy(self):
if self.__wrapped_strategy is None:
+ check_sideeffect_during_initialization("deferred evaluation of {!r}", self)
+
if not inspect.isfunction(self.__definition):
raise InvalidArgument(
f"Expected definition to be a function but got {self.__definition!r} "
diff --git a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/lazy.py b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/lazy.py
index 5e493a9099..d6bb13c7c1 100644
--- a/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/lazy.py
+++ b/contrib/python/hypothesis/py3/hypothesis/strategies/_internal/lazy.py
@@ -12,6 +12,7 @@ from inspect import signature
from typing import MutableMapping
from weakref import WeakKeyDictionary
+from hypothesis.configuration import check_sideeffect_during_initialization
from hypothesis.internal.reflection import (
convert_keyword_arguments,
convert_positional_arguments,
@@ -100,6 +101,8 @@ class LazyStrategy(SearchStrategy):
@property
def wrapped_strategy(self):
if self.__wrapped_strategy is None:
+ check_sideeffect_during_initialization("lazy evaluation of {!r}", self)
+
unwrapped_args = tuple(unwrap_strategies(s) for s in self.__args)
unwrapped_kwargs = {
k: unwrap_strategies(v) for k, v in self.__kwargs.items()
diff --git a/contrib/python/hypothesis/py3/hypothesis/version.py b/contrib/python/hypothesis/py3/hypothesis/version.py
index dc8e1e70f0..fd4613cb61 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, 93, 2)
+__version_info__ = (6, 94, 0)
__version__ = ".".join(map(str, __version_info__))
diff --git a/contrib/python/hypothesis/py3/ya.make b/contrib/python/hypothesis/py3/ya.make
index 3e25d0b11c..476e93730e 100644
--- a/contrib/python/hypothesis/py3/ya.make
+++ b/contrib/python/hypothesis/py3/ya.make
@@ -2,7 +2,7 @@
PY3_LIBRARY()
-VERSION(6.93.2)
+VERSION(6.94.0)
LICENSE(MPL-2.0)
@@ -20,6 +20,7 @@ NO_CHECK_IMPORTS(
PY_SRCS(
TOP_LEVEL
_hypothesis_ftz_detector.py
+ _hypothesis_globals.py
_hypothesis_pytestplugin.py
hypothesis/__init__.py
hypothesis/_settings.py
diff --git a/yt/yt/client/table_client/schema.cpp b/yt/yt/client/table_client/schema.cpp
index 2717aaeb8a..733d997ffc 100644
--- a/yt/yt/client/table_client/schema.cpp
+++ b/yt/yt/client/table_client/schema.cpp
@@ -1514,6 +1514,7 @@ void ValidateColumnSchema(
"first",
"xdelta",
"_yt_stored_replica_set",
+ "_yt_last_seen_replica_set",
};
const auto& stableName = columnSchema.StableName();