Drop support for positional arguments in @pytest.fixture
This commit is contained in:
parent
98530184a5
commit
c747dc5248
|
@ -2,3 +2,5 @@ As per our policy, the following features have been deprecated in the 5.X series
|
|||
removed:
|
||||
|
||||
* The ``funcargnames`` read-only property of ``FixtureRequest``, ``Metafunc``, and ``Function`` classes. Use ``fixturenames`` attribute.
|
||||
|
||||
* ``@pytest.fixture`` no longer supports positional arguments, pass all arguments by keyword instead.
|
||||
|
|
|
@ -162,6 +162,13 @@ 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.fixture`` arguments are keyword only
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. versionremoved:: 6.0
|
||||
|
||||
Passing arguments to pytest.fixture() as positional arguments has been removed - pass them by keyword instead.
|
||||
|
||||
``funcargnames`` alias for ``fixturenames``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -30,11 +30,6 @@ RESULT_LOG = PytestDeprecationWarning(
|
|||
"See https://docs.pytest.org/en/stable/deprecations.html#result-log-result-log for more information."
|
||||
)
|
||||
|
||||
FIXTURE_POSITIONAL_ARGUMENTS = PytestDeprecationWarning(
|
||||
"Passing arguments to pytest.fixture() as positional arguments is deprecated - pass them "
|
||||
"as a keyword argument instead."
|
||||
)
|
||||
|
||||
NODE_USE_FROM_PARENT = UnformattedWarning(
|
||||
PytestDeprecationWarning,
|
||||
"Direct construction of {name} has been deprecated, please use {name}.from_parent.\n"
|
||||
|
|
|
@ -2,7 +2,6 @@ import functools
|
|||
import inspect
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from collections import deque
|
||||
from types import TracebackType
|
||||
|
@ -46,7 +45,6 @@ from _pytest.compat import TYPE_CHECKING
|
|||
from _pytest.config import _PluggyPlugin
|
||||
from _pytest.config import Config
|
||||
from _pytest.config.argparsing import Parser
|
||||
from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS
|
||||
from _pytest.mark import ParameterSet
|
||||
from _pytest.outcomes import fail
|
||||
from _pytest.outcomes import TEST_OUTCOME
|
||||
|
@ -1246,7 +1244,7 @@ def fixture( # noqa: F811
|
|||
|
||||
def fixture( # noqa: F811
|
||||
fixture_function: Optional[_FixtureFunction] = None,
|
||||
*args: Any,
|
||||
*,
|
||||
scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = "function",
|
||||
params: Optional[Iterable[object]] = None,
|
||||
autouse: bool = False,
|
||||
|
@ -1308,53 +1306,6 @@ def fixture( # noqa: F811
|
|||
name the decorated function ``fixture_<fixturename>`` and then use
|
||||
``@pytest.fixture(name='<fixturename>')``.
|
||||
"""
|
||||
# Positional arguments backward compatibility.
|
||||
# If a kwarg is equal to its default, assume it was not explicitly
|
||||
# passed, i.e. not duplicated. The more correct way is to use a
|
||||
# **kwargs and check `in`, but that obfuscates the function signature.
|
||||
if isinstance(fixture_function, str):
|
||||
# It's actually the first positional argument, scope.
|
||||
args = (fixture_function, *args) # type: ignore[unreachable]
|
||||
fixture_function = None
|
||||
duplicated_args = []
|
||||
if len(args) > 0:
|
||||
if scope == "function":
|
||||
scope = args[0]
|
||||
else:
|
||||
duplicated_args.append("scope")
|
||||
if len(args) > 1:
|
||||
if params is None:
|
||||
params = args[1]
|
||||
else:
|
||||
duplicated_args.append("params")
|
||||
if len(args) > 2:
|
||||
if autouse is False:
|
||||
autouse = args[2]
|
||||
else:
|
||||
duplicated_args.append("autouse")
|
||||
if len(args) > 3:
|
||||
if ids is None:
|
||||
ids = args[3]
|
||||
else:
|
||||
duplicated_args.append("ids")
|
||||
if len(args) > 4:
|
||||
if name is None:
|
||||
name = args[4]
|
||||
else:
|
||||
duplicated_args.append("name")
|
||||
if len(args) > 5:
|
||||
raise TypeError(
|
||||
"fixture() takes 5 positional arguments but {} were given".format(len(args))
|
||||
)
|
||||
if duplicated_args:
|
||||
raise TypeError(
|
||||
"The fixture arguments are defined as positional and keyword: {}. "
|
||||
"Use only keyword arguments.".format(", ".join(duplicated_args))
|
||||
)
|
||||
if args:
|
||||
warnings.warn(FIXTURE_POSITIONAL_ARGUMENTS, stacklevel=2)
|
||||
# End backward compatiblity.
|
||||
|
||||
fixture_marker = FixtureFunctionMarker(
|
||||
scope=scope, params=params, autouse=autouse, ids=ids, name=name,
|
||||
)
|
||||
|
|
|
@ -4130,73 +4130,6 @@ def test_fixture_named_request(testdir):
|
|||
)
|
||||
|
||||
|
||||
def test_fixture_duplicated_arguments() -> None:
|
||||
"""Raise error if there are positional and keyword arguments for the same parameter (#1682)."""
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
|
||||
@pytest.fixture("session", scope="session") # type: ignore[call-overload]
|
||||
def arg(arg):
|
||||
pass
|
||||
|
||||
assert (
|
||||
str(excinfo.value)
|
||||
== "The fixture arguments are defined as positional and keyword: scope. "
|
||||
"Use only keyword arguments."
|
||||
)
|
||||
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
|
||||
@pytest.fixture( # type: ignore[call-overload]
|
||||
"function",
|
||||
["p1"],
|
||||
True,
|
||||
["id1"],
|
||||
"name",
|
||||
scope="session",
|
||||
params=["p1"],
|
||||
autouse=True,
|
||||
ids=["id1"],
|
||||
name="name",
|
||||
)
|
||||
def arg2(request):
|
||||
pass
|
||||
|
||||
assert (
|
||||
str(excinfo.value)
|
||||
== "The fixture arguments are defined as positional and keyword: scope, params, autouse, ids, name. "
|
||||
"Use only keyword arguments."
|
||||
)
|
||||
|
||||
|
||||
def test_fixture_with_positionals() -> None:
|
||||
"""Raise warning, but the positionals should still works (#1682)."""
|
||||
from _pytest.deprecated import FIXTURE_POSITIONAL_ARGUMENTS
|
||||
|
||||
with pytest.warns(pytest.PytestDeprecationWarning) as warnings:
|
||||
|
||||
@pytest.fixture("function", [0], True) # type: ignore[call-overload]
|
||||
def fixture_with_positionals():
|
||||
pass
|
||||
|
||||
assert str(warnings[0].message) == str(FIXTURE_POSITIONAL_ARGUMENTS)
|
||||
|
||||
assert fixture_with_positionals._pytestfixturefunction.scope == "function"
|
||||
assert fixture_with_positionals._pytestfixturefunction.params == (0,)
|
||||
assert fixture_with_positionals._pytestfixturefunction.autouse
|
||||
|
||||
|
||||
def test_fixture_with_too_many_positionals() -> None:
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
|
||||
@pytest.fixture("function", [0], True, ["id"], "name", "extra") # type: ignore[call-overload]
|
||||
def fixture_with_positionals():
|
||||
pass
|
||||
|
||||
assert (
|
||||
str(excinfo.value) == "fixture() takes 5 positional arguments but 6 were given"
|
||||
)
|
||||
|
||||
|
||||
def test_indirect_fixture_does_not_break_scope(testdir):
|
||||
"""Ensure that fixture scope is respected when using indirect fixtures (#570)"""
|
||||
testdir.makepyfile(
|
||||
|
|
Loading…
Reference in New Issue