Merge pull request #4566 from nicoddemus/remove-setup-cfg-non-top-level-pytest-plugins

Remove support for [pytest] in setup.cfg files and pytest_plugins in non-top-level conftests
This commit is contained in:
Ronny Pfannschmidt 2018-12-20 08:47:25 +01:00 committed by GitHub
commit b2d3ae257a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 61 additions and 73 deletions

View File

@ -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]``.

View File

@ -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.

View File

@ -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. :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`` marks in ``pytest.mark.parametrize``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -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``) Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -185,6 +166,16 @@ Switch over to the ``@pytest.fixture`` decorator:
return SomeData() 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 Metafunc.addcall
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
@ -241,6 +232,16 @@ You can consult `funcarg comparison section in the docs <https://docs.pytest.org
more information. 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`` ``Config.warn`` and ``Node.warn``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -31,6 +31,7 @@ from _pytest._code import ExceptionInfo
from _pytest._code import filter_traceback from _pytest._code import filter_traceback
from _pytest.compat import lru_cache from _pytest.compat import lru_cache
from _pytest.compat import safe_str from _pytest.compat import safe_str
from _pytest.outcomes import fail
from _pytest.outcomes import Skipped from _pytest.outcomes import Skipped
from _pytest.warning_types import PytestWarning from _pytest.warning_types import PytestWarning
@ -429,11 +430,11 @@ class PytestPluginManager(PluginManager):
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
) )
warnings.warn_explicit( fail(
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST, PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST.format(
category=None, conftestpath, self._confcutdir
filename=str(conftestpath), ),
lineno=0, pytrace=False,
) )
except Exception: except Exception:
raise ConftestImportFailure(conftestpath, sys.exc_info()) raise ConftestImportFailure(conftestpath, sys.exc_info())

View File

@ -3,6 +3,7 @@ import os
import py import py
from .exceptions import UsageError from .exceptions import UsageError
from _pytest.outcomes import fail
def exists(path, ignore=EnvironmentError): def exists(path, ignore=EnvironmentError):
@ -34,15 +35,10 @@ def getcfg(args, config=None):
iniconfig = py.iniconfig.IniConfig(p) iniconfig = py.iniconfig.IniConfig(p)
if "pytest" in iniconfig.sections: if "pytest" in iniconfig.sections:
if inibasename == "setup.cfg" and config is not None: 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( fail(
RemovedInPytest4Warning( CFG_PYTEST_SECTION.format(filename=inibasename),
CFG_PYTEST_SECTION.format(filename=inibasename) pytrace=False,
),
hook=config.hook,
stacklevel=2,
) )
return base, p, iniconfig["pytest"] return base, p, iniconfig["pytest"]
if ( if (
@ -112,14 +108,9 @@ def determine_setup(inifile, args, rootdir_cmd_arg=None, config=None):
inicfg = iniconfig[section] inicfg = iniconfig[section]
if is_cfg_file and section == "pytest" and config is not None: if is_cfg_file and section == "pytest" and config is not None:
from _pytest.deprecated import CFG_PYTEST_SECTION 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 fail(
# the deprecation expires. CFG_PYTEST_SECTION.format(filename=str(inifile)), pytrace=False
_issue_warning_captured(
CFG_PYTEST_SECTION.format(filename=str(inifile)),
config.hook,
stacklevel=2,
) )
break break
except KeyError: except KeyError:

View File

@ -14,7 +14,6 @@ from __future__ import print_function
from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestDeprecationWarning
from _pytest.warning_types import RemovedInPytest4Warning 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" YIELD_TESTS = "yield tests were removed in pytest 4.0 - {name} will be ignored"
@ -31,10 +30,7 @@ FIXTURE_NAMED_REQUEST = PytestDeprecationWarning(
"'request' is a reserved name for fixtures and will raise an error in future versions" "'request' is a reserved name for fixtures and will raise an error in future versions"
) )
CFG_PYTEST_SECTION = UnformattedWarning( CFG_PYTEST_SECTION = "[pytest] section in {filename} files is no longer supported, change to [tool:pytest] instead."
RemovedInPytest4Warning,
"[pytest] section in {filename} files is deprecated, use [tool:pytest] instead.",
)
GETFUNCARGVALUE = RemovedInPytest4Warning( GETFUNCARGVALUE = RemovedInPytest4Warning(
"getfuncargvalue is deprecated, use getfixturevalue" "getfuncargvalue is deprecated, use getfixturevalue"
@ -73,10 +69,14 @@ WARNS_EXEC = PytestDeprecationWarning(
"See https://docs.pytest.org/en/latest/deprecations.html#raises-warns-exec" "See https://docs.pytest.org/en/latest/deprecations.html#raises-warns-exec"
) )
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = RemovedInPytest4Warning( PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = (
"Defining pytest_plugins in a non-top-level conftest is deprecated, " "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" "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( PYTEST_CONFIG_GLOBAL = PytestDeprecationWarning(

View File

@ -10,8 +10,7 @@ from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
pytestmark = pytest.mark.pytester_example_path("deprecated") pytestmark = pytest.mark.pytester_example_path("deprecated")
@pytest.mark.filterwarnings("default") def test_pytest_setup_cfg_unsupported(testdir):
def test_pytest_setup_cfg_deprecated(testdir):
testdir.makefile( testdir.makefile(
".cfg", ".cfg",
setup=""" setup="""
@ -19,14 +18,11 @@ def test_pytest_setup_cfg_deprecated(testdir):
addopts = --verbose addopts = --verbose
""", """,
) )
result = testdir.runpytest() with pytest.raises(pytest.fail.Exception):
result.stdout.fnmatch_lines( testdir.runpytest()
["*pytest*section in setup.cfg files is deprecated*use*tool:pytest*instead*"]
)
@pytest.mark.filterwarnings("default") def test_pytest_custom_cfg_unsupported(testdir):
def test_pytest_custom_cfg_deprecated(testdir):
testdir.makefile( testdir.makefile(
".cfg", ".cfg",
custom=""" custom="""
@ -34,10 +30,8 @@ def test_pytest_custom_cfg_deprecated(testdir):
addopts = --verbose addopts = --verbose
""", """,
) )
result = testdir.runpytest("-c", "custom.cfg") with pytest.raises(pytest.fail.Exception):
result.stdout.fnmatch_lines( testdir.runpytest("-c", "custom.cfg")
["*pytest*section in custom.cfg files is deprecated*use*tool:pytest*instead*"]
)
def test_getfuncargvalue_is_deprecated(request): def test_getfuncargvalue_is_deprecated(request):
@ -119,17 +113,15 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir):
""" """
) )
res = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG) 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] msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines( res.stdout.fnmatch_lines(
"*subdirectory{sep}conftest.py:0: RemovedInPytest4Warning: {msg}*".format( ["*{msg}*".format(msg=msg), "*subdirectory{sep}conftest.py*".format(sep=os.sep)]
sep=os.sep, msg=msg
)
) )
@pytest.mark.parametrize("use_pyargs", [True, False]) @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 testdir, use_pyargs
): ):
"""When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)""" """When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)"""
@ -149,7 +141,7 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs(
args = ("--pyargs", "pkg") if use_pyargs else () args = ("--pyargs", "pkg") if use_pyargs else ()
args += (SHOW_PYTEST_WARNINGS_ARG,) args += (SHOW_PYTEST_WARNINGS_ARG,)
res = testdir.runpytest(*args) 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] msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
if use_pyargs: if use_pyargs:
assert msg not in res.stdout.str() assert msg not in res.stdout.str()
@ -157,7 +149,7 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_pyargs(
res.stdout.fnmatch_lines("*{msg}*".format(msg=msg)) 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 testdir
): ):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
@ -166,8 +158,6 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_confte
subdirectory.mkdir() subdirectory.mkdir()
testdir.makeconftest( testdir.makeconftest(
""" """
import warnings
warnings.filterwarnings('always', category=DeprecationWarning)
pytest_plugins=['capture'] pytest_plugins=['capture']
""" """
) )
@ -181,16 +171,14 @@ def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_confte
) )
res = testdir.runpytest_subprocess() res = testdir.runpytest_subprocess()
assert res.ret == 0 assert res.ret == 2
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0] msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines( res.stdout.fnmatch_lines(
"*subdirectory{sep}conftest.py:0: RemovedInPytest4Warning: {msg}*".format( ["*{msg}*".format(msg=msg), "*subdirectory{sep}conftest.py*".format(sep=os.sep)]
sep=os.sep, msg=msg
)
) )
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 testdir
): ):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST