diff --git a/changelog/3050.deprecation.rst b/changelog/3050.deprecation.rst new file mode 100644 index 000000000..2da417c85 --- /dev/null +++ b/changelog/3050.deprecation.rst @@ -0,0 +1 @@ +Deprecate ``pytest.config`` global. See https://docs.pytest.org/en/latest/deprecations.html#pytest-config-global diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 80b819e97..ca72bfbff 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -14,6 +14,15 @@ Below is a complete list of all pytest features which are considered deprecated. :class:`_pytest.warning_types.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. +``pytest.config`` global +~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 4.1 + +The ``pytest.config`` global object is deprecated. Instead use +``request.config`` (via the ``request`` fixture) or if you are a plugin author +use the ``pytest_configure(config)`` hook. + .. _raises-warns-exec: ``raises`` / ``warns`` with a string as the second argument diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 7c9ff9425..0d3dc85cc 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -97,6 +97,10 @@ PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST = RemovedInPytest4Warning( "Please move it to the top level conftest file instead." ) +PYTEST_CONFIG_GLOBAL = PytestDeprecationWarning( + "the `pytest.config` global is deprecated. Please use `request.config` " + "or `pytest_configure` (if you're a pytest plugin) instead." +) PYTEST_ENSURETEMP = RemovedInPytest4Warning( "pytest/tmpdir_factory.ensuretemp is deprecated, \n" diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 851b08ae3..08490f03a 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -8,6 +8,7 @@ import functools import os import pkgutil import sys +import warnings import attr import py @@ -18,6 +19,7 @@ from _pytest import nodes from _pytest.config import directory_arg from _pytest.config import hookimpl from _pytest.config import UsageError +from _pytest.deprecated import PYTEST_CONFIG_GLOBAL from _pytest.outcomes import exit from _pytest.runner import collect_one_node @@ -167,8 +169,24 @@ def pytest_addoption(parser): ) +class _ConfigDeprecated(object): + def __init__(self, config): + self.__dict__["_config"] = config + + def __getattr__(self, attr): + warnings.warn(PYTEST_CONFIG_GLOBAL, stacklevel=2) + return getattr(self._config, attr) + + def __setattr__(self, attr, val): + warnings.warn(PYTEST_CONFIG_GLOBAL, stacklevel=2) + return setattr(self._config, attr, val) + + def __repr__(self): + return "{}({!r})".format(type(self).__name__, self._config) + + def pytest_configure(config): - __import__("pytest").config = config # compatibility + __import__("pytest").config = _ConfigDeprecated(config) # compatibility def wrap_session(config, doit): diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 2a7a646ee..20f4f0078 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -539,7 +539,7 @@ class TestTerminalFunctional(object): result.stdout.fnmatch_lines(["test_passes.py ..*", "* 2 pass*"]) assert result.ret == 0 - def test_header_trailer_info(self, testdir): + def test_header_trailer_info(self, testdir, request): testdir.makepyfile( """ def test_passes(): @@ -563,7 +563,7 @@ class TestTerminalFunctional(object): "=* 1 passed*in *.[0-9][0-9] seconds *=", ] ) - if pytest.config.pluginmanager.list_plugin_distinfo(): + if request.config.pluginmanager.list_plugin_distinfo(): result.stdout.fnmatch_lines(["plugins: *"]) def test_showlocals(self, testdir):