diff --git a/changelog/5180.removal.rst b/changelog/5180.removal.rst index 2417672be..e72b76d5a 100644 --- a/changelog/5180.removal.rst +++ b/changelog/5180.removal.rst @@ -7,6 +7,10 @@ removed: * ``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. + For more information consult `Deprecations and Removals `__ in the docs. diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index bbb073520..dd2d65d15 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -10,7 +10,6 @@ in case of warnings which need to format their messages. """ 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" @@ -73,15 +72,3 @@ 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.", -) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 1af7a9b42..aa4c8f828 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -9,7 +9,6 @@ import attr from ..compat import ascii_escaped from ..compat import getfslineno from ..compat import NOTSET -from _pytest.deprecated import PYTEST_PARAM_UNKNOWN_KWARGS from _pytest.outcomes import fail from _pytest.warning_types import PytestUnknownMarkWarning @@ -61,26 +60,19 @@ def get_empty_parameterset_mark(config, argnames, func): class ParameterSet(namedtuple("ParameterSet", "values, marks, id")): @classmethod - def param(cls, *values, **kwargs): - marks = kwargs.pop("marks", ()) + def param(cls, *values, marks=(), id=None): if isinstance(marks, MarkDecorator): marks = (marks,) else: assert isinstance(marks, (tuple, list, set)) - id_ = kwargs.pop("id", None) - if id_ is not None: - if not isinstance(id_, str): + if id is not None: + if not isinstance(id, str): 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_) - - if kwargs: - warnings.warn( - PYTEST_PARAM_UNKNOWN_KWARGS.format(args=sorted(kwargs)), stacklevel=3 - ) - return cls(values, marks, id_) + id = ascii_escaped(id) + return cls(values, marks, id) @classmethod def extract_from(cls, parameterset, force_tuple=False): diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 9f5220766..3266188a1 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -523,7 +523,7 @@ def _is_numpy_array(obj): # builtin pytest.raises helper -def raises(expected_exception, *args, **kwargs): +def raises(expected_exception, *args, match=None, **kwargs): r""" Assert that a code block/function call raises ``expected_exception`` or raise a failure exception otherwise. @@ -649,16 +649,14 @@ def raises(expected_exception, *args, **kwargs): raise TypeError(msg % type(exc)) message = "DID NOT RAISE {}".format(expected_exception) - match_expr = None if not args: - if "match" in kwargs: - match_expr = kwargs.pop("match") if kwargs: msg = "Unexpected keyword arguments passed to pytest.raises: " msg += ", ".join(sorted(kwargs)) + msg += "\nUse context-manager form instead?" raise TypeError(msg) - return RaisesContext(expected_exception, message, match_expr) + return RaisesContext(expected_exception, message, match) else: func = args[0] if not callable(func): diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 8733a893a..8a1cad4a1 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -3,7 +3,6 @@ import inspect import re import warnings -from _pytest.deprecated import PYTEST_WARNS_UNKNOWN_KWARGS from _pytest.fixtures import yield_fixture from _pytest.outcomes import fail @@ -43,7 +42,7 @@ def deprecated_call(func=None, *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. Specifically, the parameter ``expected_warning`` can be a warning class or @@ -77,12 +76,12 @@ def warns(expected_warning, *args, **kwargs): """ __tracebackhide__ = True if not args: - match_expr = kwargs.pop("match", None) if kwargs: - warnings.warn( - PYTEST_WARNS_UNKNOWN_KWARGS.format(args=sorted(kwargs)), stacklevel=2 - ) - return WarningsChecker(expected_warning, match_expr=match_expr) + msg = "Unexpected keyword arguments passed to pytest.warns: " + msg += ", ".join(sorted(kwargs)) + msg += "\nUse context-manager form instead?" + raise TypeError(msg) + return WarningsChecker(expected_warning, match_expr=match) else: func = args[0] if not callable(func): diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 4db4a9c98..b21a08703 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -2,7 +2,6 @@ import os import pytest 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") @@ -199,11 +198,3 @@ def test_fixture_named_request(testdir): "*'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") diff --git a/testing/test_mark.py b/testing/test_mark.py index 1544ffe56..ce5991563 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -8,7 +8,6 @@ from _pytest.mark import EMPTY_PARAMETERSET_OPTION from _pytest.mark import MarkGenerator as Mark from _pytest.nodes import Collector from _pytest.nodes import Node -from _pytest.warning_types import PytestDeprecationWarning from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG ignore_markinfo = pytest.mark.filterwarnings( @@ -1004,15 +1003,3 @@ def test_pytest_param_id_requires_string(): @pytest.mark.parametrize("s", (None, "hello world")) def test_pytest_param_id_allows_none_or_string(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." - )