Merge pull request #3978 from nicoddemus/warn-yield-and-compat-properties
Actually deprecate long standing features
This commit is contained in:
commit
bceaede198
|
@ -0,0 +1,22 @@
|
|||
The following accesses have been documented as deprecated for years, but are now actually emitting deprecation warnings.
|
||||
|
||||
* Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances. Now
|
||||
users will this warning::
|
||||
|
||||
usage of Function.Module is deprecated, please use pytest.Module instead
|
||||
|
||||
Users should just ``import pytest`` and access those objects using the ``pytest`` module.
|
||||
|
||||
* ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can
|
||||
consult `funcarg comparision section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_.
|
||||
|
||||
* Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
||||
subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during
|
||||
collection.
|
||||
|
||||
This issue should affect only advanced plugins who create new collection types, so if you see this warning
|
||||
message please contact the authors so they can change the code.
|
||||
|
||||
* The warning that produces the message below has changed to ``RemovedInPytest4Warning``::
|
||||
|
||||
getfuncargvalue is deprecated, use getfixturevalue
|
|
@ -14,7 +14,8 @@ Each file should be named like ``<ISSUE>.<TYPE>.rst``, where
|
|||
* ``feature``: new user facing features, like new command-line options and new behavior.
|
||||
* ``bugfix``: fixes a reported bug.
|
||||
* ``doc``: documentation improvement, like rewording an entire session or adding missing docs.
|
||||
* ``removal``: feature deprecation or removal.
|
||||
* ``deprecation``: feature deprecation.
|
||||
* ``removal``: feature removal.
|
||||
* ``vendor``: changes in packages vendored in pytest.
|
||||
* ``trivial``: fixing a small typo or internal change that might be noteworthy.
|
||||
|
||||
|
|
|
@ -175,3 +175,13 @@ Previous to version 2.4 to set a break point in code one needed to use ``pytest.
|
|||
This is no longer needed and one can use the native ``import pdb;pdb.set_trace()`` call directly.
|
||||
|
||||
For more details see :ref:`breakpoints`.
|
||||
|
||||
"compat" properties
|
||||
-------------------
|
||||
|
||||
.. deprecated:: 3.9
|
||||
|
||||
Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances have long
|
||||
been documented as deprecated, but started to emit warnings from pytest ``3.9`` and onward.
|
||||
|
||||
Users should just ``import pytest`` and access those objects using the ``pytest`` module.
|
||||
|
|
|
@ -15,7 +15,12 @@ template = "changelog/_template.rst"
|
|||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "removal"
|
||||
name = "Deprecations and Removals"
|
||||
name = "Removals"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
directory = "deprecation"
|
||||
name = "Deprecations"
|
||||
showcontent = true
|
||||
|
||||
[[tool.towncrier.type]]
|
||||
|
|
|
@ -103,21 +103,18 @@ def determine_setup(inifile, args, rootdir_cmd_arg=None, config=None):
|
|||
if inifile:
|
||||
iniconfig = py.iniconfig.IniConfig(inifile)
|
||||
is_cfg_file = str(inifile).endswith(".cfg")
|
||||
# TODO: [pytest] section in *.cfg files is depricated. Need refactoring.
|
||||
sections = ["tool:pytest", "pytest"] if is_cfg_file else ["pytest"]
|
||||
for section in sections:
|
||||
try:
|
||||
inicfg = iniconfig[section]
|
||||
if is_cfg_file and section == "pytest" and config is not None:
|
||||
from _pytest.deprecated import CFG_PYTEST_SECTION
|
||||
from _pytest.warning_types import RemovedInPytest4Warning
|
||||
from _pytest.warnings import _issue_config_warning
|
||||
|
||||
# TODO: [pytest] section in *.cfg files is deprecated. Need refactoring once
|
||||
# the deprecation expires.
|
||||
_issue_config_warning(
|
||||
RemovedInPytest4Warning(
|
||||
CFG_PYTEST_SECTION.format(filename=str(inifile))
|
||||
),
|
||||
config,
|
||||
CFG_PYTEST_SECTION.format(filename=str(inifile)), config
|
||||
)
|
||||
break
|
||||
except KeyError:
|
||||
|
|
|
@ -4,10 +4,15 @@ that is planned to be removed in the next pytest release.
|
|||
|
||||
Keeping it in a central location makes it easy to track what is deprecated and should
|
||||
be removed when the time comes.
|
||||
|
||||
All constants defined in this module should be either PytestWarning instances or UnformattedWarning
|
||||
in case of warnings which need to format their messages.
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
from _pytest.warning_types import RemovedInPytest4Warning
|
||||
|
||||
from _pytest.warning_types import UnformattedWarning, RemovedInPytest4Warning
|
||||
|
||||
|
||||
MAIN_STR_ARGS = RemovedInPytest4Warning(
|
||||
"passing a string to pytest.main() is deprecated, "
|
||||
|
@ -18,25 +23,48 @@ YIELD_TESTS = RemovedInPytest4Warning(
|
|||
"yield tests are deprecated, and scheduled to be removed in pytest 4.0"
|
||||
)
|
||||
|
||||
FUNCARG_PREFIX = (
|
||||
CACHED_SETUP = RemovedInPytest4Warning(
|
||||
"cached_setup is deprecated and will be removed in a future release. "
|
||||
"Use standard fixture functions instead."
|
||||
)
|
||||
|
||||
COMPAT_PROPERTY = UnformattedWarning(
|
||||
RemovedInPytest4Warning,
|
||||
"usage of {owner}.{name} is deprecated, please use pytest.{name} instead",
|
||||
)
|
||||
|
||||
CUSTOM_CLASS = UnformattedWarning(
|
||||
RemovedInPytest4Warning,
|
||||
'use of special named "{name}" objects in collectors of type "{type_name}" to '
|
||||
"customize the created nodes is deprecated. "
|
||||
"Use pytest_pycollect_makeitem(...) to create custom "
|
||||
"collection nodes instead.",
|
||||
)
|
||||
|
||||
FUNCARG_PREFIX = UnformattedWarning(
|
||||
RemovedInPytest4Warning,
|
||||
'{name}: declaring fixtures using "pytest_funcarg__" prefix is deprecated '
|
||||
"and scheduled to be removed in pytest 4.0. "
|
||||
"Please remove the prefix and use the @pytest.fixture decorator instead."
|
||||
"Please remove the prefix and use the @pytest.fixture decorator instead.",
|
||||
)
|
||||
|
||||
FIXTURE_FUNCTION_CALL = (
|
||||
FIXTURE_FUNCTION_CALL = UnformattedWarning(
|
||||
RemovedInPytest4Warning,
|
||||
'Fixture "{name}" called directly. Fixtures are not meant to be called directly, '
|
||||
"are created automatically when test functions request them as parameters. "
|
||||
"See https://docs.pytest.org/en/latest/fixture.html for more information."
|
||||
"See https://docs.pytest.org/en/latest/fixture.html for more information.",
|
||||
)
|
||||
|
||||
CFG_PYTEST_SECTION = (
|
||||
"[pytest] section in {filename} files is deprecated, use [tool:pytest] instead."
|
||||
CFG_PYTEST_SECTION = UnformattedWarning(
|
||||
RemovedInPytest4Warning,
|
||||
"[pytest] section in {filename} files is deprecated, use [tool:pytest] instead.",
|
||||
)
|
||||
|
||||
GETFUNCARGVALUE = "getfuncargvalue is deprecated, use getfixturevalue"
|
||||
GETFUNCARGVALUE = RemovedInPytest4Warning(
|
||||
"getfuncargvalue is deprecated, use getfixturevalue"
|
||||
)
|
||||
|
||||
RESULT_LOG = (
|
||||
RESULT_LOG = RemovedInPytest4Warning(
|
||||
"--result-log is deprecated and scheduled for removal in pytest 4.0.\n"
|
||||
"See https://docs.pytest.org/en/latest/usage.html#creating-resultlog-format-files for more information."
|
||||
)
|
||||
|
|
|
@ -32,7 +32,7 @@ from _pytest.compat import (
|
|||
get_real_method,
|
||||
_PytestWrapper,
|
||||
)
|
||||
from _pytest.deprecated import FIXTURE_FUNCTION_CALL, RemovedInPytest4Warning
|
||||
from _pytest.deprecated import FIXTURE_FUNCTION_CALL
|
||||
from _pytest.outcomes import fail, TEST_OUTCOME
|
||||
|
||||
FIXTURE_MSG = 'fixtures cannot have "pytest_funcarg__" prefix and be decorated with @pytest.fixture:\n{}'
|
||||
|
@ -479,6 +479,9 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
or ``session`` indicating the caching lifecycle of the resource.
|
||||
:arg extrakey: added to internal caching key of (funcargname, scope).
|
||||
"""
|
||||
from _pytest.deprecated import CACHED_SETUP
|
||||
|
||||
warnings.warn(CACHED_SETUP, stacklevel=2)
|
||||
if not hasattr(self.config, "_setupcache"):
|
||||
self.config._setupcache = {} # XXX weakref?
|
||||
cachekey = (self.fixturename, self._getscopeitem(scope), extrakey)
|
||||
|
@ -512,7 +515,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
|||
""" Deprecated, use getfixturevalue. """
|
||||
from _pytest import deprecated
|
||||
|
||||
warnings.warn(deprecated.GETFUNCARGVALUE, DeprecationWarning, stacklevel=2)
|
||||
warnings.warn(deprecated.GETFUNCARGVALUE, stacklevel=2)
|
||||
return self.getfixturevalue(argname)
|
||||
|
||||
def _get_active_fixturedef(self, argname):
|
||||
|
@ -956,8 +959,9 @@ def wrap_function_to_warning_if_called_directly(function, fixture_marker):
|
|||
used as an argument in a test function.
|
||||
"""
|
||||
is_yield_function = is_generator(function)
|
||||
msg = FIXTURE_FUNCTION_CALL.format(name=fixture_marker.name or function.__name__)
|
||||
warning = RemovedInPytest4Warning(msg)
|
||||
warning = FIXTURE_FUNCTION_CALL.format(
|
||||
name=fixture_marker.name or function.__name__
|
||||
)
|
||||
|
||||
if is_yield_function:
|
||||
|
||||
|
@ -1284,9 +1288,7 @@ class FixtureManager(object):
|
|||
|
||||
filename, lineno = getfslineno(obj)
|
||||
warnings.warn_explicit(
|
||||
RemovedInPytest4Warning(
|
||||
deprecated.FUNCARG_PREFIX.format(name=name)
|
||||
),
|
||||
deprecated.FUNCARG_PREFIX.format(name=name),
|
||||
category=None,
|
||||
filename=str(filename),
|
||||
lineno=lineno + 1,
|
||||
|
|
|
@ -61,11 +61,11 @@ class _CompatProperty(object):
|
|||
if obj is None:
|
||||
return self
|
||||
|
||||
# TODO: reenable in the features branch
|
||||
# warnings.warn(
|
||||
# "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format(
|
||||
# name=self.name, owner=type(owner).__name__),
|
||||
# PendingDeprecationWarning, stacklevel=2)
|
||||
from _pytest.deprecated import COMPAT_PROPERTY
|
||||
|
||||
warnings.warn(
|
||||
COMPAT_PROPERTY.format(name=self.name, owner=owner.__name__), stacklevel=2
|
||||
)
|
||||
return getattr(__import__("pytest"), self.name)
|
||||
|
||||
|
||||
|
@ -126,11 +126,10 @@ class Node(object):
|
|||
if isinstance(maybe_compatprop, _CompatProperty):
|
||||
return getattr(__import__("pytest"), name)
|
||||
else:
|
||||
from _pytest.deprecated import CUSTOM_CLASS
|
||||
|
||||
cls = getattr(self, name)
|
||||
# TODO: reenable in the features branch
|
||||
# warnings.warn("use of node.%s is deprecated, "
|
||||
# "use pytest_pycollect_makeitem(...) to create custom "
|
||||
# "collection nodes" % name, category=DeprecationWarning)
|
||||
self.warn(CUSTOM_CLASS.format(name=name, type_name=type(self).__name__))
|
||||
return cls
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
@ -800,7 +800,10 @@ class Generator(FunctionMixin, PyCollector):
|
|||
"%r generated tests with non-unique name %r" % (self, name)
|
||||
)
|
||||
seen[name] = True
|
||||
values.append(self.Function(name, self, args=args, callobj=call))
|
||||
with warnings.catch_warnings():
|
||||
# ignore our own deprecation warning
|
||||
function_class = self.Function
|
||||
values.append(function_class(name, self, args=args, callobj=call))
|
||||
self.warn(deprecated.YIELD_TESTS)
|
||||
return values
|
||||
|
||||
|
|
|
@ -31,10 +31,9 @@ def pytest_configure(config):
|
|||
config.pluginmanager.register(config._resultlog)
|
||||
|
||||
from _pytest.deprecated import RESULT_LOG
|
||||
from _pytest.warning_types import RemovedInPytest4Warning
|
||||
from _pytest.warnings import _issue_config_warning
|
||||
|
||||
_issue_config_warning(RemovedInPytest4Warning(RESULT_LOG), config)
|
||||
_issue_config_warning(RESULT_LOG, config)
|
||||
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import attr
|
||||
|
||||
|
||||
class PytestWarning(UserWarning):
|
||||
"""
|
||||
Bases: :class:`UserWarning`.
|
||||
|
@ -39,4 +42,19 @@ class PytestExperimentalApiWarning(PytestWarning, FutureWarning):
|
|||
)
|
||||
|
||||
|
||||
@attr.s
|
||||
class UnformattedWarning(object):
|
||||
"""Used to hold warnings that need to format their message at runtime, as opposed to a direct message.
|
||||
|
||||
Using this class avoids to keep all the warning types and messages in this module, avoiding misuse.
|
||||
"""
|
||||
|
||||
category = attr.ib()
|
||||
template = attr.ib()
|
||||
|
||||
def format(self, **kwargs):
|
||||
"""Returns an instance of the warning category, formatted with given kwargs"""
|
||||
return self.category(self.template.format(**kwargs))
|
||||
|
||||
|
||||
PYTESTER_COPY_EXAMPLE = PytestExperimentalApiWarning.simple("testdir.copy_example")
|
||||
|
|
|
@ -30,6 +30,74 @@ def test_yield_tests_deprecation(testdir):
|
|||
assert result.stdout.str().count("yield tests are deprecated") == 2
|
||||
|
||||
|
||||
def test_compat_properties_deprecation(testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo(request):
|
||||
print(request.node.Module)
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*test_compat_properties_deprecation.py:2:*usage of Function.Module is deprecated, "
|
||||
"please use pytest.Module instead*",
|
||||
"*1 passed, 1 warnings in*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_cached_setup_deprecation(testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def fix(request):
|
||||
return request.cached_setup(lambda: 1)
|
||||
|
||||
def test_foo(fix):
|
||||
assert fix == 1
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*test_cached_setup_deprecation.py:4:*cached_setup is deprecated*",
|
||||
"*1 passed, 1 warnings in*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_custom_class_deprecation(testdir):
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
class MyModule(pytest.Module):
|
||||
|
||||
class Class(pytest.Class):
|
||||
pass
|
||||
|
||||
def pytest_pycollect_makemodule(path, parent):
|
||||
return MyModule(path, parent)
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
class Test:
|
||||
def test_foo(self):
|
||||
pass
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
'*test_custom_class_deprecation.py:1:*"Class" objects in collectors of type "MyModule*',
|
||||
"*1 passed, 1 warnings in*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings("default")
|
||||
def test_funcarg_prefix_deprecation(testdir):
|
||||
testdir.makepyfile(
|
||||
|
|
|
@ -240,6 +240,9 @@ class TestClass(object):
|
|||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings(
|
||||
"ignore:usage of Generator.Function is deprecated, please use pytest.Function instead"
|
||||
)
|
||||
class TestGenerator(object):
|
||||
def test_generative_functions(self, testdir):
|
||||
modcol = testdir.getmodulecol(
|
||||
|
@ -1255,6 +1258,9 @@ class TestReportInfo(object):
|
|||
assert lineno == 1
|
||||
assert msg == "TestClass"
|
||||
|
||||
@pytest.mark.filterwarnings(
|
||||
"ignore:usage of Generator.Function is deprecated, please use pytest.Function instead"
|
||||
)
|
||||
def test_generator_reportinfo(self, testdir):
|
||||
modcol = testdir.getmodulecol(
|
||||
"""
|
||||
|
|
|
@ -977,6 +977,7 @@ class TestRequestCachedSetup(object):
|
|||
)
|
||||
reprec.assertoutcome(passed=4)
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:cached_setup is deprecated")
|
||||
def test_request_cachedsetup_extrakey(self, testdir):
|
||||
item1 = testdir.getitem("def test_func(): pass")
|
||||
req1 = fixtures.FixtureRequest(item1)
|
||||
|
@ -994,6 +995,7 @@ class TestRequestCachedSetup(object):
|
|||
assert ret1 == ret1b
|
||||
assert ret2 == ret2b
|
||||
|
||||
@pytest.mark.filterwarnings("ignore:cached_setup is deprecated")
|
||||
def test_request_cachedsetup_cache_deletion(self, testdir):
|
||||
item1 = testdir.getitem("def test_func(): pass")
|
||||
req1 = fixtures.FixtureRequest(item1)
|
||||
|
|
Loading…
Reference in New Issue