ENH: Figure out where to go
This commit is contained in:
parent
3efcff8bd1
commit
9733d57bed
|
@ -11,7 +11,10 @@ in case of warnings which need to format their messages.
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
from pathlib import Path
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
from warnings import warn_explicit
|
||||||
|
|
||||||
from _pytest.warning_types import PytestDeprecationWarning
|
from _pytest.warning_types import PytestDeprecationWarning
|
||||||
from _pytest.warning_types import PytestRemovedIn9Warning
|
from _pytest.warning_types import PytestRemovedIn9Warning
|
||||||
|
@ -89,3 +92,25 @@ MARKED_FIXTURE = PytestRemovedIn9Warning(
|
||||||
def check_ispytest(ispytest: bool) -> None:
|
def check_ispytest(ispytest: bool) -> None:
|
||||||
if not ispytest:
|
if not ispytest:
|
||||||
warn(PRIVATE, stacklevel=3)
|
warn(PRIVATE, stacklevel=3)
|
||||||
|
|
||||||
|
|
||||||
|
def _warn_auto_stacklevel(message, category=UserWarning):
|
||||||
|
"""Emit a warning with trace outside the pytest namespace."""
|
||||||
|
root_dir = Path(__file__).parents[1]
|
||||||
|
frame = inspect.currentframe()
|
||||||
|
fname, lineno = "unknown", 0
|
||||||
|
while frame:
|
||||||
|
fname = frame.f_code.co_filename
|
||||||
|
lineno = frame.f_lineno
|
||||||
|
if fname and root_dir not in Path(fname).parents:
|
||||||
|
break
|
||||||
|
frame = frame.f_back
|
||||||
|
del frame
|
||||||
|
warn_explicit(
|
||||||
|
message,
|
||||||
|
category,
|
||||||
|
filename=fname,
|
||||||
|
lineno=lineno,
|
||||||
|
module="pytest",
|
||||||
|
registry=globals().get("__warningregistry__", {}),
|
||||||
|
)
|
||||||
|
|
|
@ -60,6 +60,7 @@ from _pytest.config.argparsing import Parser
|
||||||
from _pytest.deprecated import check_ispytest
|
from _pytest.deprecated import check_ispytest
|
||||||
from _pytest.deprecated import MARKED_FIXTURE
|
from _pytest.deprecated import MARKED_FIXTURE
|
||||||
from _pytest.deprecated import YIELD_FIXTURE
|
from _pytest.deprecated import YIELD_FIXTURE
|
||||||
|
from _pytest.deprecated import _warn_auto_stacklevel
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
from _pytest.mark import Mark
|
from _pytest.mark import Mark
|
||||||
from _pytest.mark import ParameterSet
|
from _pytest.mark import ParameterSet
|
||||||
|
@ -1192,7 +1193,7 @@ class FixtureFunctionMarker:
|
||||||
)
|
)
|
||||||
|
|
||||||
if hasattr(function, "pytestmark"):
|
if hasattr(function, "pytestmark"):
|
||||||
warnings.warn(MARKED_FIXTURE, stacklevel=4)
|
_warn_auto_stacklevel(MARKED_FIXTURE)
|
||||||
|
|
||||||
function = wrap_function_to_error_out_if_called_directly(function, self)
|
function = wrap_function_to_error_out_if_called_directly(function, self)
|
||||||
|
|
||||||
|
@ -1322,7 +1323,7 @@ def yield_fixture(
|
||||||
.. deprecated:: 3.0
|
.. deprecated:: 3.0
|
||||||
Use :py:func:`pytest.fixture` directly instead.
|
Use :py:func:`pytest.fixture` directly instead.
|
||||||
"""
|
"""
|
||||||
warnings.warn(YIELD_FIXTURE, stacklevel=2)
|
_warn_auto_stacklevel(YIELD_FIXTURE)
|
||||||
return fixture(
|
return fixture(
|
||||||
fixture_function,
|
fixture_function,
|
||||||
*args,
|
*args,
|
||||||
|
|
|
@ -18,7 +18,6 @@ from typing import Sequence
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
from typing import TypeVar
|
from typing import TypeVar
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import warnings
|
|
||||||
|
|
||||||
from .._code import getfslineno
|
from .._code import getfslineno
|
||||||
from ..compat import ascii_escaped
|
from ..compat import ascii_escaped
|
||||||
|
@ -27,6 +26,7 @@ from ..compat import NotSetType
|
||||||
from _pytest.config import Config
|
from _pytest.config import Config
|
||||||
from _pytest.deprecated import check_ispytest
|
from _pytest.deprecated import check_ispytest
|
||||||
from _pytest.deprecated import MARKED_FIXTURE
|
from _pytest.deprecated import MARKED_FIXTURE
|
||||||
|
from _pytest.deprecated import _warn_auto_stacklevel
|
||||||
from _pytest.outcomes import fail
|
from _pytest.outcomes import fail
|
||||||
from _pytest.scope import _ScopeName
|
from _pytest.scope import _ScopeName
|
||||||
from _pytest.warning_types import PytestUnknownMarkWarning
|
from _pytest.warning_types import PytestUnknownMarkWarning
|
||||||
|
@ -353,7 +353,7 @@ class MarkDecorator:
|
||||||
func = args[0]
|
func = args[0]
|
||||||
is_class = inspect.isclass(func)
|
is_class = inspect.isclass(func)
|
||||||
if len(args) == 1 and (istestfunc(func) or is_class):
|
if len(args) == 1 and (istestfunc(func) or is_class):
|
||||||
store_mark(func, self.mark, stacklevel=3)
|
store_mark(func, self.mark)
|
||||||
return func
|
return func
|
||||||
return self.with_args(*args, **kwargs)
|
return self.with_args(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ def normalize_mark_list(
|
||||||
yield mark_obj
|
yield mark_obj
|
||||||
|
|
||||||
|
|
||||||
def store_mark(obj, mark: Mark, *, stacklevel: int = 2) -> None:
|
def store_mark(obj, mark: Mark) -> None:
|
||||||
"""Store a Mark on an object.
|
"""Store a Mark on an object.
|
||||||
|
|
||||||
This is used to implement the Mark declarations/decorators correctly.
|
This is used to implement the Mark declarations/decorators correctly.
|
||||||
|
@ -418,7 +418,7 @@ def store_mark(obj, mark: Mark, *, stacklevel: int = 2) -> None:
|
||||||
from ..fixtures import getfixturemarker
|
from ..fixtures import getfixturemarker
|
||||||
|
|
||||||
if getfixturemarker(obj) is not None:
|
if getfixturemarker(obj) is not None:
|
||||||
warnings.warn(MARKED_FIXTURE, stacklevel=stacklevel)
|
_warn_auto_stacklevel(MARKED_FIXTURE)
|
||||||
|
|
||||||
# Always reassign name to avoid updating pytestmark in a reference that
|
# Always reassign name to avoid updating pytestmark in a reference that
|
||||||
# was only borrowed.
|
# was only borrowed.
|
||||||
|
@ -543,12 +543,11 @@ class MarkGenerator:
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
fail(f"Unknown '{name}' mark, did you mean 'parametrize'?")
|
fail(f"Unknown '{name}' mark, did you mean 'parametrize'?")
|
||||||
|
|
||||||
warnings.warn(
|
_warn_auto_stacklevel(
|
||||||
f"Unknown pytest.mark.{name} - is this a typo? You can register "
|
f"Unknown pytest.mark.{name} - is this a typo? You can register "
|
||||||
"custom marks to avoid this warning - for details, see "
|
"custom marks to avoid this warning - for details, see "
|
||||||
"https://docs.pytest.org/en/stable/how-to/mark.html",
|
"https://docs.pytest.org/en/stable/how-to/mark.html",
|
||||||
PytestUnknownMarkWarning,
|
PytestUnknownMarkWarning,
|
||||||
2,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return MarkDecorator(Mark(name, (), {}, _ispytest=True), _ispytest=True)
|
return MarkDecorator(Mark(name, (), {}, _ispytest=True), _ispytest=True)
|
||||||
|
|
|
@ -59,7 +59,7 @@ def test_hookimpl_via_function_attributes_are_deprecated():
|
||||||
|
|
||||||
with pytest.warns(
|
with pytest.warns(
|
||||||
PytestDeprecationWarning,
|
PytestDeprecationWarning,
|
||||||
match=r"Please use the pytest.hookimpl\(tryfirst=True\)",
|
match=r"Please use the pytest\.hookimpl\(tryfirst=True\)",
|
||||||
) as recorder:
|
) as recorder:
|
||||||
pm.register(DeprecatedMarkImplPlugin())
|
pm.register(DeprecatedMarkImplPlugin())
|
||||||
(record,) = recorder
|
(record,) = recorder
|
||||||
|
@ -188,6 +188,18 @@ def test_fixture_disallow_on_marked_functions():
|
||||||
# should point to this file
|
# should point to this file
|
||||||
assert record[0].filename == __file__
|
assert record[0].filename == __file__
|
||||||
|
|
||||||
|
# Same with a different order
|
||||||
|
with pytest.warns(
|
||||||
|
pytest.PytestRemovedIn9Warning,
|
||||||
|
match=r"Marks applied to fixtures have no effect",
|
||||||
|
) as record:
|
||||||
|
@pytest.mark.parametrize("example", ["hello"])
|
||||||
|
@pytest.fixture
|
||||||
|
def foo():
|
||||||
|
raise NotImplementedError()
|
||||||
|
assert len(record) == 1
|
||||||
|
assert record[0].filename == __file__
|
||||||
|
|
||||||
|
|
||||||
def test_fixture_disallow_marks_on_fixtures():
|
def test_fixture_disallow_marks_on_fixtures():
|
||||||
"""Test that applying a mark to a fixture warns (#3364)."""
|
"""Test that applying a mark to a fixture warns (#3364)."""
|
||||||
|
|
Loading…
Reference in New Issue