Remove deprecated features (#5529)

Remove deprecated features
This commit is contained in:
Bruno Oliveira 2019-07-09 19:04:06 -03:00 committed by GitHub
commit 31738155b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 339 additions and 645 deletions

View File

@ -0,0 +1,26 @@
As per our policy, the following features have been deprecated in the 4.X series and are now
removed:
* ``Request.getfuncargvalue``: use ``Request.getfixturevalue`` instead.
* ``pytest.raises`` and ``pytest.warns`` no longer support strings as the second argument.
* ``message`` parameter of ``pytest.raises``.
* ``pytest.raises``, ``pytest.warns`` and ``ParameterSet.param`` now use native keyword-only
syntax. This might change the exception message from previous versions, but they still raise
``TypeError`` on unknown keyword arguments as before.
* ``pytest.config`` global variable.
* ``tmpdir_factory.ensuretemp`` method.
* ``pytest_logwarning`` hook.
* ``RemovedInPytest4Warning`` warning type.
* ``request`` is now a reserved name for fixtures.
For more information consult
`Deprecations and Removals <https://docs.pytest.org/en/latest/deprecations.html>`__ in the docs.

View File

@ -20,8 +20,8 @@ Below is a complete list of all pytest features which are considered deprecated.
:ref:`standard warning filters <warnings>`. :ref:`standard warning filters <warnings>`.
Removal of ``funcargnames`` alias for ``fixturenames`` ``funcargnames`` alias for ``fixturenames``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.0 .. deprecated:: 5.0
@ -34,12 +34,47 @@ in places where we or plugin authors must distinguish between fixture names and
names supplied by non-fixture things such as ``pytest.mark.parametrize``. names supplied by non-fixture things such as ``pytest.mark.parametrize``.
Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 4.0
The ``--result-log`` option produces a stream of test reports which can be
analysed at runtime. It uses a custom format which requires users to implement their own
parser, but the team believes using a line-based format that can be parsed using standard
tools would provide a suitable and better alternative.
The current plan is to provide an alternative in the pytest 5.0 series and remove the ``--result-log``
option in pytest 6.0 after the new implementation proves satisfactory to all users and is deemed
stable.
The actual alternative is still being discussed in issue `#4488 <https://github.com/pytest-dev/pytest/issues/4488>`__.
Removed Features
----------------
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed.
``pytest.config`` global
~~~~~~~~~~~~~~~~~~~~~~~~
.. versionremoved:: 5.0
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. Note that many hooks can also access
the ``config`` object indirectly, through ``session.config`` or ``item.config`` for example.
.. _`raises message deprecated`: .. _`raises message deprecated`:
``"message"`` parameter of ``pytest.raises`` ``"message"`` parameter of ``pytest.raises``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 4.1 .. versionremoved:: 5.0
It is a common mistake to think this parameter will match the exception message, while in fact It is a common mistake to think this parameter will match the exception message, while in fact
it only serves to provide a custom message in case the ``pytest.raises`` check fails. To prevent it only serves to provide a custom message in case the ``pytest.raises`` check fails. To prevent
@ -70,22 +105,12 @@ If you still have concerns about this deprecation and future removal, please com
`issue #3974 <https://github.com/pytest-dev/pytest/issues/3974>`__. `issue #3974 <https://github.com/pytest-dev/pytest/issues/3974>`__.
``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. Note that many hooks can also access
the ``config`` object indirectly, through ``session.config`` or ``item.config`` for example.
.. _raises-warns-exec: .. _raises-warns-exec:
``raises`` / ``warns`` with a string as the second argument ``raises`` / ``warns`` with a string as the second argument
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 4.1 .. versionremoved:: 5.0
Use the context manager form of these instead. When necessary, invoke ``exec`` Use the context manager form of these instead. When necessary, invoke ``exec``
directly. directly.
@ -116,27 +141,6 @@ Becomes:
Result log (``--result-log``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 4.0
The ``--result-log`` option produces a stream of test reports which can be
analysed at runtime. It uses a custom format which requires users to implement their own
parser, but the team believes using a line-based format that can be parsed using standard
tools would provide a suitable and better alternative.
The current plan is to provide an alternative in the pytest 5.0 series and remove the ``--result-log``
option in pytest 6.0 after the new implementation proves satisfactory to all users and is deemed
stable.
The actual alternative is still being discussed in issue `#4488 <https://github.com/pytest-dev/pytest/issues/4488>`__.
Removed Features
----------------
As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after
an appropriate period of deprecation has passed.
Using ``Class`` in custom Collectors Using ``Class`` in custom Collectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -430,5 +430,3 @@ The following warning types ares used by pytest and are part of the public API:
.. autoclass:: pytest.PytestUnhandledCoroutineWarning .. autoclass:: pytest.PytestUnhandledCoroutineWarning
.. autoclass:: pytest.PytestUnknownMarkWarning .. autoclass:: pytest.PytestUnknownMarkWarning
.. autoclass:: pytest.RemovedInPytest4Warning

View File

@ -56,11 +56,11 @@ def iscoroutinefunction(func):
) )
def getlocation(function, curdir): def getlocation(function, curdir=None):
function = get_real_func(function) function = get_real_func(function)
fn = py.path.local(inspect.getfile(function)) fn = py.path.local(inspect.getfile(function))
lineno = function.__code__.co_firstlineno lineno = function.__code__.co_firstlineno
if fn.relto(curdir): if curdir is not None and fn.relto(curdir):
fn = fn.relto(curdir) fn = fn.relto(curdir)
return "%s:%d" % (fn, lineno + 1) return "%s:%d" % (fn, lineno + 1)

View File

@ -17,6 +17,7 @@ from pluggy import PluginManager
import _pytest._code import _pytest._code
import _pytest.assertion import _pytest.assertion
import _pytest.deprecated
import _pytest.hookspec # the extension point definitions import _pytest.hookspec # the extension point definitions
from .exceptions import PrintHelp from .exceptions import PrintHelp
from .exceptions import UsageError from .exceptions import UsageError
@ -204,6 +205,19 @@ def _prepareconfig(args=None, plugins=None):
raise raise
def _fail_on_non_top_pytest_plugins(conftestpath, confcutdir):
msg = (
"Defining 'pytest_plugins' in a non-top-level conftest is no longer supported:\n"
"It affects the entire test suite instead of just below the conftest as expected.\n"
" {}\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"
)
fail(msg.format(conftestpath, confcutdir), pytrace=False)
class PytestPluginManager(PluginManager): class PytestPluginManager(PluginManager):
""" """
Overwrites :py:class:`pluggy.PluginManager <pluggy.PluginManager>` to add pytest-specific Overwrites :py:class:`pluggy.PluginManager <pluggy.PluginManager>` to add pytest-specific
@ -424,16 +438,7 @@ class PytestPluginManager(PluginManager):
and self._configured and self._configured
and not self._using_pyargs and not self._using_pyargs
): ):
from _pytest.deprecated import ( _fail_on_non_top_pytest_plugins(conftestpath, self._confcutdir)
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST,
)
fail(
PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST.format(
conftestpath, self._confcutdir
),
pytrace=False,
)
except Exception: except Exception:
raise ConftestImportFailure(conftestpath, sys.exc_info()) raise ConftestImportFailure(conftestpath, sys.exc_info())

View File

@ -20,8 +20,6 @@ def getcfg(args, config=None):
note: config is optional and used only to issue warnings explicitly (#2891). note: config is optional and used only to issue warnings explicitly (#2891).
""" """
from _pytest.deprecated import CFG_PYTEST_SECTION
inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"] inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"]
args = [x for x in args if not str(x).startswith("-")] args = [x for x in args if not str(x).startswith("-")]
if not args: if not args:
@ -97,6 +95,9 @@ def get_dirs_from_args(args):
return [get_dir_from_path(path) for path in possible_paths if path.exists()] return [get_dir_from_path(path) for path in possible_paths if path.exists()]
CFG_PYTEST_SECTION = "[pytest] section in {filename} files is no longer supported, change to [tool:pytest] instead."
def determine_setup(inifile, args, rootdir_cmd_arg=None, config=None): def determine_setup(inifile, args, rootdir_cmd_arg=None, config=None):
dirs = get_dirs_from_args(args) dirs = get_dirs_from_args(args)
if inifile: if inifile:
@ -107,8 +108,6 @@ def determine_setup(inifile, args, rootdir_cmd_arg=None, config=None):
try: try:
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
fail( fail(
CFG_PYTEST_SECTION.format(filename=str(inifile)), pytrace=False CFG_PYTEST_SECTION.format(filename=str(inifile)), pytrace=False
) )

View File

@ -9,10 +9,6 @@ All constants defined in this module should be either PytestWarning instances or
in case of warnings which need to format their messages. in case of warnings which need to format their messages.
""" """
from _pytest.warning_types import PytestDeprecationWarning 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"
# set of plugins which have been integrated into the core; we use this list to ignore # set of plugins which have been integrated into the core; we use this list to ignore
# them during registration to avoid conflicts # them during registration to avoid conflicts
@ -23,82 +19,13 @@ DEPRECATED_EXTERNAL_PLUGINS = {
} }
FIXTURE_FUNCTION_CALL = (
'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n'
"but are created automatically when test functions request them as parameters.\n"
"See https://docs.pytest.org/en/latest/fixture.html for more information about fixtures, and\n"
"https://docs.pytest.org/en/latest/deprecations.html#calling-fixtures-directly about how to update your code."
)
FIXTURE_NAMED_REQUEST = PytestDeprecationWarning(
"'request' is a reserved name for fixtures and will raise an error in future versions"
)
CFG_PYTEST_SECTION = "[pytest] section in {filename} files is no longer supported, change to [tool:pytest] instead."
GETFUNCARGVALUE = RemovedInPytest4Warning(
"getfuncargvalue is deprecated, use getfixturevalue"
)
FUNCARGNAMES = PytestDeprecationWarning( FUNCARGNAMES = PytestDeprecationWarning(
"The `funcargnames` attribute was an alias for `fixturenames`, " "The `funcargnames` attribute was an alias for `fixturenames`, "
"since pytest 2.3 - use the newer attribute instead." "since pytest 2.3 - use the newer attribute instead."
) )
RAISES_MESSAGE_PARAMETER = PytestDeprecationWarning(
"The 'message' parameter is deprecated.\n"
"(did you mean to use `match='some regex'` to check the exception message?)\n"
"Please see:\n"
" https://docs.pytest.org/en/4.6-maintenance/deprecations.html#message-parameter-of-pytest-raises"
)
RESULT_LOG = PytestDeprecationWarning( RESULT_LOG = PytestDeprecationWarning(
"--result-log is deprecated and scheduled for removal in pytest 6.0.\n" "--result-log is deprecated and scheduled for removal in pytest 6.0.\n"
"See https://docs.pytest.org/en/latest/deprecations.html#result-log-result-log for more information." "See https://docs.pytest.org/en/latest/deprecations.html#result-log-result-log for more information."
) )
RAISES_EXEC = PytestDeprecationWarning(
"raises(..., 'code(as_a_string)') is deprecated, use the context manager form or use `exec()` directly\n\n"
"See https://docs.pytest.org/en/latest/deprecations.html#raises-warns-exec"
)
WARNS_EXEC = PytestDeprecationWarning(
"warns(..., 'code(as_a_string)') is deprecated, use the context manager form or use `exec()` directly.\n\n"
"See https://docs.pytest.org/en/latest/deprecations.html#raises-warns-exec"
)
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"
" {}\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(
"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"
"please use the tmp_path fixture or tmp_path_factory.mktemp"
)
PYTEST_LOGWARNING = PytestDeprecationWarning(
"pytest_logwarning is deprecated, no longer being called, and will be removed soon\n"
"please use pytest_warning_captured instead"
)
PYTEST_WARNS_UNKNOWN_KWARGS = UnformattedWarning(
PytestDeprecationWarning,
"pytest.warns() got unexpected keyword arguments: {args!r}.\n"
"This will be an error in future versions.",
)
PYTEST_PARAM_UNKNOWN_KWARGS = UnformattedWarning(
PytestDeprecationWarning,
"pytest.param() got unexpected keyword arguments: {args!r}.\n"
"This will be an error in future versions.",
)

View File

@ -2,7 +2,6 @@ import functools
import inspect import inspect
import itertools import itertools
import sys import sys
import warnings
from collections import defaultdict from collections import defaultdict
from collections import deque from collections import deque
from collections import OrderedDict from collections import OrderedDict
@ -28,8 +27,6 @@ from _pytest.compat import getlocation
from _pytest.compat import is_generator from _pytest.compat import is_generator
from _pytest.compat import NOTSET from _pytest.compat import NOTSET
from _pytest.compat import safe_getattr from _pytest.compat import safe_getattr
from _pytest.deprecated import FIXTURE_FUNCTION_CALL
from _pytest.deprecated import FIXTURE_NAMED_REQUEST
from _pytest.outcomes import fail from _pytest.outcomes import fail
from _pytest.outcomes import TEST_OUTCOME from _pytest.outcomes import TEST_OUTCOME
@ -475,13 +472,6 @@ class FixtureRequest(FuncargnamesCompatAttr):
""" """
return self._get_active_fixturedef(argname).cached_result[0] return self._get_active_fixturedef(argname).cached_result[0]
def getfuncargvalue(self, argname):
""" Deprecated, use getfixturevalue. """
from _pytest import deprecated
warnings.warn(deprecated.GETFUNCARGVALUE, stacklevel=2)
return self.getfixturevalue(argname)
def _get_active_fixturedef(self, argname): def _get_active_fixturedef(self, argname):
try: try:
return self._fixture_defs[argname] return self._fixture_defs[argname]
@ -945,9 +935,12 @@ def wrap_function_to_error_out_if_called_directly(function, fixture_marker):
"""Wrap the given fixture function so we can raise an error about it being called directly, """Wrap the given fixture function so we can raise an error about it being called directly,
instead of used as an argument in a test function. instead of used as an argument in a test function.
""" """
message = FIXTURE_FUNCTION_CALL.format( message = (
name=fixture_marker.name or function.__name__ 'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n'
) "but are created automatically when test functions request them as parameters.\n"
"See https://docs.pytest.org/en/latest/fixture.html for more information about fixtures, and\n"
"https://docs.pytest.org/en/latest/deprecations.html#calling-fixtures-directly about how to update your code."
).format(name=fixture_marker.name or function.__name__)
@functools.wraps(function) @functools.wraps(function)
def result(*args, **kwargs): def result(*args, **kwargs):
@ -982,7 +975,13 @@ class FixtureFunctionMarker:
name = self.name or function.__name__ name = self.name or function.__name__
if name == "request": if name == "request":
warnings.warn(FIXTURE_NAMED_REQUEST) location = getlocation(function)
fail(
"'request' is a reserved word for fixtures, use another name:\n {}".format(
location
),
pytrace=False,
)
function._pytestfixturefunction = self function._pytestfixturefunction = self
return function return function

View File

@ -1,7 +1,6 @@
""" hook specifications for pytest plugins, invoked from main.py and builtin plugins. """ """ hook specifications for pytest plugins, invoked from main.py and builtin plugins. """
from pluggy import HookspecMarker from pluggy import HookspecMarker
from _pytest.deprecated import PYTEST_LOGWARNING
hookspec = HookspecMarker("pytest") hookspec = HookspecMarker("pytest")
@ -575,27 +574,6 @@ def pytest_terminal_summary(terminalreporter, exitstatus, config):
""" """
@hookspec(historic=True, warn_on_impl=PYTEST_LOGWARNING)
def pytest_logwarning(message, code, nodeid, fslocation):
"""
.. deprecated:: 3.8
This hook is will stop working in a future release.
pytest no longer triggers this hook, but the
terminal writer still implements it to display warnings issued by
:meth:`_pytest.config.Config.warn` and :meth:`_pytest.nodes.Node.warn`. Calling those functions will be
an error in future releases.
process a warning specified by a message, a code string,
a nodeid and fslocation (both of which may be None
if the warning is not tied to a particular node/location).
.. note::
This hook is incompatible with ``hookwrapper=True``.
"""
@hookspec(historic=True) @hookspec(historic=True)
def pytest_warning_captured(warning_message, when, item): def pytest_warning_captured(warning_message, when, item):
""" """

View File

@ -5,7 +5,6 @@ import functools
import importlib import importlib
import os import os
import sys import sys
import warnings
import attr import attr
import py import py
@ -15,7 +14,6 @@ from _pytest import nodes
from _pytest.config import directory_arg from _pytest.config import directory_arg
from _pytest.config import hookimpl from _pytest.config import hookimpl
from _pytest.config import UsageError from _pytest.config import UsageError
from _pytest.deprecated import PYTEST_CONFIG_GLOBAL
from _pytest.outcomes import exit from _pytest.outcomes import exit
from _pytest.runner import collect_one_node from _pytest.runner import collect_one_node
@ -179,26 +177,6 @@ def pytest_addoption(parser):
) )
class _ConfigDeprecated:
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 = _ConfigDeprecated(config) # compatibility
def wrap_session(config, doit): def wrap_session(config, doit):
"""Skeleton command line program""" """Skeleton command line program"""
session = Session(config) session = Session(config)

View File

@ -10,7 +10,6 @@ import attr
from ..compat import ascii_escaped from ..compat import ascii_escaped
from ..compat import getfslineno from ..compat import getfslineno
from ..compat import NOTSET from ..compat import NOTSET
from _pytest.deprecated import PYTEST_PARAM_UNKNOWN_KWARGS
from _pytest.outcomes import fail from _pytest.outcomes import fail
from _pytest.warning_types import PytestUnknownMarkWarning from _pytest.warning_types import PytestUnknownMarkWarning
@ -62,26 +61,19 @@ def get_empty_parameterset_mark(config, argnames, func):
class ParameterSet(namedtuple("ParameterSet", "values, marks, id")): class ParameterSet(namedtuple("ParameterSet", "values, marks, id")):
@classmethod @classmethod
def param(cls, *values, **kwargs): def param(cls, *values, marks=(), id=None):
marks = kwargs.pop("marks", ())
if isinstance(marks, MarkDecorator): if isinstance(marks, MarkDecorator):
marks = (marks,) marks = (marks,)
else: else:
assert isinstance(marks, (tuple, list, set)) assert isinstance(marks, (tuple, list, set))
id_ = kwargs.pop("id", None) if id is not None:
if id_ is not None: if not isinstance(id, str):
if not isinstance(id_, str):
raise TypeError( raise TypeError(
"Expected id to be a string, got {}: {!r}".format(type(id_), id_) "Expected id to be a string, got {}: {!r}".format(type(id), id)
) )
id_ = ascii_escaped(id_) id = ascii_escaped(id)
return cls(values, marks, id)
if kwargs:
warnings.warn(
PYTEST_PARAM_UNKNOWN_KWARGS.format(args=sorted(kwargs)), stacklevel=3
)
return cls(values, marks, id_)
@classmethod @classmethod
def extract_from(cls, parameterset, force_tuple=False): def extract_from(cls, parameterset, force_tuple=False):

View File

@ -12,7 +12,6 @@ from textwrap import dedent
import py import py
import _pytest import _pytest
from _pytest import deprecated
from _pytest import fixtures from _pytest import fixtures
from _pytest import nodes from _pytest import nodes
from _pytest._code import filter_traceback from _pytest._code import filter_traceback
@ -218,7 +217,9 @@ def pytest_pycollect_makeitem(collector, name, obj):
elif getattr(obj, "__test__", True): elif getattr(obj, "__test__", True):
if is_generator(obj): if is_generator(obj):
res = Function(name, parent=collector) res = Function(name, parent=collector)
reason = deprecated.YIELD_TESTS.format(name=name) reason = "yield tests were removed in pytest 4.0 - {name} will be ignored".format(
name=name
)
res.add_marker(MARK_GEN.xfail(run=False, reason=reason)) res.add_marker(MARK_GEN.xfail(run=False, reason=reason))
res.warn(PytestCollectionWarning(reason)) res.warn(PytestCollectionWarning(reason))
else: else:

View File

@ -1,8 +1,6 @@
import inspect import inspect
import math import math
import pprint import pprint
import sys
import warnings
from collections.abc import Iterable from collections.abc import Iterable
from collections.abc import Mapping from collections.abc import Mapping
from collections.abc import Sized from collections.abc import Sized
@ -14,7 +12,6 @@ from typing import Union
from more_itertools.more import always_iterable from more_itertools.more import always_iterable
import _pytest._code import _pytest._code
from _pytest import deprecated
from _pytest.compat import STRING_TYPES from _pytest.compat import STRING_TYPES
from _pytest.outcomes import fail from _pytest.outcomes import fail
@ -531,7 +528,7 @@ def _is_numpy_array(obj):
# builtin pytest.raises helper # builtin pytest.raises helper
def raises(expected_exception, *args, **kwargs): def raises(expected_exception, *args, match=None, **kwargs):
r""" r"""
Assert that a code block/function call raises ``expected_exception`` Assert that a code block/function call raises ``expected_exception``
or raise a failure exception otherwise. or raise a failure exception otherwise.
@ -544,8 +541,6 @@ def raises(expected_exception, *args, **kwargs):
__ https://docs.python.org/3/library/re.html#regular-expression-syntax __ https://docs.python.org/3/library/re.html#regular-expression-syntax
:kwparam message: **(deprecated since 4.1)** if specified, provides a custom failure message
if the exception is not raised. See :ref:`the deprecation docs <raises message deprecated>` for a workaround.
.. currentmodule:: _pytest._code .. currentmodule:: _pytest._code
@ -659,36 +654,17 @@ def raises(expected_exception, *args, **kwargs):
raise TypeError(msg % type(exc)) raise TypeError(msg % type(exc))
message = "DID NOT RAISE {}".format(expected_exception) message = "DID NOT RAISE {}".format(expected_exception)
match_expr = None
if not args: if not args:
if "message" in kwargs: return RaisesContext(
message = kwargs.pop("message") expected_exception, message=message, match_expr=match, **kwargs
warnings.warn(deprecated.RAISES_MESSAGE_PARAMETER, stacklevel=2) )
if "match" in kwargs:
match_expr = kwargs.pop("match")
if kwargs:
msg = "Unexpected keyword arguments passed to pytest.raises: "
msg += ", ".join(sorted(kwargs))
raise TypeError(msg)
return RaisesContext(expected_exception, message, match_expr)
elif isinstance(args[0], str):
warnings.warn(deprecated.RAISES_EXEC, stacklevel=2)
code, = args
assert isinstance(code, str)
frame = sys._getframe(1)
loc = frame.f_locals.copy()
loc.update(kwargs)
# print "raises frame scope: %r" % frame.f_locals
try:
code = _pytest._code.Source(code).compile(_genframe=frame)
exec(code, frame.f_globals, loc)
# XXX didn't mean f_globals == f_locals something special?
# this is destroyed here ...
except expected_exception:
return _pytest._code.ExceptionInfo.from_current()
else: else:
func = args[0] func = args[0]
if not callable(func):
raise TypeError(
"{!r} object (type: {}) must be callable".format(func, type(func))
)
try: try:
func(*args[1:], **kwargs) func(*args[1:], **kwargs)
except expected_exception: except expected_exception:

View File

@ -1,12 +1,8 @@
""" recording warnings during test function execution. """ """ recording warnings during test function execution. """
import inspect import inspect
import re import re
import sys
import warnings import warnings
import _pytest._code
from _pytest.deprecated import PYTEST_WARNS_UNKNOWN_KWARGS
from _pytest.deprecated import WARNS_EXEC
from _pytest.fixtures import yield_fixture from _pytest.fixtures import yield_fixture
from _pytest.outcomes import fail from _pytest.outcomes import fail
@ -46,7 +42,7 @@ def deprecated_call(func=None, *args, **kwargs):
return warns((DeprecationWarning, PendingDeprecationWarning), *args, **kwargs) return warns((DeprecationWarning, PendingDeprecationWarning), *args, **kwargs)
def warns(expected_warning, *args, **kwargs): def warns(expected_warning, *args, match=None, **kwargs):
r"""Assert that code raises a particular class of warning. r"""Assert that code raises a particular class of warning.
Specifically, the parameter ``expected_warning`` can be a warning class or Specifically, the parameter ``expected_warning`` can be a warning class or
@ -80,25 +76,13 @@ def warns(expected_warning, *args, **kwargs):
""" """
__tracebackhide__ = True __tracebackhide__ = True
if not args: if not args:
match_expr = kwargs.pop("match", None) return WarningsChecker(expected_warning, match_expr=match, **kwargs)
if kwargs:
warnings.warn(
PYTEST_WARNS_UNKNOWN_KWARGS.format(args=sorted(kwargs)), stacklevel=2
)
return WarningsChecker(expected_warning, match_expr=match_expr)
elif isinstance(args[0], str):
warnings.warn(WARNS_EXEC, stacklevel=2)
code, = args
assert isinstance(code, str)
frame = sys._getframe(1)
loc = frame.f_locals.copy()
loc.update(kwargs)
with WarningsChecker(expected_warning):
code = _pytest._code.Source(code).compile()
exec(code, frame.f_globals, loc)
else: else:
func = args[0] func = args[0]
if not callable(func):
raise TypeError(
"{!r} object (type: {}) must be callable".format(func, type(func))
)
with WarningsChecker(expected_warning): with WarningsChecker(expected_warning):
return func(*args[1:], **kwargs) return func(*args[1:], **kwargs)

View File

@ -2,7 +2,6 @@
import os import os
import re import re
import tempfile import tempfile
import warnings
import attr import attr
import py import py
@ -88,19 +87,6 @@ class TempdirFactory:
_tmppath_factory = attr.ib() _tmppath_factory = attr.ib()
def ensuretemp(self, string, dir=1):
""" (deprecated) return temporary directory path with
the given string as the trailing part. It is usually
better to use the 'tmpdir' function argument which
provides an empty unique-per-test-invocation directory
and is guaranteed to be empty.
"""
# py.log._apiwarn(">1.1", "use tmpdir function argument")
from .deprecated import PYTEST_ENSURETEMP
warnings.warn(PYTEST_ENSURETEMP, stacklevel=2)
return self.getbasetemp().ensure(string, dir=dir)
def mktemp(self, basename, numbered=True): def mktemp(self, basename, numbered=True):
"""Create a subdirectory of the base temporary directory and return it. """Create a subdirectory of the base temporary directory and return it.
If ``numbered``, ensure the directory is unique by adding a number If ``numbered``, ensure the directory is unique by adding a number
@ -138,7 +124,6 @@ def pytest_configure(config):
config._cleanup.append(mp.undo) config._cleanup.append(mp.undo)
mp.setattr(config, "_tmp_path_factory", tmppath_handler, raising=False) mp.setattr(config, "_tmp_path_factory", tmppath_handler, raising=False)
mp.setattr(config, "_tmpdirhandler", t, raising=False) mp.setattr(config, "_tmpdirhandler", t, raising=False)
mp.setattr(pytest, "ensuretemp", t.ensuretemp, raising=False)
@pytest.fixture(scope="session") @pytest.fixture(scope="session")

View File

@ -103,16 +103,6 @@ class PytestUnknownMarkWarning(PytestWarning):
__module__ = "pytest" __module__ = "pytest"
class RemovedInPytest4Warning(PytestDeprecationWarning):
"""
Bases: :class:`pytest.PytestDeprecationWarning`.
Warning class for features scheduled to be removed in pytest 4.0.
"""
__module__ = "pytest"
@attr.s @attr.s
class UnformattedWarning: class UnformattedWarning:
"""Used to hold warnings that need to format their message at runtime, as opposed to a direct message. """Used to hold warnings that need to format their message at runtime, as opposed to a direct message.

View File

@ -4,8 +4,6 @@ from contextlib import contextmanager
import pytest import pytest
SHOW_PYTEST_WARNINGS_ARG = "-Walways::pytest.RemovedInPytest4Warning"
def _setoption(wmod, arg): def _setoption(wmod, arg):
""" """
@ -74,9 +72,6 @@ def catch_warnings_for_item(config, ihook, when, item):
warnings.filterwarnings("always", category=DeprecationWarning) warnings.filterwarnings("always", category=DeprecationWarning)
warnings.filterwarnings("always", category=PendingDeprecationWarning) warnings.filterwarnings("always", category=PendingDeprecationWarning)
warnings.filterwarnings("error", category=pytest.RemovedInPytest4Warning)
warnings.filterwarnings("error", category=pytest.PytestDeprecationWarning)
# filters should have this precedence: mark, cmdline options, ini # filters should have this precedence: mark, cmdline options, ini
# filters should be applied in the inverse order of precedence # filters should be applied in the inverse order of precedence
for arg in inifilters: for arg in inifilters:

View File

@ -44,7 +44,7 @@ from _pytest.warning_types import PytestExperimentalApiWarning
from _pytest.warning_types import PytestUnhandledCoroutineWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning
from _pytest.warning_types import PytestUnknownMarkWarning from _pytest.warning_types import PytestUnknownMarkWarning
from _pytest.warning_types import PytestWarning from _pytest.warning_types import PytestWarning
from _pytest.warning_types import RemovedInPytest4Warning
set_trace = __pytestPDB.set_trace set_trace = __pytestPDB.set_trace
@ -84,7 +84,6 @@ __all__ = [
"PytestWarning", "PytestWarning",
"raises", "raises",
"register_assert_rewrite", "register_assert_rewrite",
"RemovedInPytest4Warning",
"Session", "Session",
"set_trace", "set_trace",
"skip", "skip",

View File

@ -9,7 +9,6 @@ import py
import pytest import pytest
from _pytest.compat import importlib_metadata from _pytest.compat import importlib_metadata
from _pytest.main import ExitCode from _pytest.main import ExitCode
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
def prepend_pythonpath(*dirs): def prepend_pythonpath(*dirs):
@ -343,7 +342,7 @@ class TestGeneralUsage:
""" """
) )
p = testdir.makepyfile("""def test_func(x): pass""") p = testdir.makepyfile("""def test_func(x): pass""")
res = testdir.runpytest(p, SHOW_PYTEST_WARNINGS_ARG) res = testdir.runpytest(p)
assert res.ret == 0 assert res.ret == 0
res.stdout.fnmatch_lines(["*1 skipped*"]) res.stdout.fnmatch_lines(["*1 skipped*"])
@ -356,9 +355,7 @@ class TestGeneralUsage:
pass pass
""" """
) )
res = testdir.runpytest( res = testdir.runpytest(p.basename + "::" + "test_func[1]")
p.basename + "::" + "test_func[1]", SHOW_PYTEST_WARNINGS_ARG
)
assert res.ret == 0 assert res.ret == 0
res.stdout.fnmatch_lines(["*1 passed*"]) res.stdout.fnmatch_lines(["*1 passed*"])

View File

@ -1,39 +1,5 @@
import os
import pytest import pytest
from _pytest import deprecated from _pytest import deprecated
from _pytest.warning_types import PytestDeprecationWarning
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
pytestmark = pytest.mark.pytester_example_path("deprecated")
def test_pytest_setup_cfg_unsupported(testdir):
testdir.makefile(
".cfg",
setup="""
[pytest]
addopts = --verbose
""",
)
with pytest.raises(pytest.fail.Exception):
testdir.runpytest()
def test_pytest_custom_cfg_unsupported(testdir):
testdir.makefile(
".cfg",
custom="""
[pytest]
addopts = --verbose
""",
)
with pytest.raises(pytest.fail.Exception):
testdir.runpytest("-c", "custom.cfg")
def test_getfuncargvalue_is_deprecated(request):
pytest.deprecated_call(request.getfuncargvalue, "tmpdir")
@pytest.mark.filterwarnings("default") @pytest.mark.filterwarnings("default")
@ -78,142 +44,3 @@ def test_external_plugins_integrated(testdir, plugin):
with pytest.warns(pytest.PytestConfigWarning): with pytest.warns(pytest.PytestConfigWarning):
testdir.parseconfig("-p", plugin) testdir.parseconfig("-p", plugin)
def test_raises_message_argument_deprecated():
with pytest.warns(pytest.PytestDeprecationWarning):
with pytest.raises(RuntimeError, message="foobar"):
raise RuntimeError
def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
testdir.makepyfile(
**{
"subdirectory/conftest.py": """
pytest_plugins=['capture']
"""
}
)
testdir.makepyfile(
"""
def test_func():
pass
"""
)
res = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG)
assert res.ret == 2
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines(
["*{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_unsupported_pyargs(
testdir, use_pyargs
):
"""When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)"""
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
files = {
"src/pkg/__init__.py": "",
"src/pkg/conftest.py": "",
"src/pkg/test_root.py": "def test(): pass",
"src/pkg/sub/__init__.py": "",
"src/pkg/sub/conftest.py": "pytest_plugins=['capture']",
"src/pkg/sub/test_bar.py": "def test(): pass",
}
testdir.makepyfile(**files)
testdir.syspathinsert(testdir.tmpdir.join("src"))
args = ("--pyargs", "pkg") if use_pyargs else ()
args += (SHOW_PYTEST_WARNINGS_ARG,)
res = testdir.runpytest(*args)
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_unsupported_no_top_level_conftest(
testdir
):
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
subdirectory = testdir.tmpdir.join("subdirectory")
subdirectory.mkdir()
testdir.makeconftest(
"""
pytest_plugins=['capture']
"""
)
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
testdir.makepyfile(
"""
def test_func():
pass
"""
)
res = testdir.runpytest_subprocess()
assert res.ret == 2
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
res.stdout.fnmatch_lines(
["*{msg}*".format(msg=msg), "*subdirectory{sep}conftest.py*".format(sep=os.sep)]
)
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
subdirectory = testdir.tmpdir.join("subdirectory")
subdirectory.mkdir()
testdir.makeconftest(
"""
pass
"""
)
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
testdir.makeconftest(
"""
import warnings
warnings.filterwarnings('always', category=DeprecationWarning)
pytest_plugins=['capture']
"""
)
testdir.makepyfile(
"""
def test_func():
pass
"""
)
res = testdir.runpytest_subprocess()
assert res.ret == 0
msg = str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
assert msg not in res.stdout.str()
def test_fixture_named_request(testdir):
testdir.copy_example()
result = testdir.runpytest()
result.stdout.fnmatch_lines(
[
"*'request' is a reserved name for fixtures and will raise an error in future versions"
]
)
def test_pytest_warns_unknown_kwargs():
with pytest.warns(
PytestDeprecationWarning,
match=r"pytest.warns\(\) got unexpected keyword arguments: \['foo'\]",
):
pytest.warns(UserWarning, foo="hello")

View File

@ -7,7 +7,6 @@ from _pytest.fixtures import FixtureLookupError
from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FixtureRequest
from _pytest.pathlib import Path from _pytest.pathlib import Path
from _pytest.pytester import get_public_names from _pytest.pytester import get_public_names
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
def test_getfuncargnames(): def test_getfuncargnames():
@ -599,8 +598,7 @@ class TestRequestBasic:
result = testdir.runpytest() result = testdir.runpytest()
result.stdout.fnmatch_lines(["* 2 passed in *"]) result.stdout.fnmatch_lines(["* 2 passed in *"])
@pytest.mark.parametrize("getfixmethod", ("getfixturevalue", "getfuncargvalue")) def test_getfixturevalue(self, testdir):
def test_getfixturevalue(self, testdir, getfixmethod):
item = testdir.getitem( item = testdir.getitem(
""" """
import pytest import pytest
@ -613,30 +611,17 @@ class TestRequestBasic:
def test_func(something): pass def test_func(something): pass
""" """
) )
import contextlib
if getfixmethod == "getfuncargvalue":
warning_expectation = pytest.warns(DeprecationWarning)
else:
# see #1830 for a cleaner way to accomplish this
@contextlib.contextmanager
def expecting_no_warning():
yield
warning_expectation = expecting_no_warning()
req = item._request req = item._request
with warning_expectation:
fixture_fetcher = getattr(req, getfixmethod)
with pytest.raises(FixtureLookupError): with pytest.raises(FixtureLookupError):
fixture_fetcher("notexists") req.getfixturevalue("notexists")
val = fixture_fetcher("something") val = req.getfixturevalue("something")
assert val == 1 assert val == 1
val = fixture_fetcher("something") val = req.getfixturevalue("something")
assert val == 1 assert val == 1
val2 = fixture_fetcher("other") val2 = req.getfixturevalue("other")
assert val2 == 2 assert val2 == 2
val2 = fixture_fetcher("other") # see about caching val2 = req.getfixturevalue("other") # see about caching
assert val2 == 2 assert val2 == 2
pytest._fillfuncargs(item) pytest._fillfuncargs(item)
assert item.funcargs["something"] == 1 assert item.funcargs["something"] == 1
@ -1141,21 +1126,6 @@ class TestFixtureUsages:
values = reprec.getfailedcollections() values = reprec.getfailedcollections()
assert len(values) == 1 assert len(values) == 1
def test_request_can_be_overridden(self, testdir):
testdir.makepyfile(
"""
import pytest
@pytest.fixture()
def request(request):
request.a = 1
return request
def test_request(request):
assert request.a == 1
"""
)
reprec = testdir.inline_run("-Wignore::pytest.PytestDeprecationWarning")
reprec.assertoutcome(passed=1)
def test_usefixtures_marker(self, testdir): def test_usefixtures_marker(self, testdir):
testdir.makepyfile( testdir.makepyfile(
""" """
@ -2200,7 +2170,7 @@ class TestFixtureMarker:
pass pass
""" """
) )
result = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest()
assert result.ret != 0 assert result.ret != 0
result.stdout.fnmatch_lines( result.stdout.fnmatch_lines(
["*ScopeMismatch*You tried*function*session*request*"] ["*ScopeMismatch*You tried*function*session*request*"]
@ -3988,3 +3958,14 @@ def test_fixture_param_shadowing(testdir):
result.stdout.fnmatch_lines(["*::test_normal_fixture[[]a[]]*"]) result.stdout.fnmatch_lines(["*::test_normal_fixture[[]a[]]*"])
result.stdout.fnmatch_lines(["*::test_normal_fixture[[]b[]]*"]) result.stdout.fnmatch_lines(["*::test_normal_fixture[[]b[]]*"])
result.stdout.fnmatch_lines(["*::test_indirect[[]1[]]*"]) result.stdout.fnmatch_lines(["*::test_indirect[[]1[]]*"])
def test_fixture_named_request(testdir):
testdir.copy_example("fixtures/test_fixture_named_request.py")
result = testdir.runpytest()
result.stdout.fnmatch_lines(
[
"*'request' is a reserved word for fixtures, use another name:",
" *test_fixture_named_request.py:5",
]
)

View File

@ -9,7 +9,6 @@ from hypothesis import strategies
import pytest import pytest
from _pytest import fixtures from _pytest import fixtures
from _pytest import python from _pytest import python
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
class TestMetafunc: class TestMetafunc:
@ -915,7 +914,7 @@ class TestMetafuncFunctional:
assert metafunc.cls == TestClass assert metafunc.cls == TestClass
""" """
) )
result = testdir.runpytest(p, "-v", SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest(p, "-v")
result.assert_outcomes(passed=2) result.assert_outcomes(passed=2)
def test_two_functions(self, testdir): def test_two_functions(self, testdir):
@ -931,7 +930,7 @@ class TestMetafuncFunctional:
assert arg1 in (10, 20) assert arg1 in (10, 20)
""" """
) )
result = testdir.runpytest("-v", p, SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines( result.stdout.fnmatch_lines(
[ [
"*test_func1*0*PASS*", "*test_func1*0*PASS*",
@ -967,7 +966,7 @@ class TestMetafuncFunctional:
assert hello == "world" assert hello == "world"
""" """
) )
result = testdir.runpytest("-v", p, SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines(["*test_myfunc*hello*PASS*", "*1 passed*"]) result.stdout.fnmatch_lines(["*test_myfunc*hello*PASS*", "*1 passed*"])
def test_two_functions_not_same_instance(self, testdir): def test_two_functions_not_same_instance(self, testdir):
@ -982,7 +981,7 @@ class TestMetafuncFunctional:
self.x = 1 self.x = 1
""" """
) )
result = testdir.runpytest("-v", p, SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest("-v", p)
result.stdout.fnmatch_lines( result.stdout.fnmatch_lines(
["*test_func*0*PASS*", "*test_func*1*PASS*", "*2 pass*"] ["*test_func*0*PASS*", "*test_func*1*PASS*", "*2 pass*"]
) )
@ -1000,7 +999,7 @@ class TestMetafuncFunctional:
self.val = 1 self.val = 1
""" """
) )
result = testdir.runpytest(p, SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest(p)
result.assert_outcomes(passed=1) result.assert_outcomes(passed=1)
def test_parametrize_functional2(self, testdir): def test_parametrize_functional2(self, testdir):
@ -1522,7 +1521,7 @@ class TestMarkersWithParametrization:
assert n + 1 == expected assert n + 1 == expected
""" """
testdir.makepyfile(s) testdir.makepyfile(s)
rec = testdir.inline_run("-m", "foo", SHOW_PYTEST_WARNINGS_ARG) rec = testdir.inline_run("-m", "foo")
passed, skipped, fail = rec.listoutcomes() passed, skipped, fail = rec.listoutcomes()
assert len(passed) == 1 assert len(passed) == 1
assert len(skipped) == 0 assert len(skipped) == 0
@ -1562,7 +1561,7 @@ class TestMarkersWithParametrization:
assert n + 1 == expected assert n + 1 == expected
""" """
testdir.makepyfile(s) testdir.makepyfile(s)
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
# xfail is skip?? # xfail is skip??
reprec.assertoutcome(passed=2, skipped=1) reprec.assertoutcome(passed=2, skipped=1)
@ -1579,7 +1578,7 @@ class TestMarkersWithParametrization:
assert n % 2 == 0 assert n % 2 == 0
""" """
testdir.makepyfile(s) testdir.makepyfile(s)
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
reprec.assertoutcome(passed=2, skipped=1) reprec.assertoutcome(passed=2, skipped=1)
def test_xfail_with_arg(self, testdir): def test_xfail_with_arg(self, testdir):
@ -1595,7 +1594,7 @@ class TestMarkersWithParametrization:
assert n + 1 == expected assert n + 1 == expected
""" """
testdir.makepyfile(s) testdir.makepyfile(s)
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
reprec.assertoutcome(passed=2, skipped=1) reprec.assertoutcome(passed=2, skipped=1)
def test_xfail_with_kwarg(self, testdir): def test_xfail_with_kwarg(self, testdir):
@ -1611,7 +1610,7 @@ class TestMarkersWithParametrization:
assert n + 1 == expected assert n + 1 == expected
""" """
testdir.makepyfile(s) testdir.makepyfile(s)
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
reprec.assertoutcome(passed=2, skipped=1) reprec.assertoutcome(passed=2, skipped=1)
def test_xfail_with_arg_and_kwarg(self, testdir): def test_xfail_with_arg_and_kwarg(self, testdir):
@ -1627,7 +1626,7 @@ class TestMarkersWithParametrization:
assert n + 1 == expected assert n + 1 == expected
""" """
testdir.makepyfile(s) testdir.makepyfile(s)
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
reprec.assertoutcome(passed=2, skipped=1) reprec.assertoutcome(passed=2, skipped=1)
@pytest.mark.parametrize("strict", [True, False]) @pytest.mark.parametrize("strict", [True, False])
@ -1648,7 +1647,7 @@ class TestMarkersWithParametrization:
strict=strict strict=strict
) )
testdir.makepyfile(s) testdir.makepyfile(s)
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
passed, failed = (2, 1) if strict else (3, 0) passed, failed = (2, 1) if strict else (3, 0)
reprec.assertoutcome(passed=passed, failed=failed) reprec.assertoutcome(passed=passed, failed=failed)
@ -1672,7 +1671,7 @@ class TestMarkersWithParametrization:
assert n + 1 == expected assert n + 1 == expected
""" """
testdir.makepyfile(s) testdir.makepyfile(s)
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
reprec.assertoutcome(passed=2, skipped=2) reprec.assertoutcome(passed=2, skipped=2)
def test_parametrize_ID_generation_string_int_works(self, testdir): def test_parametrize_ID_generation_string_int_works(self, testdir):

View File

@ -2,35 +2,20 @@ import sys
import pytest import pytest
from _pytest.outcomes import Failed from _pytest.outcomes import Failed
from _pytest.warning_types import PytestDeprecationWarning
class TestRaises: class TestRaises:
def test_check_callable(self):
with pytest.raises(TypeError, match=r".* must be callable"):
pytest.raises(RuntimeError, "int('qwe')")
def test_raises(self): def test_raises(self):
source = "int('qwe')" excinfo = pytest.raises(ValueError, int, "qwe")
with pytest.warns(PytestDeprecationWarning): assert "invalid literal" in str(excinfo.value)
excinfo = pytest.raises(ValueError, source)
code = excinfo.traceback[-1].frame.code
s = str(code.fullsource)
assert s == source
def test_raises_exec(self):
with pytest.warns(PytestDeprecationWarning) as warninfo:
pytest.raises(ValueError, "a,x = []")
assert warninfo[0].filename == __file__
def test_raises_exec_correct_filename(self):
with pytest.warns(PytestDeprecationWarning):
excinfo = pytest.raises(ValueError, 'int("s")')
assert __file__ in excinfo.traceback[-1].path
def test_raises_syntax_error(self):
with pytest.warns(PytestDeprecationWarning) as warninfo:
pytest.raises(SyntaxError, "qwe qwe qwe")
assert warninfo[0].filename == __file__
def test_raises_function(self): def test_raises_function(self):
pytest.raises(ValueError, int, "hello") excinfo = pytest.raises(ValueError, int, "hello")
assert "invalid literal" in str(excinfo.value)
def test_raises_callable_no_exception(self): def test_raises_callable_no_exception(self):
class A: class A:
@ -169,17 +154,6 @@ class TestRaises:
else: else:
assert False, "Expected pytest.raises.Exception" assert False, "Expected pytest.raises.Exception"
def test_custom_raise_message(self):
message = "TEST_MESSAGE"
try:
with pytest.warns(PytestDeprecationWarning):
with pytest.raises(ValueError, message=message):
pass
except pytest.raises.Exception as e:
assert e.msg == message
else:
assert False, "Expected pytest.raises.Exception"
@pytest.mark.parametrize("method", ["function", "with"]) @pytest.mark.parametrize("method", ["function", "with"])
def test_raises_cyclic_reference(self, method): def test_raises_cyclic_reference(self, method):
""" """

View File

@ -1,3 +1,4 @@
import os
import sys import sys
import textwrap import textwrap
@ -1241,3 +1242,140 @@ def test_config_blocked_default_plugins(testdir, plugin):
result.stdout.fnmatch_lines(["* 1 failed in *"]) result.stdout.fnmatch_lines(["* 1 failed in *"])
else: else:
assert result.stdout.lines == [""] assert result.stdout.lines == [""]
class TestSetupCfg:
def test_pytest_setup_cfg_unsupported(self, testdir):
testdir.makefile(
".cfg",
setup="""
[pytest]
addopts = --verbose
""",
)
with pytest.raises(pytest.fail.Exception):
testdir.runpytest()
def test_pytest_custom_cfg_unsupported(self, testdir):
testdir.makefile(
".cfg",
custom="""
[pytest]
addopts = --verbose
""",
)
with pytest.raises(pytest.fail.Exception):
testdir.runpytest("-c", "custom.cfg")
class TestPytestPluginsVariable:
def test_pytest_plugins_in_non_top_level_conftest_unsupported(self, testdir):
testdir.makepyfile(
**{
"subdirectory/conftest.py": """
pytest_plugins=['capture']
"""
}
)
testdir.makepyfile(
"""
def test_func():
pass
"""
)
res = testdir.runpytest()
assert res.ret == 2
msg = "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported"
res.stdout.fnmatch_lines(
[
"*{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_unsupported_pyargs(
self, testdir, use_pyargs
):
"""When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)"""
files = {
"src/pkg/__init__.py": "",
"src/pkg/conftest.py": "",
"src/pkg/test_root.py": "def test(): pass",
"src/pkg/sub/__init__.py": "",
"src/pkg/sub/conftest.py": "pytest_plugins=['capture']",
"src/pkg/sub/test_bar.py": "def test(): pass",
}
testdir.makepyfile(**files)
testdir.syspathinsert(testdir.tmpdir.join("src"))
args = ("--pyargs", "pkg") if use_pyargs else ()
res = testdir.runpytest(*args)
assert res.ret == (0 if use_pyargs else 2)
msg = (
msg
) = "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported"
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_unsupported_no_top_level_conftest(
self, testdir
):
subdirectory = testdir.tmpdir.join("subdirectory")
subdirectory.mkdir()
testdir.makeconftest(
"""
pytest_plugins=['capture']
"""
)
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
testdir.makepyfile(
"""
def test_func():
pass
"""
)
res = testdir.runpytest_subprocess()
assert res.ret == 2
msg = "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported"
res.stdout.fnmatch_lines(
[
"*{msg}*".format(msg=msg),
"*subdirectory{sep}conftest.py*".format(sep=os.sep),
]
)
def test_pytest_plugins_in_non_top_level_conftest_unsupported_no_false_positives(
self, testdir
):
subdirectory = testdir.tmpdir.join("subdirectory")
subdirectory.mkdir()
testdir.makeconftest(
"""
pass
"""
)
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
testdir.makeconftest(
"""
import warnings
warnings.filterwarnings('always', category=DeprecationWarning)
pytest_plugins=['capture']
"""
)
testdir.makepyfile(
"""
def test_func():
pass
"""
)
res = testdir.runpytest_subprocess()
assert res.ret == 0
msg = "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported"
assert msg not in res.stdout.str()

View File

@ -8,12 +8,6 @@ from _pytest.mark import EMPTY_PARAMETERSET_OPTION
from _pytest.mark import MarkGenerator as Mark from _pytest.mark import MarkGenerator as Mark
from _pytest.nodes import Collector from _pytest.nodes import Collector
from _pytest.nodes import Node from _pytest.nodes import Node
from _pytest.warning_types import PytestDeprecationWarning
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
ignore_markinfo = pytest.mark.filterwarnings(
"ignore:MarkInfo objects:pytest.RemovedInPytest4Warning"
)
class TestMark: class TestMark:
@ -25,7 +19,8 @@ class TestMark:
def test_pytest_mark_notcallable(self): def test_pytest_mark_notcallable(self):
mark = Mark() mark = Mark()
pytest.raises((AttributeError, TypeError), mark) with pytest.raises(TypeError):
mark()
def test_mark_with_param(self): def test_mark_with_param(self):
def some_function(abc): def some_function(abc):
@ -625,7 +620,6 @@ class TestFunctional:
reprec = testdir.inline_run() reprec = testdir.inline_run()
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)
@ignore_markinfo
def test_keyword_added_for_session(self, testdir): def test_keyword_added_for_session(self, testdir):
testdir.makeconftest( testdir.makeconftest(
""" """
@ -651,7 +645,7 @@ class TestFunctional:
assert marker.kwargs == {} assert marker.kwargs == {}
""" """
) )
reprec = testdir.inline_run("-m", "mark1", SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run("-m", "mark1")
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)
def assert_markers(self, items, **expected): def assert_markers(self, items, **expected):
@ -689,7 +683,7 @@ class TestFunctional:
assert True assert True
""" """
) )
reprec = testdir.inline_run(SHOW_PYTEST_WARNINGS_ARG) reprec = testdir.inline_run()
reprec.assertoutcome(skipped=1) reprec.assertoutcome(skipped=1)
@ -989,7 +983,7 @@ def test_markers_from_parametrize(testdir):
""" """
) )
result = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest()
result.assert_outcomes(passed=4) result.assert_outcomes(passed=4)
@ -1003,15 +997,3 @@ def test_pytest_param_id_requires_string():
@pytest.mark.parametrize("s", (None, "hello world")) @pytest.mark.parametrize("s", (None, "hello world"))
def test_pytest_param_id_allows_none_or_string(s): def test_pytest_param_id_allows_none_or_string(s):
assert pytest.param(id=s) assert pytest.param(id=s)
def test_pytest_param_warning_on_unknown_kwargs():
with pytest.warns(PytestDeprecationWarning) as warninfo:
# typo, should be marks=
pytest.param(1, 2, mark=pytest.mark.xfail())
assert warninfo[0].filename == __file__
msg, = warninfo[0].message.args
assert msg == (
"pytest.param() got unexpected keyword arguments: ['mark'].\n"
"This will be an error in future versions."
)

View File

@ -72,8 +72,7 @@ def test_make_hook_recorder(testdir):
def test_parseconfig(testdir): def test_parseconfig(testdir):
config1 = testdir.parseconfig() config1 = testdir.parseconfig()
config2 = testdir.parseconfig() config2 = testdir.parseconfig()
assert config2 != config1 assert config2 is not config1
assert config1 != pytest.config
def test_testdir_runs_with_plugin(testdir): def test_testdir_runs_with_plugin(testdir):

View File

@ -3,7 +3,6 @@ import warnings
import pytest import pytest
from _pytest.recwarn import WarningsRecorder from _pytest.recwarn import WarningsRecorder
from _pytest.warning_types import PytestDeprecationWarning
def test_recwarn_stacklevel(recwarn): def test_recwarn_stacklevel(recwarn):
@ -206,22 +205,17 @@ class TestDeprecatedCall:
class TestWarns: class TestWarns:
def test_strings(self): def test_check_callable(self):
source = "warnings.warn('w1', RuntimeWarning)"
with pytest.raises(TypeError, match=r".* must be callable"):
pytest.warns(RuntimeWarning, source)
def test_several_messages(self):
# different messages, b/c Python suppresses multiple identical warnings # different messages, b/c Python suppresses multiple identical warnings
source1 = "warnings.warn('w1', RuntimeWarning)" pytest.warns(RuntimeWarning, lambda: warnings.warn("w1", RuntimeWarning))
source2 = "warnings.warn('w2', RuntimeWarning)" with pytest.raises(pytest.fail.Exception):
source3 = "warnings.warn('w3', RuntimeWarning)" pytest.warns(UserWarning, lambda: warnings.warn("w2", RuntimeWarning))
with pytest.warns(PytestDeprecationWarning) as warninfo: # yo dawg pytest.warns(RuntimeWarning, lambda: warnings.warn("w3", RuntimeWarning))
pytest.warns(RuntimeWarning, source1)
pytest.raises(
pytest.fail.Exception, lambda: pytest.warns(UserWarning, source2)
)
pytest.warns(RuntimeWarning, source3)
assert len(warninfo) == 3
for w in warninfo:
assert w.filename == __file__
msg, = w.message.args
assert msg.startswith("warns(..., 'code(as_a_string)') is deprecated")
def test_function(self): def test_function(self):
pytest.warns( pytest.warns(

View File

@ -5,7 +5,6 @@ import attr
import pytest import pytest
from _pytest import pathlib from _pytest import pathlib
from _pytest.pathlib import Path from _pytest.pathlib import Path
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
def test_tmpdir_fixture(testdir): def test_tmpdir_fixture(testdir):
@ -14,13 +13,6 @@ def test_tmpdir_fixture(testdir):
results.stdout.fnmatch_lines(["*1 passed*"]) results.stdout.fnmatch_lines(["*1 passed*"])
def test_ensuretemp(recwarn):
d1 = pytest.ensuretemp("hello")
d2 = pytest.ensuretemp("hello")
assert d1 == d2
assert d1.check(dir=1)
@attr.s @attr.s
class FakeConfig: class FakeConfig:
basetemp = attr.ib() basetemp = attr.ib()
@ -85,12 +77,13 @@ def test_basetemp(testdir):
p = testdir.makepyfile( p = testdir.makepyfile(
""" """
import pytest import pytest
def test_1(): def test_1(tmpdir_factory):
pytest.ensuretemp("hello") tmpdir_factory.mktemp('hello', numbered=False)
""" """
) )
result = testdir.runpytest(p, "--basetemp=%s" % mytemp, SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest(p, "--basetemp=%s" % mytemp)
assert result.ret == 0 assert result.ret == 0
print(mytemp)
assert mytemp.join("hello").check() assert mytemp.join("hello").check()

View File

@ -498,38 +498,15 @@ class TestDeprecationWarningsByDefault:
@pytest.mark.parametrize("change_default", [None, "ini", "cmdline"]) @pytest.mark.parametrize("change_default", [None, "ini", "cmdline"])
def test_removed_in_pytest4_warning_as_error(testdir, change_default): @pytest.mark.skip(
testdir.makepyfile( reason="This test should be enabled again before pytest 6.0 is released"
""" )
import warnings, pytest
def test():
warnings.warn(pytest.RemovedInPytest4Warning("some warning"))
"""
)
if change_default == "ini":
testdir.makeini(
"""
[pytest]
filterwarnings =
ignore::pytest.RemovedInPytest4Warning
"""
)
args = (
("-Wignore::pytest.RemovedInPytest4Warning",)
if change_default == "cmdline"
else ()
)
result = testdir.runpytest(*args)
if change_default is None:
result.stdout.fnmatch_lines(["* 1 failed in *"])
else:
assert change_default in ("ini", "cmdline")
result.stdout.fnmatch_lines(["* 1 passed in *"])
@pytest.mark.parametrize("change_default", [None, "ini", "cmdline"])
def test_deprecation_warning_as_error(testdir, change_default): def test_deprecation_warning_as_error(testdir, change_default):
"""This ensures that PytestDeprecationWarnings raised by pytest are turned into errors.
This test should be enabled as part of each major release, and skipped again afterwards
to ensure our deprecations are turning into warnings as expected.
"""
testdir.makepyfile( testdir.makepyfile(
""" """
import warnings, pytest import warnings, pytest

View File

@ -128,9 +128,6 @@ norecursedirs = testing/example_scripts
xfail_strict=true xfail_strict=true
filterwarnings = filterwarnings =
error error
ignore:yield tests are deprecated, and scheduled to be removed in pytest 4.0:pytest.RemovedInPytest4Warning
ignore:Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0:pytest.RemovedInPytest4Warning
ignore::pytest.RemovedInPytest4Warning
ignore:Module already imported so cannot be rewritten:pytest.PytestWarning ignore:Module already imported so cannot be rewritten:pytest.PytestWarning
# produced by path.local # produced by path.local
ignore:bad escape.*:DeprecationWarning:re ignore:bad escape.*:DeprecationWarning:re