refactor: removed PytestWrapper class

This commit is contained in:
Glyphack 2024-06-20 15:16:47 +02:00
parent ef46a374a0
commit 91fc20876a
3 changed files with 15 additions and 31 deletions

View File

@ -3,7 +3,6 @@
from __future__ import annotations
import dataclasses
import enum
import functools
import inspect
@ -210,30 +209,15 @@ def ascii_escaped(val: bytes | str) -> str:
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):
"""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
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
for _ in range(100):
if isinstance(obj, FixtureFunctionDefinition):
obj = obj.get_real_func()
break
new_obj = getattr(obj, "__wrapped__", None)
if new_obj is None:

View File

@ -42,7 +42,6 @@ from _pytest._code import Source
from _pytest._code.code import FormattedExcinfo
from _pytest._code.code import TerminalRepr
from _pytest._io import TerminalWriter
from _pytest.compat import _PytestWrapper
from _pytest.compat import assert_never
from _pytest.compat import get_real_func
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.
# Like lazy loaded classes.
self._pytestfixturefunction = fixture_function_marker
self.__pytest_wrapped__ = _PytestWrapper(function)
self.fixture_function_marker = fixture_function_marker
self.fixture_function = function
self.instance = instance

View File

@ -7,7 +7,6 @@ import sys
from typing import TYPE_CHECKING
from typing import Union
from _pytest.compat import _PytestWrapper
from _pytest.compat import assert_never
from _pytest.compat import get_real_func
from _pytest.compat import is_generator
@ -52,8 +51,8 @@ def test_real_func_loop_limit() -> None:
with pytest.raises(
ValueError,
match=(
"could not find real function of <Evil left=800>\n"
"stopped at <Evil left=800>"
"could not find real function of <Evil left=900>\n"
"stopped at <Evil left=900>"
),
):
get_real_func(evil)
@ -78,10 +77,13 @@ def test_get_real_func() -> None:
wrapped_func2 = decorator(decorator(wrapped_func))
assert get_real_func(wrapped_func2) is func
# special case for __pytest_wrapped__ attribute: used to obtain the function up until the point
# a function was wrapped by pytest itself
wrapped_func2.__pytest_wrapped__ = _PytestWrapper(wrapped_func)
assert get_real_func(wrapped_func2) is wrapped_func
# obtain the function up until the point a function was wrapped by pytest itself
@pytest.fixture
def wrapped_func3():
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: