diff options
author | deshevoy <deshevoy@yandex-team.ru> | 2022-02-10 16:46:56 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:56 +0300 |
commit | e988f30484abe5fdeedcc7a5d3c226c01a21800c (patch) | |
tree | 0a217b173aabb57b7e51f8a169989b1a3e0309fe /contrib/python/pytest/py3/_pytest/compat.py | |
parent | 33ee501c05d3f24036ae89766a858930ae66c548 (diff) | |
download | ydb-e988f30484abe5fdeedcc7a5d3c226c01a21800c.tar.gz |
Restoring authorship annotation for <deshevoy@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/compat.py')
-rw-r--r-- | contrib/python/pytest/py3/_pytest/compat.py | 334 |
1 files changed, 167 insertions, 167 deletions
diff --git a/contrib/python/pytest/py3/_pytest/compat.py b/contrib/python/pytest/py3/_pytest/compat.py index c23cc962ce..6ed8e80daf 100644 --- a/contrib/python/pytest/py3/_pytest/compat.py +++ b/contrib/python/pytest/py3/_pytest/compat.py @@ -1,10 +1,10 @@ """Python version compatibility code.""" import enum -import functools -import inspect -import re -import sys -from contextlib import contextmanager +import functools +import inspect +import re +import sys +from contextlib import contextmanager from inspect import Parameter from inspect import signature from pathlib import Path @@ -16,21 +16,21 @@ from typing import Tuple from typing import TYPE_CHECKING from typing import TypeVar from typing import Union - + import attr - -from _pytest.outcomes import fail -from _pytest.outcomes import TEST_OUTCOME - + +from _pytest.outcomes import fail +from _pytest.outcomes import TEST_OUTCOME + if TYPE_CHECKING: from typing import NoReturn from typing_extensions import Final - - + + _T = TypeVar("_T") _S = TypeVar("_S") - - + + # fmt: off # Singleton type for NOTSET, as described in: # https://www.python.org/dev/peps/pep-0484/#support-for-singleton-types-in-unions @@ -38,7 +38,7 @@ class NotSetType(enum.Enum): token = 0 NOTSET: "Final" = NotSetType.token # noqa: E305 # fmt: on - + if sys.version_info >= (3, 8): from importlib import metadata as importlib_metadata else: @@ -46,27 +46,27 @@ else: def _format_args(func: Callable[..., Any]) -> str: - return str(signature(func)) - - -# The type of re.compile objects is not exposed in Python. -REGEX_TYPE = type(re.compile("")) - - + return str(signature(func)) + + +# The type of re.compile objects is not exposed in Python. +REGEX_TYPE = type(re.compile("")) + + def is_generator(func: object) -> bool: - genfunc = inspect.isgeneratorfunction(func) - return genfunc and not iscoroutinefunction(func) - - + genfunc = inspect.isgeneratorfunction(func) + return genfunc and not iscoroutinefunction(func) + + def iscoroutinefunction(func: object) -> bool: """Return True if func is a coroutine function (a function defined with async def syntax, and doesn't contain yield), or a function decorated with @asyncio.coroutine. - + Note: copied and modified from Python 3.5's builtin couroutines.py to avoid importing asyncio directly, which in turns also initializes the "logging" module as a side-effect (see issue #8). - """ + """ return inspect.iscoroutinefunction(func) or getattr(func, "_is_coroutine", False) @@ -74,12 +74,12 @@ def is_async_function(func: object) -> bool: """Return True if the given function seems to be an async function or an async generator.""" return iscoroutinefunction(func) or inspect.isasyncgenfunction(func) - - + + def getlocation(function, curdir: Optional[str] = None) -> str: - function = get_real_func(function) + function = get_real_func(function) fn = Path(inspect.getfile(function)) - lineno = function.__code__.co_firstlineno + lineno = function.__code__.co_firstlineno if curdir is not None: try: relfn = fn.relative_to(curdir) @@ -87,18 +87,18 @@ def getlocation(function, curdir: Optional[str] = None) -> str: pass else: return "%s:%d" % (relfn, lineno + 1) - return "%s:%d" % (fn, lineno + 1) - - + return "%s:%d" % (fn, lineno + 1) + + def num_mock_patch_args(function) -> int: """Return number of arguments used up by mock arguments (if any).""" - patchings = getattr(function, "patchings", None) - if not patchings: - return 0 - + patchings = getattr(function, "patchings", None) + if not patchings: + return 0 + mock_sentinel = getattr(sys.modules.get("mock"), "DEFAULT", object()) ut_mock_sentinel = getattr(sys.modules.get("unittest.mock"), "DEFAULT", object()) - + return len( [ p @@ -117,66 +117,66 @@ def getfuncargnames( cls: Optional[type] = None, ) -> Tuple[str, ...]: """Return the names of a function's mandatory arguments. - + Should return the names of all function arguments that: * Aren't bound to an instance or type as in instance or class methods. * Don't have default values. * Aren't bound with functools.partial. * Aren't replaced with mocks. - - The is_method and cls arguments indicate that the function should - be treated as a bound method even though it's not unless, only in - the case of cls, the function is a static method. - + + The is_method and cls arguments indicate that the function should + be treated as a bound method even though it's not unless, only in + the case of cls, the function is a static method. + The name parameter should be the original name in which the function was collected. """ # TODO(RonnyPfannschmidt): This function should be refactored when we # revisit fixtures. The fixture mechanism should ask the node for # the fixture names, and not try to obtain directly from the # function object well after collection has occurred. - - # The parameters attribute of a Signature object contains an - # ordered mapping of parameter names to Parameter instances. This - # creates a tuple of the names of the parameters that don't have - # defaults. - try: - parameters = signature(function).parameters - except (ValueError, TypeError) as e: - fail( + + # The parameters attribute of a Signature object contains an + # ordered mapping of parameter names to Parameter instances. This + # creates a tuple of the names of the parameters that don't have + # defaults. + try: + parameters = signature(function).parameters + except (ValueError, TypeError) as e: + fail( f"Could not determine arguments of {function!r}: {e}", pytrace=False, - ) - - arg_names = tuple( - p.name - for p in parameters.values() - if ( - p.kind is Parameter.POSITIONAL_OR_KEYWORD - or p.kind is Parameter.KEYWORD_ONLY - ) - and p.default is Parameter.empty - ) + ) + + arg_names = tuple( + p.name + for p in parameters.values() + if ( + p.kind is Parameter.POSITIONAL_OR_KEYWORD + or p.kind is Parameter.KEYWORD_ONLY + ) + and p.default is Parameter.empty + ) if not name: name = function.__name__ - # If this function should be treated as a bound method even though - # it's passed as an unbound method or function, remove the first - # parameter name. - if is_method or ( + # If this function should be treated as a bound method even though + # it's passed as an unbound method or function, remove the first + # parameter name. + if is_method or ( cls and not isinstance(cls.__dict__.get(name, None), staticmethod) - ): - arg_names = arg_names[1:] - # Remove any names that will be replaced with mocks. - if hasattr(function, "__wrapped__"): - arg_names = arg_names[num_mock_patch_args(function) :] - return arg_names - - + ): + arg_names = arg_names[1:] + # Remove any names that will be replaced with mocks. + if hasattr(function, "__wrapped__"): + arg_names = arg_names[num_mock_patch_args(function) :] + return arg_names + + if sys.version_info < (3, 7): - + @contextmanager def nullcontext(): yield - + else: from contextlib import nullcontext as nullcontext # noqa: F401 @@ -186,14 +186,14 @@ def get_default_arg_names(function: Callable[..., Any]) -> Tuple[str, ...]: # Note: this code intentionally mirrors the code at the beginning of # getfuncargnames, to get the arguments which were excluded from its result # because they had default values. - return tuple( - p.name - for p in signature(function).parameters.values() - if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) - and p.default is not Parameter.empty - ) - - + return tuple( + p.name + for p in signature(function).parameters.values() + if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY) + and p.default is not Parameter.empty + ) + + _non_printable_ascii_translate_table = { i: f"\\x{i:02x}" for i in range(128) if i not in range(32, 127) } @@ -207,23 +207,23 @@ def _translate_non_printable(s: str) -> str: STRING_TYPES = bytes, str - - + + def _bytes_to_ascii(val: bytes) -> str: return val.decode("ascii", "backslashreplace") - - + + def ascii_escaped(val: Union[bytes, str]) -> str: r"""If val is pure ASCII, return it as an str, otherwise, escape bytes objects into a sequence of escaped bytes: - + b'\xc3\xb4\xc5\xd6' -> r'\xc3\xb4\xc5\xd6' - + and escapes unicode objects into a sequence of escaped unicode ids, e.g.: - + r'4\nV\U00043efa\x0eMXWB\x1e\u3028\u15fd\xcd\U0007d944' - + Note: The obvious "v.decode('unicode-escape')" will return valid UTF-8 unicode if it finds them in bytes, but we @@ -235,93 +235,93 @@ def ascii_escaped(val: Union[bytes, str]) -> str: else: ret = val return ret - - + + @attr.s class _PytestWrapper: - """Dummy wrapper around a function object for internal use only. - + """Dummy wrapper around a function object for internal use only. + Used to correctly unwrap the underlying function object when we are creating fixtures, because we wrap the function object ourselves with a decorator to issue warnings when the fixture function is called directly. - """ - + """ + obj = attr.ib() - - -def get_real_func(obj): + + +def get_real_func(obj): """Get the real function object of the (possibly) wrapped object by functools.wraps or functools.partial.""" - start_obj = obj - for i in range(100): - # __pytest_wrapped__ is set by @pytest.fixture when wrapping the fixture function - # to trigger a warning if it gets called directly instead of by pytest: we don't - # want to unwrap further than this otherwise we lose useful wrappings like @mock.patch (#3774) - new_obj = getattr(obj, "__pytest_wrapped__", None) - if isinstance(new_obj, _PytestWrapper): - obj = new_obj.obj - break - new_obj = getattr(obj, "__wrapped__", None) - if new_obj is None: - break - obj = new_obj - else: + start_obj = obj + for i in range(100): + # __pytest_wrapped__ is set by @pytest.fixture when wrapping the fixture function + # to trigger a warning if it gets called directly instead of by pytest: we don't + # want to unwrap further than this otherwise we lose useful wrappings like @mock.patch (#3774) + new_obj = getattr(obj, "__pytest_wrapped__", None) + if isinstance(new_obj, _PytestWrapper): + obj = new_obj.obj + break + new_obj = getattr(obj, "__wrapped__", None) + if new_obj is None: + break + obj = new_obj + else: from _pytest._io.saferepr import saferepr - raise ValueError( - ("could not find real function of {start}\nstopped at {current}").format( + raise ValueError( + ("could not find real function of {start}\nstopped at {current}").format( start=saferepr(start_obj), current=saferepr(obj) - ) - ) - if isinstance(obj, functools.partial): - obj = obj.func - return obj - - -def get_real_method(obj, holder): + ) + ) + if isinstance(obj, functools.partial): + obj = obj.func + return obj + + +def get_real_method(obj, holder): """Attempt to obtain the real function object that might be wrapping ``obj``, while at the same time returning a bound method to ``holder`` if the original object was a bound method.""" - try: - is_method = hasattr(obj, "__func__") - obj = get_real_func(obj) + try: + is_method = hasattr(obj, "__func__") + obj = get_real_func(obj) except Exception: # pragma: no cover - return obj - if is_method and hasattr(obj, "__get__") and callable(obj.__get__): - obj = obj.__get__(holder) - return obj - - -def getimfunc(func): - try: - return func.__func__ - except AttributeError: - return func - - + return obj + if is_method and hasattr(obj, "__get__") and callable(obj.__get__): + obj = obj.__get__(holder) + return obj + + +def getimfunc(func): + try: + return func.__func__ + except AttributeError: + return func + + def safe_getattr(object: Any, name: str, default: Any) -> Any: """Like getattr but return default upon any Exception or any OutcomeException. - - Attribute access can potentially fail for 'evil' Python objects. - See issue #214. + + Attribute access can potentially fail for 'evil' Python objects. + See issue #214. It catches OutcomeException because of #2490 (issue #580), new outcomes are derived from BaseException instead of Exception (for more details check #2707). - """ - try: - return getattr(object, name, default) - except TEST_OUTCOME: - return default - - + """ + try: + return getattr(object, name, default) + except TEST_OUTCOME: + return default + + def safe_isclass(obj: object) -> bool: - """Ignore any exception via isinstance on Python 3.""" - try: + """Ignore any exception via isinstance on Python 3.""" + try: return inspect.isclass(obj) - except Exception: - return False - - + except Exception: + return False + + if TYPE_CHECKING: if sys.version_info >= (3, 8): from typing import final as final @@ -330,24 +330,24 @@ if TYPE_CHECKING: elif sys.version_info >= (3, 8): from typing import final as final else: - + def final(f): return f - - + + if sys.version_info >= (3, 8): from functools import cached_property as cached_property else: from typing import overload from typing import Type - + class cached_property(Generic[_S, _T]): __slots__ = ("func", "__doc__") - + def __init__(self, func: Callable[[_S], _T]) -> None: self.func = func self.__doc__ = func.__doc__ - + @overload def __get__( self, instance: None, owner: Optional[Type[_S]] = ... |