Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change pytest deprecation warnings into errors for 6.0 release #7362

Merged
merged 6 commits into from Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 23 additions & 0 deletions changelog/5584.breaking.rst
@@ -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>`__.
41 changes: 38 additions & 3 deletions doc/en/reference.rst
Expand Up @@ -1021,10 +1021,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`:
Expand Down
31 changes: 1 addition & 30 deletions doc/en/warnings.rst
Expand Up @@ -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
Expand Down Expand Up @@ -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>`.
4 changes: 2 additions & 2 deletions src/_pytest/fixtures.py
Expand Up @@ -46,7 +46,6 @@
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
Expand Down Expand Up @@ -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:
Expand Down
5 changes: 3 additions & 2 deletions src/_pytest/hookspec.py
Expand Up @@ -12,7 +12,6 @@
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:
Expand Down Expand Up @@ -738,7 +737,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']",
Expand Down
9 changes: 4 additions & 5 deletions src/_pytest/mark/__init__.py
@@ -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
Expand All @@ -23,8 +22,6 @@
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:
Expand Down Expand Up @@ -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]

Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/warning_types.py
Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions src/_pytest/warnings.py
Expand Up @@ -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:
Expand Down
5 changes: 2 additions & 3 deletions src/pytest/collect.py
@@ -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 = [
Expand Down Expand Up @@ -33,7 +31,8 @@ def __dir__(self) -> List[str]:
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)


Expand Down
4 changes: 2 additions & 2 deletions testing/acceptance_test.py
Expand Up @@ -302,10 +302,10 @@ def runtest(self):
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")
Expand Down
4 changes: 2 additions & 2 deletions testing/conftest.py
Expand Up @@ -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):
Expand Down
6 changes: 5 additions & 1 deletion testing/deprecated_test.py
Expand Up @@ -28,6 +28,7 @@ def test():
)


@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):
Expand Down Expand Up @@ -117,14 +118,16 @@ class MockConfig:
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",
):
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="""
Expand All @@ -137,6 +140,7 @@ def test_three(): assert 1
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="""
Expand Down
9 changes: 7 additions & 2 deletions testing/example_scripts/fixtures/custom_item/conftest.py
@@ -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)
Expand Up @@ -3,11 +3,11 @@

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):
Expand Down
6 changes: 3 additions & 3 deletions testing/python/collect.py
Expand Up @@ -758,7 +758,7 @@ class MyModule(pytest.Module):
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")
Expand Down Expand Up @@ -832,7 +832,7 @@ class MyFunction(pytest.Function):
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")
Expand Down Expand Up @@ -869,7 +869,7 @@ def find_module(self, name, path=None):

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",
Expand Down