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

Remove support for [pytest] in setup.cfg files and pytest_plugins in non-top-level conftests #4566

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog/3086.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
``[pytest]`` section in **setup.cfg** files is not longer supported, use ``[tool:pytest]`` instead. ``setup.cfg`` files
are meant for use with ``distutils``, and a section named ``pytest`` has notoriously been a source of conflicts and bugs.

Note that for **pytest.ini** and **tox.ini** files the section remains ``[pytest]``.
3 changes: 3 additions & 0 deletions changelog/4548.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
An error is now raised if the ``pytest_plugins`` variable is defined in a non-top-level ``conftest.py`` file (i.e., not residing in the ``rootdir``).

See our `docs <https://docs.pytest.org/en/latest/deprecations.html#pytest-plugins-in-non-top-level-conftest-files>`__ for more information.
39 changes: 20 additions & 19 deletions doc/en/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,6 @@ As part of a large :ref:`marker-revamp`, :meth:`_pytest.nodes.Node.get_marker` i
:ref:`the documentation <update marker code>` on tips on how to update your code.


pytest_plugins in non-top-level conftest files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 3.5

Defining ``pytest_plugins`` is now deprecated in non-top-level conftest.py
files because they will activate referenced plugins *globally*, which is surprising because for all other pytest
features ``conftest.py`` files are only *active* for tests at or below it.


marks in ``pytest.mark.parametrize``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -125,15 +115,6 @@ To update the code, use ``pytest.param``:




[pytest] section in setup.cfg files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 3.0

``[pytest]`` sections in ``setup.cfg`` files should now be named ``[tool:pytest]``
to avoid conflicts with other distutils commands.

Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -185,6 +166,16 @@ Switch over to the ``@pytest.fixture`` decorator:
return SomeData()



[pytest] section in setup.cfg files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*Removed in version 4.0.*

``[pytest]`` sections in ``setup.cfg`` files should now be named ``[tool:pytest]``
to avoid conflicts with other distutils commands.


Metafunc.addcall
~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -241,6 +232,16 @@ You can consult `funcarg comparison section in the docs <https://docs.pytest.org
more information.


pytest_plugins in non-top-level conftest files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*Removed in version 4.0.*

Defining ``pytest_plugins`` is now deprecated in non-top-level conftest.py
files because they will activate referenced plugins *globally*, which is surprising because for all other pytest
features ``conftest.py`` files are only *active* for tests at or below it.


``Config.warn`` and ``Node.warn``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
11 changes: 6 additions & 5 deletions src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from _pytest._code import filter_traceback
from _pytest.compat import lru_cache
from _pytest.compat import safe_str
from _pytest.outcomes import fail
from _pytest.outcomes import Skipped
from _pytest.warning_types import PytestWarning

Expand Down Expand Up @@ -429,11 +430,11 @@ def _importconftest(self, conftestpath):
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
)

warnings.warn_explicit(
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST,
category=None,
filename=str(conftestpath),
lineno=0,
fail(
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST.format(
conftestpath, self._confcutdir
),
pytrace=False,
)
except Exception:
raise ConftestImportFailure(conftestpath, sys.exc_info())
Expand Down
25 changes: 8 additions & 17 deletions src/_pytest/config/findpaths.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import py

from .exceptions import UsageError
from _pytest.outcomes import fail


def exists(path, ignore=EnvironmentError):
Expand Down Expand Up @@ -34,15 +35,10 @@ def getcfg(args, config=None):
iniconfig = py.iniconfig.IniConfig(p)
if "pytest" in iniconfig.sections:
if inibasename == "setup.cfg" and config is not None:
from _pytest.warnings import _issue_warning_captured
from _pytest.warning_types import RemovedInPytest4Warning

_issue_warning_captured(
RemovedInPytest4Warning(
CFG_PYTEST_SECTION.format(filename=inibasename)
),
hook=config.hook,
stacklevel=2,

fail(
CFG_PYTEST_SECTION.format(filename=inibasename),
pytrace=False,
)
return base, p, iniconfig["pytest"]
if (
Expand Down Expand Up @@ -112,14 +108,9 @@ def determine_setup(inifile, args, rootdir_cmd_arg=None, config=None):
inicfg = iniconfig[section]
if is_cfg_file and section == "pytest" and config is not None:
from _pytest.deprecated import CFG_PYTEST_SECTION
from _pytest.warnings import _issue_warning_captured

# TODO: [pytest] section in *.cfg files is deprecated. Need refactoring once
# the deprecation expires.
_issue_warning_captured(
CFG_PYTEST_SECTION.format(filename=str(inifile)),
config.hook,
stacklevel=2,

fail(
CFG_PYTEST_SECTION.format(filename=str(inifile)), pytrace=False
)
break
except KeyError:
Expand Down
16 changes: 8 additions & 8 deletions src/_pytest/deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

from _pytest.warning_types import PytestDeprecationWarning
from _pytest.warning_types import RemovedInPytest4Warning
from _pytest.warning_types import UnformattedWarning


YIELD_TESTS = "yield tests were removed in pytest 4.0 - {name} will be ignored"
Expand All @@ -31,10 +30,7 @@
"'request' is a reserved name for fixtures and will raise an error in future versions"
)

CFG_PYTEST_SECTION = UnformattedWarning(
RemovedInPytest4Warning,
"[pytest] section in {filename} files is deprecated, use [tool:pytest] instead.",
)
CFG_PYTEST_SECTION = "[pytest] section in {filename} files is no longer supported, change to [tool:pytest] instead."

GETFUNCARGVALUE = RemovedInPytest4Warning(
"getfuncargvalue is deprecated, use getfixturevalue"
Expand Down Expand Up @@ -73,10 +69,14 @@
"See https://docs.pytest.org/en/latest/deprecations.html#raises-warns-exec"
)

PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = RemovedInPytest4Warning(
"Defining pytest_plugins in a non-top-level conftest is deprecated, "
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = (
"Defining 'pytest_plugins' in a non-top-level conftest is no longer supported "
"because it affects the entire directory tree in a non-explicit way.\n"
"Please move it to the top level conftest file instead."
" {}\n"
"Please move it to a top level conftest file at the rootdir:\n"
" {}\n"
"For more information, visit:\n"
" https://docs.pytest.org/en/latest/deprecations.html#pytest-plugins-in-non-top-level-conftest-files"
)

PYTEST_CONFIG_GLOBAL = PytestDeprecationWarning(
Expand Down
40 changes: 14 additions & 26 deletions testing/deprecated_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,28 @@
pytestmark = pytest.mark.pytester_example_path("deprecated")


@pytest.mark.filterwarnings("default")
def test_pytest_setup_cfg_deprecated(testdir):
def test_pytest_setup_cfg_unsupported(testdir):
testdir.makefile(
".cfg",
setup="""
[pytest]
addopts = --verbose
""",
)
result = testdir.runpytest()
result.stdout.fnmatch_lines(
["*pytest*section in setup.cfg files is deprecated*use*tool:pytest*instead*"]
)
with pytest.raises(pytest.fail.Exception):
testdir.runpytest()


@pytest.mark.filterwarnings("default")
def test_pytest_custom_cfg_deprecated(testdir):
def test_pytest_custom_cfg_unsupported(testdir):
testdir.makefile(
".cfg",
custom="""
[pytest]
addopts = --verbose
""",
)
result = testdir.runpytest("-c", "custom.cfg")
result.stdout.fnmatch_lines(
["*pytest*section in custom.cfg files is deprecated*use*tool:pytest*instead*"]
)
with pytest.raises(pytest.fail.Exception):
testdir.runpytest("-c", "custom.cfg")


def test_getfuncargvalue_is_deprecated(request):
Expand Down Expand Up @@ -119,17 +113,15 @@ def test_func():
"""
)
res = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG)
assert res.ret == 0
assert res.ret == 2
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines(
"*subdirectory{sep}conftest.py:0: RemovedInPytest4Warning: {msg}*".format(
sep=os.sep, msg=msg
)
["*{msg}*".format(msg=msg), "*subdirectory{sep}conftest.py*".format(sep=os.sep)]
)


@pytest.mark.parametrize("use_pyargs", [True, False])
def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs(
def test_pytest_plugins_in_non_top_level_conftest_unsupported_pyargs(
testdir, use_pyargs
):
"""When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)"""
Expand All @@ -149,15 +141,15 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs(
args = ("--pyargs", "pkg") if use_pyargs else ()
args += (SHOW_PYTEST_WARNINGS_ARG,)
res = testdir.runpytest(*args)
assert res.ret == 0
assert res.ret == (0 if use_pyargs else 2)
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
if use_pyargs:
assert msg not in res.stdout.str()
else:
res.stdout.fnmatch_lines("*{msg}*".format(msg=msg))


def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_conftest(
def test_pytest_plugins_in_non_top_level_conftest_unsupported_no_top_level_conftest(
testdir
):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
Expand All @@ -166,8 +158,6 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_confte
subdirectory.mkdir()
testdir.makeconftest(
"""
import warnings
warnings.filterwarnings('always', category=DeprecationWarning)
pytest_plugins=['capture']
"""
)
Expand All @@ -181,16 +171,14 @@ def test_func():
)

res = testdir.runpytest_subprocess()
assert res.ret == 0
assert res.ret == 2
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines(
"*subdirectory{sep}conftest.py:0: RemovedInPytest4Warning: {msg}*".format(
sep=os.sep, msg=msg
)
["*{msg}*".format(msg=msg), "*subdirectory{sep}conftest.py*".format(sep=os.sep)]
)


def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_false_positives(
def test_pytest_plugins_in_non_top_level_conftest_unsupported_no_false_positives(
testdir
):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
Expand Down