refactor: removed PytestWrapper class
This commit is contained in:
parent
ef46a374a0
commit
91fc20876a
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import dataclasses
|
|
||||||
import enum
|
import enum
|
||||||
import functools
|
import functools
|
||||||
import inspect
|
import inspect
|
||||||
|
@ -210,30 +209,15 @@ def ascii_escaped(val: bytes | str) -> str:
|
||||||
return ret.translate(_non_printable_ascii_translate_table)
|
return ret.translate(_non_printable_ascii_translate_table)
|
||||||
|
|
||||||
|
|
||||||
# TODO: remove and replace with FixtureFunctionDefinition
|
|
||||||
@dataclasses.dataclass
|
|
||||||
class _PytestWrapper:
|
|
||||||
"""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: Any
|
|
||||||
|
|
||||||
|
|
||||||
def get_real_func(obj):
|
def get_real_func(obj):
|
||||||
"""Get the real function object of the (possibly) wrapped object by
|
"""Get the real function object of the (possibly) wrapped object by
|
||||||
functools.wraps or functools.partial."""
|
functools.wraps or functools.partial or pytest.fixture"""
|
||||||
|
from _pytest.fixtures import FixtureFunctionDefinition
|
||||||
|
|
||||||
start_obj = obj
|
start_obj = obj
|
||||||
for i in range(100):
|
for _ in range(100):
|
||||||
# __pytest_wrapped__ is set by @pytest.fixture when wrapping the fixture function
|
if isinstance(obj, FixtureFunctionDefinition):
|
||||||
# to trigger a warning if it gets called directly instead of by pytest: we don't
|
obj = obj.get_real_func()
|
||||||
# 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
|
break
|
||||||
new_obj = getattr(obj, "__wrapped__", None)
|
new_obj = getattr(obj, "__wrapped__", None)
|
||||||
if new_obj is None:
|
if new_obj is None:
|
||||||
|
|
|
@ -42,7 +42,6 @@ from _pytest._code import Source
|
||||||
from _pytest._code.code import FormattedExcinfo
|
from _pytest._code.code import FormattedExcinfo
|
||||||
from _pytest._code.code import TerminalRepr
|
from _pytest._code.code import TerminalRepr
|
||||||
from _pytest._io import TerminalWriter
|
from _pytest._io import TerminalWriter
|
||||||
from _pytest.compat import _PytestWrapper
|
|
||||||
from _pytest.compat import assert_never
|
from _pytest.compat import assert_never
|
||||||
from _pytest.compat import get_real_func
|
from _pytest.compat import get_real_func
|
||||||
from _pytest.compat import getfuncargnames
|
from _pytest.compat import getfuncargnames
|
||||||
|
@ -1204,7 +1203,6 @@ class FixtureFunctionDefinition:
|
||||||
# Using isinstance on every object in code might execute code that is not intended to be executed.
|
# Using isinstance on every object in code might execute code that is not intended to be executed.
|
||||||
# Like lazy loaded classes.
|
# Like lazy loaded classes.
|
||||||
self._pytestfixturefunction = fixture_function_marker
|
self._pytestfixturefunction = fixture_function_marker
|
||||||
self.__pytest_wrapped__ = _PytestWrapper(function)
|
|
||||||
self.fixture_function_marker = fixture_function_marker
|
self.fixture_function_marker = fixture_function_marker
|
||||||
self.fixture_function = function
|
self.fixture_function = function
|
||||||
self.instance = instance
|
self.instance = instance
|
||||||
|
|
|
@ -7,7 +7,6 @@ import sys
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from _pytest.compat import _PytestWrapper
|
|
||||||
from _pytest.compat import assert_never
|
from _pytest.compat import assert_never
|
||||||
from _pytest.compat import get_real_func
|
from _pytest.compat import get_real_func
|
||||||
from _pytest.compat import is_generator
|
from _pytest.compat import is_generator
|
||||||
|
@ -52,8 +51,8 @@ def test_real_func_loop_limit() -> None:
|
||||||
with pytest.raises(
|
with pytest.raises(
|
||||||
ValueError,
|
ValueError,
|
||||||
match=(
|
match=(
|
||||||
"could not find real function of <Evil left=800>\n"
|
"could not find real function of <Evil left=900>\n"
|
||||||
"stopped at <Evil left=800>"
|
"stopped at <Evil left=900>"
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
get_real_func(evil)
|
get_real_func(evil)
|
||||||
|
@ -78,10 +77,13 @@ def test_get_real_func() -> None:
|
||||||
wrapped_func2 = decorator(decorator(wrapped_func))
|
wrapped_func2 = decorator(decorator(wrapped_func))
|
||||||
assert get_real_func(wrapped_func2) is func
|
assert get_real_func(wrapped_func2) is func
|
||||||
|
|
||||||
# special case for __pytest_wrapped__ attribute: used to obtain the function up until the point
|
# obtain the function up until the point a function was wrapped by pytest itself
|
||||||
# a function was wrapped by pytest itself
|
@pytest.fixture
|
||||||
wrapped_func2.__pytest_wrapped__ = _PytestWrapper(wrapped_func)
|
def wrapped_func3():
|
||||||
assert get_real_func(wrapped_func2) is wrapped_func
|
pass
|
||||||
|
|
||||||
|
wrapped_func4 = decorator(wrapped_func3)
|
||||||
|
assert get_real_func(wrapped_func4) is wrapped_func3.get_real_func()
|
||||||
|
|
||||||
|
|
||||||
def test_get_real_func_partial() -> None:
|
def test_get_real_func_partial() -> None:
|
||||||
|
|
Loading…
Reference in New Issue