diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-09 12:00:52 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 15:58:17 +0300 |
commit | 8e1413fed79d1e8036e65228af6c93399ccf5502 (patch) | |
tree | 502c9df7b2614d20541c7a2d39d390e9a51877cc /contrib/python/pytest/py3/_pytest/recwarn.py | |
parent | 6b813c17d56d1d05f92c61ddc347d0e4d358fe85 (diff) | |
download | ydb-8e1413fed79d1e8036e65228af6c93399ccf5502.tar.gz |
intermediate changes
ref:614ed510ddd3cdf86a8c5dbf19afd113397e0172
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/recwarn.py')
-rw-r--r-- | contrib/python/pytest/py3/_pytest/recwarn.py | 134 |
1 files changed, 83 insertions, 51 deletions
diff --git a/contrib/python/pytest/py3/_pytest/recwarn.py b/contrib/python/pytest/py3/_pytest/recwarn.py index c57c94b1cb1..d872d9da401 100644 --- a/contrib/python/pytest/py3/_pytest/recwarn.py +++ b/contrib/python/pytest/py3/_pytest/recwarn.py @@ -1,53 +1,79 @@ -""" recording warnings during test function execution. """ +"""Record warnings during test function execution.""" import re import warnings from types import TracebackType from typing import Any from typing import Callable +from typing import Generator from typing import Iterator from typing import List from typing import Optional +from typing import overload from typing import Pattern from typing import Tuple +from typing import Type +from typing import TypeVar from typing import Union -from _pytest.compat import overload -from _pytest.compat import TYPE_CHECKING -from _pytest.fixtures import yield_fixture +from _pytest.compat import final +from _pytest.deprecated import check_ispytest +from _pytest.fixtures import fixture from _pytest.outcomes import fail -if TYPE_CHECKING: - from typing import Type +T = TypeVar("T") -@yield_fixture -def recwarn(): + +@fixture +def recwarn() -> Generator["WarningsRecorder", None, None]: """Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See http://docs.python.org/library/warnings.html for information on warning categories. """ - wrec = WarningsRecorder() + wrec = WarningsRecorder(_ispytest=True) with wrec: warnings.simplefilter("default") yield wrec -def deprecated_call(func=None, *args, **kwargs): - """context manager that can be used to ensure a block of code triggers a - ``DeprecationWarning`` or ``PendingDeprecationWarning``:: +@overload +def deprecated_call( + *, match: Optional[Union[str, Pattern[str]]] = ... +) -> "WarningsRecorder": + ... + + +@overload +def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: + ... + + +def deprecated_call( + func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any +) -> Union["WarningsRecorder", Any]: + """Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning``. + + This function can be used as a context manager:: >>> import warnings >>> def api_call_v2(): ... warnings.warn('use v3 of this api', DeprecationWarning) ... return 200 - >>> with deprecated_call(): + >>> import pytest + >>> with pytest.deprecated_call(): ... assert api_call_v2() == 200 - ``deprecated_call`` can also be used by passing a function and ``*args`` and ``*kwargs``, - in which case it will ensure calling ``func(*args, **kwargs)`` produces one of the warnings - types above. + It can also be used by passing a function and ``*args`` and ``**kwargs``, + in which case it will ensure calling ``func(*args, **kwargs)`` produces one of + the warnings types above. The return value is the return value of the function. + + In the context manager form you may use the keyword argument ``match`` to assert + that the warning matches a text or regex. + + The context manager produces a list of :class:`warnings.WarningMessage` objects, + one for each warning raised. """ __tracebackhide__ = True if func is not None: @@ -57,29 +83,28 @@ def deprecated_call(func=None, *args, **kwargs): @overload def warns( - expected_warning: Optional[Union["Type[Warning]", Tuple["Type[Warning]", ...]]], + expected_warning: Optional[Union[Type[Warning], Tuple[Type[Warning], ...]]], *, - match: "Optional[Union[str, Pattern]]" = ... + match: Optional[Union[str, Pattern[str]]] = ..., ) -> "WarningsChecker": - raise NotImplementedError() + ... -@overload # noqa: F811 -def warns( # noqa: F811 - expected_warning: Optional[Union["Type[Warning]", Tuple["Type[Warning]", ...]]], - func: Callable, +@overload +def warns( + expected_warning: Optional[Union[Type[Warning], Tuple[Type[Warning], ...]]], + func: Callable[..., T], *args: Any, - match: Optional[Union[str, "Pattern"]] = ..., - **kwargs: Any -) -> Union[Any]: - raise NotImplementedError() + **kwargs: Any, +) -> T: + ... -def warns( # noqa: F811 - expected_warning: Optional[Union["Type[Warning]", Tuple["Type[Warning]", ...]]], +def warns( + expected_warning: Optional[Union[Type[Warning], Tuple[Type[Warning], ...]]], *args: Any, - match: Optional[Union[str, "Pattern"]] = None, - **kwargs: Any + match: Optional[Union[str, Pattern[str]]] = None, + **kwargs: Any, ) -> Union["WarningsChecker", Any]: r"""Assert that code raises a particular class of warning. @@ -91,21 +116,22 @@ def warns( # noqa: F811 one for each warning raised. This function can be used as a context manager, or any of the other ways - ``pytest.raises`` can be used:: + :func:`pytest.raises` can be used:: - >>> with warns(RuntimeWarning): + >>> import pytest + >>> with pytest.warns(RuntimeWarning): ... warnings.warn("my warning", RuntimeWarning) In the context manager form you may use the keyword argument ``match`` to assert - that the exception matches a text or regex:: + that the warning matches a text or regex:: - >>> with warns(UserWarning, match='must be 0 or None'): + >>> with pytest.warns(UserWarning, match='must be 0 or None'): ... warnings.warn("value must be 0 or None", UserWarning) - >>> with warns(UserWarning, match=r'must be \d+$'): + >>> with pytest.warns(UserWarning, match=r'must be \d+$'): ... warnings.warn("value must be 42", UserWarning) - >>> with warns(UserWarning, match=r'must be \d+$'): + >>> with pytest.warns(UserWarning, match=r'must be \d+$'): ... warnings.warn("this is not here", UserWarning) Traceback (most recent call last): ... @@ -119,14 +145,14 @@ def warns( # noqa: F811 msg += ", ".join(sorted(kwargs)) msg += "\nUse context-manager form instead?" raise TypeError(msg) - return WarningsChecker(expected_warning, match_expr=match) + return WarningsChecker(expected_warning, match_expr=match, _ispytest=True) else: func = args[0] if not callable(func): raise TypeError( "{!r} object (type: {}) must be callable".format(func, type(func)) ) - with WarningsChecker(expected_warning): + with WarningsChecker(expected_warning, _ispytest=True): return func(*args[1:], **kwargs) @@ -136,21 +162,23 @@ class WarningsRecorder(warnings.catch_warnings): Adapted from `warnings.catch_warnings`. """ - def __init__(self): - super().__init__(record=True) + def __init__(self, *, _ispytest: bool = False) -> None: + check_ispytest(_ispytest) + # Type ignored due to the way typeshed handles warnings.catch_warnings. + super().__init__(record=True) # type: ignore[call-arg] self._entered = False - self._list = [] # type: List[warnings._Record] + self._list: List[warnings.WarningMessage] = [] @property - def list(self) -> List["warnings._Record"]: + def list(self) -> List["warnings.WarningMessage"]: """The list of recorded warnings.""" return self._list - def __getitem__(self, i: int) -> "warnings._Record": + def __getitem__(self, i: int) -> "warnings.WarningMessage": """Get a recorded warning by index.""" return self._list[i] - def __iter__(self) -> Iterator["warnings._Record"]: + def __iter__(self) -> Iterator["warnings.WarningMessage"]: """Iterate through the recorded warnings.""" return iter(self._list) @@ -158,7 +186,7 @@ class WarningsRecorder(warnings.catch_warnings): """The number of recorded warnings.""" return len(self._list) - def pop(self, cls: "Type[Warning]" = Warning) -> "warnings._Record": + def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": """Pop the first recorded warning, raise exception if not exists.""" for i, w in enumerate(self._list): if issubclass(w.category, cls): @@ -185,7 +213,7 @@ class WarningsRecorder(warnings.catch_warnings): def __exit__( self, - exc_type: Optional["Type[BaseException]"], + exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType], ) -> None: @@ -200,15 +228,19 @@ class WarningsRecorder(warnings.catch_warnings): self._entered = False +@final class WarningsChecker(WarningsRecorder): def __init__( self, expected_warning: Optional[ - Union["Type[Warning]", Tuple["Type[Warning]", ...]] + Union[Type[Warning], Tuple[Type[Warning], ...]] ] = None, - match_expr: Optional[Union[str, "Pattern"]] = None, + match_expr: Optional[Union[str, Pattern[str]]] = None, + *, + _ispytest: bool = False, ) -> None: - super().__init__() + check_ispytest(_ispytest) + super().__init__(_ispytest=True) msg = "exceptions must be derived from Warning, not %s" if expected_warning is None: @@ -228,7 +260,7 @@ class WarningsChecker(WarningsRecorder): def __exit__( self, - exc_type: Optional["Type[BaseException]"], + exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType], ) -> None: |