Change pytest deprecation warnings into errors for 6.0 release (#7362)
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
This commit is contained in:
parent
a9799f0b35
commit
7ec6401ffa
|
@ -0,0 +1,23 @@
|
|||
**PytestDeprecationWarning are now errors by default.**
|
||||
|
||||
Following our plan to remove deprecated features with as little disruption as
|
||||
possible, all warnings of type ``PytestDeprecationWarning`` now generate errors
|
||||
instead of warning messages.
|
||||
|
||||
**The affected features will be effectively removed in pytest 6.1**, so please consult the
|
||||
`Deprecations and Removals <https://docs.pytest.org/en/latest/deprecations.html>`__
|
||||
section in the docs for directions on how to update existing code.
|
||||
|
||||
In the pytest ``6.0.X`` series, it is possible to change the errors back into warnings as a
|
||||
stopgap measure by adding this to your ``pytest.ini`` file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
filterwarnings =
|
||||
ignore::pytest.PytestDeprecationWarning
|
||||
|
||||
But this will stop working when pytest ``6.1`` is released.
|
||||
|
||||
**If you have concerns** about the removal of a specific feature, please add a
|
||||
comment to `#5584 <https://github.com/pytest-dev/pytest/issues/5584>`__.
|
|
@ -1024,10 +1024,45 @@ When set (regardless of value), pytest will use color in terminal output.
|
|||
Exceptions
|
||||
----------
|
||||
|
||||
UsageError
|
||||
~~~~~~~~~~
|
||||
|
||||
.. autoclass:: _pytest.config.UsageError()
|
||||
:show-inheritance:
|
||||
|
||||
.. _`warnings ref`:
|
||||
|
||||
Warnings
|
||||
--------
|
||||
|
||||
Custom warnings generated in some situations such as improper usage or deprecated features.
|
||||
|
||||
.. autoclass:: pytest.PytestWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestAssertRewriteWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestCacheWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestCollectionWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestConfigWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestDeprecationWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestExperimentalApiWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestUnhandledCoroutineWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestUnknownMarkWarning
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
Consult the :ref:`internal-warnings` section in the documentation for more information.
|
||||
|
||||
|
||||
.. _`ini options ref`:
|
||||
|
|
|
@ -381,8 +381,6 @@ custom error message.
|
|||
Internal pytest warnings
|
||||
------------------------
|
||||
|
||||
|
||||
|
||||
pytest may generate its own warnings in some situations, such as improper usage or deprecated features.
|
||||
|
||||
For example, pytest will emit a warning if it encounters a class that matches :confval:`python_classes` but also
|
||||
|
@ -415,31 +413,4 @@ These warnings might be filtered using the same builtin mechanisms used to filte
|
|||
Please read our :ref:`backwards-compatibility` to learn how we proceed about deprecating and eventually removing
|
||||
features.
|
||||
|
||||
The following warning types are used by pytest and are part of the public API:
|
||||
|
||||
.. autoclass:: pytest.PytestWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestAssertRewriteWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestCacheWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestCollectionWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestConfigWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestDeprecationWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestExperimentalApiWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestUnhandledCoroutineWarning
|
||||
:show-inheritance:
|
||||
|
||||
.. autoclass:: pytest.PytestUnknownMarkWarning
|
||||
:show-inheritance:
|
||||
The full list of warnings is listed in :ref:`the reference documentation <warnings ref>`.
|
||||
|
|
|
@ -46,7 +46,6 @@ from _pytest.compat import TYPE_CHECKING
|
|||
from _pytest.config import _PluggyPlugin
|
||||
from _pytest.config import Config
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.deprecated import FILLFUNCARGS
|
||||
from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS
|
||||
from _pytest.deprecated import FUNCARGNAMES
|
||||
from _pytest.mark import ParameterSet
|
||||
|
@ -361,7 +360,8 @@ def reorder_items_atscope(
|
|||
|
||||
def fillfixtures(function: "Function") -> None:
|
||||
""" fill missing funcargs for a test function. """
|
||||
warnings.warn(FILLFUNCARGS, stacklevel=2)
|
||||
# Uncomment this after 6.0 release (#7361)
|
||||
# warnings.warn(FILLFUNCARGS, stacklevel=2)
|
||||
try:
|
||||
request = function._request
|
||||
except AttributeError:
|
||||
|
|
|
@ -12,7 +12,6 @@ import py.path
|
|||
from pluggy import HookspecMarker
|
||||
|
||||
from .deprecated import COLLECT_DIRECTORY_HOOK
|
||||
from .deprecated import WARNING_CAPTURED_HOOK
|
||||
from _pytest.compat import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -737,7 +736,9 @@ def pytest_terminal_summary(
|
|||
"""
|
||||
|
||||
|
||||
@hookspec(historic=True, warn_on_impl=WARNING_CAPTURED_HOOK)
|
||||
# Uncomment this after 6.0 release (#7361)
|
||||
# @hookspec(historic=True, warn_on_impl=WARNING_CAPTURED_HOOK)
|
||||
@hookspec(historic=True)
|
||||
def pytest_warning_captured(
|
||||
warning_message: "warnings.WarningMessage",
|
||||
when: "Literal['config', 'collect', 'runtest']",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
""" generic mechanism for marking and selecting python functions. """
|
||||
import typing
|
||||
import warnings
|
||||
from typing import AbstractSet
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
|
@ -23,8 +22,6 @@ from _pytest.config import ExitCode
|
|||
from _pytest.config import hookimpl
|
||||
from _pytest.config import UsageError
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.deprecated import MINUS_K_COLON
|
||||
from _pytest.deprecated import MINUS_K_DASH
|
||||
from _pytest.store import StoreKey
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -181,12 +178,14 @@ def deselect_by_keyword(items: "List[Item]", config: Config) -> None:
|
|||
|
||||
if keywordexpr.startswith("-"):
|
||||
# To be removed in pytest 7.0.0.
|
||||
warnings.warn(MINUS_K_DASH, stacklevel=2)
|
||||
# Uncomment this after 6.0 release (#7361)
|
||||
# warnings.warn(MINUS_K_DASH, stacklevel=2)
|
||||
keywordexpr = "not " + keywordexpr[1:]
|
||||
selectuntil = False
|
||||
if keywordexpr[-1:] == ":":
|
||||
# To be removed in pytest 7.0.0.
|
||||
warnings.warn(MINUS_K_COLON, stacklevel=2)
|
||||
# Uncomment this after 6.0 release (#7361)
|
||||
# warnings.warn(MINUS_K_COLON, stacklevel=2)
|
||||
selectuntil = True
|
||||
keywordexpr = keywordexpr[:-1]
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ class PytestUnhandledCoroutineWarning(PytestWarning):
|
|||
class PytestUnknownMarkWarning(PytestWarning):
|
||||
"""Warning emitted on use of unknown markers.
|
||||
|
||||
See https://docs.pytest.org/en/stable/mark.html for details.
|
||||
See :ref:`mark` for details.
|
||||
"""
|
||||
|
||||
__module__ = "pytest"
|
||||
|
|
|
@ -105,6 +105,8 @@ def catch_warnings_for_item(
|
|||
warnings.filterwarnings("always", category=DeprecationWarning)
|
||||
warnings.filterwarnings("always", category=PendingDeprecationWarning)
|
||||
|
||||
warnings.filterwarnings("error", category=pytest.PytestDeprecationWarning)
|
||||
|
||||
# filters should have this precedence: mark, cmdline options, ini
|
||||
# filters should be applied in the inverse order of precedence
|
||||
for arg in inifilters:
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import sys
|
||||
import warnings
|
||||
from types import ModuleType
|
||||
from typing import Any
|
||||
from typing import List
|
||||
|
||||
import pytest
|
||||
from _pytest.deprecated import PYTEST_COLLECT_MODULE
|
||||
|
||||
|
||||
COLLECT_FAKEMODULE_ATTRIBUTES = [
|
||||
|
@ -33,7 +31,8 @@ class FakeCollectModule(ModuleType):
|
|||
def __getattr__(self, name: str) -> Any:
|
||||
if name not in self.__all__:
|
||||
raise AttributeError(name)
|
||||
warnings.warn(PYTEST_COLLECT_MODULE.format(name=name), stacklevel=2)
|
||||
# Uncomment this after 6.0 release (#7361)
|
||||
# warnings.warn(PYTEST_COLLECT_MODULE.format(name=name), stacklevel=2)
|
||||
return getattr(pytest, name)
|
||||
|
||||
|
||||
|
|
|
@ -302,10 +302,10 @@ class TestGeneralUsage:
|
|||
pass
|
||||
class MyCollector(pytest.File):
|
||||
def collect(self):
|
||||
return [MyItem(name="xyz", parent=self)]
|
||||
return [MyItem.from_parent(name="xyz", parent=self)]
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.basename.startswith("conftest"):
|
||||
return MyCollector(path, parent)
|
||||
return MyCollector.from_parent(fspath=path, parent=parent)
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(c.basename + "::" + "xyz")
|
||||
|
|
|
@ -116,11 +116,11 @@ def dummy_yaml_custom_test(testdir):
|
|||
|
||||
def pytest_collect_file(parent, path):
|
||||
if path.ext == ".yaml" and path.basename.startswith("test"):
|
||||
return YamlFile(path, parent)
|
||||
return YamlFile.from_parent(fspath=path, parent=parent)
|
||||
|
||||
class YamlFile(pytest.File):
|
||||
def collect(self):
|
||||
yield YamlItem(self.fspath.basename, self)
|
||||
yield YamlItem.from_parent(name=self.fspath.basename, parent=self)
|
||||
|
||||
class YamlItem(pytest.Item):
|
||||
def runtest(self):
|
||||
|
|
|
@ -28,6 +28,7 @@ def test_resultlog_is_deprecated(testdir):
|
|||
)
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="should be reintroduced in 6.1: #7361")
|
||||
@pytest.mark.parametrize("attribute", pytest.collect.__all__) # type: ignore
|
||||
# false positive due to dynamic attribute
|
||||
def test_pytest_collect_module_deprecated(attribute):
|
||||
|
@ -117,7 +118,8 @@ def test_node_direct_ctor_warning() -> None:
|
|||
assert w[0].filename == __file__
|
||||
|
||||
|
||||
def test__fillfuncargs_is_deprecated() -> None:
|
||||
@pytest.mark.skip(reason="should be reintroduced in 6.1: #7361")
|
||||
def test_fillfuncargs_is_deprecated() -> None:
|
||||
with pytest.warns(
|
||||
pytest.PytestDeprecationWarning,
|
||||
match="The `_fillfuncargs` function is deprecated",
|
||||
|
@ -125,6 +127,7 @@ def test__fillfuncargs_is_deprecated() -> None:
|
|||
pytest._fillfuncargs(mock.Mock())
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="should be reintroduced in 6.1: #7361")
|
||||
def test_minus_k_dash_is_deprecated(testdir) -> None:
|
||||
threepass = testdir.makepyfile(
|
||||
test_threepass="""
|
||||
|
@ -137,6 +140,7 @@ def test_minus_k_dash_is_deprecated(testdir) -> None:
|
|||
result.stdout.fnmatch_lines(["*The `-k '-expr'` syntax*deprecated*"])
|
||||
|
||||
|
||||
@pytest.mark.skip(reason="should be reintroduced in 6.1: #7361")
|
||||
def test_minus_k_colon_is_deprecated(testdir) -> None:
|
||||
threepass = testdir.makepyfile(
|
||||
test_threepass="""
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import pytest
|
||||
|
||||
|
||||
class CustomItem(pytest.Item, pytest.File):
|
||||
class CustomItem(pytest.Item):
|
||||
def runtest(self):
|
||||
pass
|
||||
|
||||
|
||||
class CustomFile(pytest.File):
|
||||
def collect(self):
|
||||
yield CustomItem.from_parent(name="foo", parent=self)
|
||||
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
return CustomItem(path, parent)
|
||||
return CustomFile.from_parent(fspath=path, parent=parent)
|
||||
|
|
|
@ -3,11 +3,11 @@ import pytest
|
|||
|
||||
class MyFile(pytest.File):
|
||||
def collect(self):
|
||||
return [MyItem("hello", parent=self)]
|
||||
return [MyItem.from_parent(name="hello", parent=self)]
|
||||
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
return MyFile(path, parent)
|
||||
return MyFile.from_parent(fspath=path, parent=parent)
|
||||
|
||||
|
||||
class MyItem(pytest.Item):
|
||||
|
|
|
@ -762,7 +762,7 @@ class TestConftestCustomization:
|
|||
pass
|
||||
def pytest_pycollect_makemodule(path, parent):
|
||||
if path.basename == "test_xyz.py":
|
||||
return MyModule(path, parent)
|
||||
return MyModule.from_parent(fspath=path, parent=parent)
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile("def test_some(): pass")
|
||||
|
@ -836,7 +836,7 @@ class TestConftestCustomization:
|
|||
pass
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
if name == "some":
|
||||
return MyFunction(name, collector)
|
||||
return MyFunction.from_parent(name=name, parent=collector)
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile("def some(): pass")
|
||||
|
@ -873,7 +873,7 @@ class TestConftestCustomization:
|
|||
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".narf":
|
||||
return Module(path, parent)"""
|
||||
return Module.from_parent(fspath=path, parent=parent)"""
|
||||
)
|
||||
testdir.makefile(
|
||||
".narf",
|
||||
|
|
|
@ -282,7 +282,7 @@ class TestPrunetraceback:
|
|||
"""
|
||||
import pytest
|
||||
def pytest_collect_file(path, parent):
|
||||
return MyFile(path, parent)
|
||||
return MyFile.from_parent(fspath=path, parent=parent)
|
||||
class MyError(Exception):
|
||||
pass
|
||||
class MyFile(pytest.File):
|
||||
|
@ -401,7 +401,7 @@ class TestCustomConftests:
|
|||
pass
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".py":
|
||||
return MyModule(path, parent)
|
||||
return MyModule.from_parent(fspath=path, parent=parent)
|
||||
"""
|
||||
)
|
||||
testdir.mkdir("sub")
|
||||
|
@ -419,7 +419,7 @@ class TestCustomConftests:
|
|||
pass
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".py":
|
||||
return MyModule1(path, parent)
|
||||
return MyModule1.from_parent(fspath=path, parent=parent)
|
||||
"""
|
||||
)
|
||||
conf1.move(sub1.join(conf1.basename))
|
||||
|
@ -430,7 +430,7 @@ class TestCustomConftests:
|
|||
pass
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".py":
|
||||
return MyModule2(path, parent)
|
||||
return MyModule2.from_parent(fspath=path, parent=parent)
|
||||
"""
|
||||
)
|
||||
conf2.move(sub2.join(conf2.basename))
|
||||
|
@ -537,10 +537,10 @@ class TestSession:
|
|||
return # ok
|
||||
class SpecialFile(pytest.File):
|
||||
def collect(self):
|
||||
return [SpecialItem(name="check", parent=self)]
|
||||
return [SpecialItem.from_parent(name="check", parent=self)]
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.basename == %r:
|
||||
return SpecialFile(fspath=path, parent=parent)
|
||||
return SpecialFile.from_parent(fspath=path, parent=parent)
|
||||
"""
|
||||
% p.basename
|
||||
)
|
||||
|
@ -761,18 +761,23 @@ def test_matchnodes_two_collections_same_file(testdir):
|
|||
class Plugin2(object):
|
||||
def pytest_collect_file(self, path, parent):
|
||||
if path.ext == ".abc":
|
||||
return MyFile2(path, parent)
|
||||
return MyFile2.from_parent(fspath=path, parent=parent)
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".abc":
|
||||
return MyFile1(path, parent)
|
||||
return MyFile1.from_parent(fspath=path, parent=parent)
|
||||
|
||||
class MyFile1(pytest.File):
|
||||
def collect(self):
|
||||
yield Item1.from_parent(name="item1", parent=self)
|
||||
|
||||
class MyFile1(pytest.Item, pytest.File):
|
||||
def runtest(self):
|
||||
pass
|
||||
class MyFile2(pytest.File):
|
||||
def collect(self):
|
||||
return [Item2("hello", parent=self)]
|
||||
yield Item2.from_parent(name="item2", parent=self)
|
||||
|
||||
class Item1(pytest.Item):
|
||||
def runtest(self):
|
||||
pass
|
||||
|
||||
class Item2(pytest.Item):
|
||||
def runtest(self):
|
||||
|
@ -783,7 +788,7 @@ def test_matchnodes_two_collections_same_file(testdir):
|
|||
result = testdir.runpytest()
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
res = testdir.runpytest("%s::hello" % p.basename)
|
||||
res = testdir.runpytest("%s::item2" % p.basename)
|
||||
res.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
|
|
|
@ -906,11 +906,8 @@ class TestNonPython:
|
|||
import pytest
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".xyz":
|
||||
return MyItem(path, parent)
|
||||
return MyItem.from_parent(name=path.basename, parent=parent)
|
||||
class MyItem(pytest.Item):
|
||||
def __init__(self, path, parent):
|
||||
super(MyItem, self).__init__(path.basename, parent)
|
||||
self.fspath = path
|
||||
def runtest(self):
|
||||
raise ValueError(42)
|
||||
def repr_failure(self, excinfo):
|
||||
|
@ -1336,14 +1333,14 @@ def test_fancy_items_regression(testdir, run_and_parse):
|
|||
class FunCollector(pytest.File):
|
||||
def collect(self):
|
||||
return [
|
||||
FunItem('a', self),
|
||||
NoFunItem('a', self),
|
||||
NoFunItem('b', self),
|
||||
FunItem.from_parent(name='a', parent=self),
|
||||
NoFunItem.from_parent(name='a', parent=self),
|
||||
NoFunItem.from_parent(name='b', parent=self),
|
||||
]
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.check(ext='.py'):
|
||||
return FunCollector(path, parent)
|
||||
return FunCollector.from_parent(fspath=path, parent=parent)
|
||||
"""
|
||||
)
|
||||
|
||||
|
|
|
@ -1126,7 +1126,7 @@ def test_xfail_item(testdir):
|
|||
pytest.xfail("Expected Failure")
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
return MyItem("foo", parent)
|
||||
return MyItem.from_parent(name="foo", parent=parent)
|
||||
"""
|
||||
)
|
||||
result = testdir.inline_run()
|
||||
|
@ -1206,7 +1206,7 @@ def test_mark_xfail_item(testdir):
|
|||
assert False
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
return MyItem("foo", parent)
|
||||
return MyItem.from_parent(name="foo", parent=parent)
|
||||
"""
|
||||
)
|
||||
result = testdir.inline_run()
|
||||
|
|
|
@ -520,9 +520,6 @@ class TestDeprecationWarningsByDefault:
|
|||
|
||||
|
||||
@pytest.mark.parametrize("change_default", [None, "ini", "cmdline"])
|
||||
@pytest.mark.skip(
|
||||
reason="This test should be enabled again before pytest 6.0 is released"
|
||||
)
|
||||
def test_deprecation_warning_as_error(testdir, change_default):
|
||||
"""This ensures that PytestDeprecationWarnings raised by pytest are turned into errors.
|
||||
|
||||
|
|
Loading…
Reference in New Issue