diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-02-08 17:10:05 +0300 |
---|---|---|
committer | Alexander Smirnov <alex@ydb.tech> | 2024-02-09 19:18:57 +0300 |
commit | c3aeaf50a59a913402896eaddfe07ef0b9312e83 (patch) | |
tree | b1b1e1c112459e0ff307ca363116636f7477e6ec /contrib/python | |
parent | 05cec57c0cf6f640048593124d360162ade5efba (diff) | |
download | ydb-c3aeaf50a59a913402896eaddfe07ef0b9312e83.tar.gz |
Intermediate changes
Diffstat (limited to 'contrib/python')
-rw-r--r-- | contrib/python/pluggy/py3/.dist-info/METADATA | 2 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/pluggy/__init__.py | 6 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/pluggy/_callers.py | 39 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/pluggy/_hooks.py | 22 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/pluggy/_manager.py | 18 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/pluggy/_result.py | 15 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/pluggy/_version.py | 16 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/pluggy/_warnings.py | 27 | ||||
-rw-r--r-- | contrib/python/pluggy/py3/ya.make | 3 |
9 files changed, 117 insertions, 31 deletions
diff --git a/contrib/python/pluggy/py3/.dist-info/METADATA b/contrib/python/pluggy/py3/.dist-info/METADATA index 684704f432..c4c3312518 100644 --- a/contrib/python/pluggy/py3/.dist-info/METADATA +++ b/contrib/python/pluggy/py3/.dist-info/METADATA @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: pluggy -Version: 1.3.0 +Version: 1.4.0 Summary: plugin and hook calling mechanisms for python Home-page: https://github.com/pytest-dev/pluggy Author: Holger Krekel diff --git a/contrib/python/pluggy/py3/pluggy/__init__.py b/contrib/python/pluggy/py3/pluggy/__init__.py index 9d9e873bd0..2adf9454f8 100644 --- a/contrib/python/pluggy/py3/pluggy/__init__.py +++ b/contrib/python/pluggy/py3/pluggy/__init__.py @@ -18,6 +18,8 @@ __all__ = [ "HookspecMarker", "HookimplMarker", "Result", + "PluggyWarning", + "PluggyTeardownRaisedWarning", ] from ._manager import PluginManager, PluginValidationError @@ -31,3 +33,7 @@ from ._hooks import ( HookimplOpts, HookImpl, ) +from ._warnings import ( + PluggyWarning, + PluggyTeardownRaisedWarning, +) diff --git a/contrib/python/pluggy/py3/pluggy/_callers.py b/contrib/python/pluggy/py3/pluggy/_callers.py index 6498eaed64..787f56bac2 100644 --- a/contrib/python/pluggy/py3/pluggy/_callers.py +++ b/contrib/python/pluggy/py3/pluggy/_callers.py @@ -3,27 +3,52 @@ Call loop machinery """ from __future__ import annotations +import warnings from typing import cast from typing import Generator from typing import Mapping +from typing import NoReturn from typing import Sequence from typing import Tuple from typing import Union from ._hooks import HookImpl -from ._result import _raise_wrapfail from ._result import HookCallError from ._result import Result +from ._warnings import PluggyTeardownRaisedWarning # Need to distinguish between old- and new-style hook wrappers. -# Wrapping one a singleton tuple is the fastest type-safe way I found to do it. +# Wrapping with a tuple is the fastest type-safe way I found to do it. Teardown = Union[ - Tuple[Generator[None, Result[object], None]], + Tuple[Generator[None, Result[object], None], HookImpl], Generator[None, object, object], ] +def _raise_wrapfail( + wrap_controller: ( + Generator[None, Result[object], None] | Generator[None, object, object] + ), + msg: str, +) -> NoReturn: + co = wrap_controller.gi_code + raise RuntimeError( + "wrap_controller at %r %s:%d %s" + % (co.co_name, co.co_filename, co.co_firstlineno, msg) + ) + + +def _warn_teardown_exception( + hook_name: str, hook_impl: HookImpl, e: BaseException +) -> None: + msg = "A plugin raised an exception during an old-style hookwrapper teardown.\n" + msg += f"Plugin: {hook_impl.plugin_name}, Hook: {hook_name}\n" + msg += f"{type(e).__name__}: {e}\n" + msg += "For more information see https://pluggy.readthedocs.io/en/stable/api_reference.html#pluggy.PluggyTeardownRaisedWarning" # noqa: E501 + warnings.warn(PluggyTeardownRaisedWarning(msg), stacklevel=5) + + def _multicall( hook_name: str, hook_impls: Sequence[HookImpl], @@ -60,7 +85,7 @@ def _multicall( res = hook_impl.function(*args) wrapper_gen = cast(Generator[None, Result[object], None], res) next(wrapper_gen) # first yield - teardowns.append((wrapper_gen,)) + teardowns.append((wrapper_gen, hook_impl)) except StopIteration: _raise_wrapfail(wrapper_gen, "did not yield") elif hook_impl.wrapper: @@ -128,9 +153,13 @@ def _multicall( if isinstance(teardown, tuple): try: teardown[0].send(outcome) - _raise_wrapfail(teardown[0], "has second yield") except StopIteration: pass + except BaseException as e: + _warn_teardown_exception(hook_name, teardown[1], e) + raise + else: + _raise_wrapfail(teardown[0], "has second yield") else: try: if outcome._exception is not None: diff --git a/contrib/python/pluggy/py3/pluggy/_hooks.py b/contrib/python/pluggy/py3/pluggy/_hooks.py index 916ca70489..7c8420f4de 100644 --- a/contrib/python/pluggy/py3/pluggy/_hooks.py +++ b/contrib/python/pluggy/py3/pluggy/_hooks.py @@ -389,6 +389,13 @@ class HookCaller: #: Name of the hook getting called. self.name: Final = name self._hookexec: Final = hook_execute + # The hookimpls list. The caller iterates it *in reverse*. Format: + # 1. trylast nonwrappers + # 2. nonwrappers + # 3. tryfirst nonwrappers + # 4. trylast wrappers + # 5. wrappers + # 6. tryfirst wrappers self._hookimpls: Final[list[HookImpl]] = [] self._call_history: _CallHistory | None = None # TODO: Document, or make private. @@ -490,7 +497,8 @@ class HookCaller: ), "Cannot directly call a historic hook - use call_historic instead." self._verify_all_args_are_provided(kwargs) firstresult = self.spec.opts.get("firstresult", False) if self.spec else False - return self._hookexec(self.name, self._hookimpls, kwargs, firstresult) + # Copy because plugins may register other plugins during iteration (#438). + return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) def call_historic( self, @@ -511,7 +519,8 @@ class HookCaller: self._call_history.append((kwargs, result_callback)) # Historizing hooks don't return results. # Remember firstresult isn't compatible with historic. - res = self._hookexec(self.name, self._hookimpls, kwargs, False) + # Copy because plugins may register other plugins during iteration (#438). + res = self._hookexec(self.name, self._hookimpls.copy(), kwargs, False) if result_callback is None: return if isinstance(res, list): @@ -541,10 +550,11 @@ class HookCaller: hookimpl = HookImpl(None, "<temp>", method, opts) # Find last non-tryfirst nonwrapper method. i = len(hookimpls) - 1 - while ( - i >= 0 - and hookimpls[i].tryfirst - and not (hookimpls[i].hookwrapper or hookimpls[i].wrapper) + while i >= 0 and ( + # Skip wrappers. + (hookimpls[i].hookwrapper or hookimpls[i].wrapper) + # Skip tryfirst nonwrappers. + or hookimpls[i].tryfirst ): i -= 1 hookimpls.insert(i + 1, hookimpl) diff --git a/contrib/python/pluggy/py3/pluggy/_manager.py b/contrib/python/pluggy/py3/pluggy/_manager.py index 84717e6eaa..ce1e107a60 100644 --- a/contrib/python/pluggy/py3/pluggy/_manager.py +++ b/contrib/python/pluggy/py3/pluggy/_manager.py @@ -1,6 +1,5 @@ from __future__ import annotations -import importlib.metadata import inspect import types import warnings @@ -11,6 +10,7 @@ from typing import Final from typing import Iterable from typing import Mapping from typing import Sequence +from typing import TYPE_CHECKING from . import _tracing from ._callers import _multicall @@ -26,6 +26,10 @@ from ._hooks import HookspecOpts from ._hooks import normalize_hookimpl_opts from ._result import Result +if TYPE_CHECKING: + # importtlib.metadata import is slow, defer it. + import importlib.metadata + _BeforeTrace = Callable[[str, Sequence[HookImpl], Mapping[str, Any]], None] _AfterTrace = Callable[[Result[Any], str, Sequence[HookImpl], Mapping[str, Any]], None] @@ -231,6 +235,16 @@ class PluginManager: """Return whether the given plugin name is blocked.""" return name in self._name2plugin and self._name2plugin[name] is None + def unblock(self, name: str) -> bool: + """Unblocks a name. + + Returns whether the name was actually blocked. + """ + if self._name2plugin.get(name, -1) is None: + del self._name2plugin[name] + return True + return False + def add_hookspecs(self, module_or_class: _Namespace) -> None: """Add new hook specifications defined in the given ``module_or_class``. @@ -384,6 +398,8 @@ class PluginManager: :return: The number of plugins loaded by this call. """ + import importlib.metadata + count = 0 for dist in list(importlib.metadata.distributions()): for ep in dist.entry_points: diff --git a/contrib/python/pluggy/py3/pluggy/_result.py b/contrib/python/pluggy/py3/pluggy/_result.py index 29859eb92d..aa21fa1380 100644 --- a/contrib/python/pluggy/py3/pluggy/_result.py +++ b/contrib/python/pluggy/py3/pluggy/_result.py @@ -7,9 +7,7 @@ from types import TracebackType from typing import Callable from typing import cast from typing import final -from typing import Generator from typing import Generic -from typing import NoReturn from typing import Optional from typing import Tuple from typing import Type @@ -20,19 +18,6 @@ _ExcInfo = Tuple[Type[BaseException], BaseException, Optional[TracebackType]] ResultType = TypeVar("ResultType") -def _raise_wrapfail( - wrap_controller: ( - Generator[None, Result[ResultType], None] | Generator[None, object, object] - ), - msg: str, -) -> NoReturn: - co = wrap_controller.gi_code - raise RuntimeError( - "wrap_controller at %r %s:%d %s" - % (co.co_name, co.co_filename, co.co_firstlineno, msg) - ) - - class HookCallError(Exception): """Hook was called incorrectly.""" diff --git a/contrib/python/pluggy/py3/pluggy/_version.py b/contrib/python/pluggy/py3/pluggy/_version.py index 4a742d246f..ee6c4d7d05 100644 --- a/contrib/python/pluggy/py3/pluggy/_version.py +++ b/contrib/python/pluggy/py3/pluggy/_version.py @@ -1,4 +1,16 @@ # file generated by setuptools_scm # don't change, don't track in version control -__version__ = version = '1.3.0' -__version_tuple__ = version_tuple = (1, 3, 0) +TYPE_CHECKING = False +if TYPE_CHECKING: + from typing import Tuple, Union + VERSION_TUPLE = Tuple[Union[int, str], ...] +else: + VERSION_TUPLE = object + +version: str +__version__: str +__version_tuple__: VERSION_TUPLE +version_tuple: VERSION_TUPLE + +__version__ = version = '1.4.0' +__version_tuple__ = version_tuple = (1, 4, 0) diff --git a/contrib/python/pluggy/py3/pluggy/_warnings.py b/contrib/python/pluggy/py3/pluggy/_warnings.py new file mode 100644 index 0000000000..6356c770c7 --- /dev/null +++ b/contrib/python/pluggy/py3/pluggy/_warnings.py @@ -0,0 +1,27 @@ +from typing import final + + +class PluggyWarning(UserWarning): + """Base class for all warnings emitted by pluggy.""" + + __module__ = "pluggy" + + +@final +class PluggyTeardownRaisedWarning(PluggyWarning): + """A plugin raised an exception during an :ref:`old-style hookwrapper + <old_style_hookwrappers>` teardown. + + Such exceptions are not handled by pluggy, and may cause subsequent + teardowns to be executed at unexpected times, or be skipped entirely. + + This is an issue in the plugin implementation. + + If the exception is unintended, fix the underlying cause. + + If the exception is intended, switch to :ref:`new-style hook wrappers + <hookwrappers>`, or use :func:`result.force_exception() + <pluggy.Result.force_exception>` to set the exception instead of raising. + """ + + __module__ = "pluggy" diff --git a/contrib/python/pluggy/py3/ya.make b/contrib/python/pluggy/py3/ya.make index 7302e7c37d..8dc442cdd1 100644 --- a/contrib/python/pluggy/py3/ya.make +++ b/contrib/python/pluggy/py3/ya.make @@ -2,7 +2,7 @@ PY3_LIBRARY() -VERSION(1.3.0) +VERSION(1.4.0) LICENSE(MIT) @@ -17,6 +17,7 @@ PY_SRCS( pluggy/_result.py pluggy/_tracing.py pluggy/_version.py + pluggy/_warnings.py ) RESOURCE_FILES( |