Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion changelog/14742.deprecation.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The private ``_pytest.python.CallSpec2`` name has been renamed to ``CallSpec``.
The old ``CallSpec2`` alias remains available for now and will be removed in pytest 10.
The old ``CallSpec2`` alias remains available for now and will be removed in pytest 11.
2 changes: 1 addition & 1 deletion changelog/14774.deprecation.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Similarly to the deprecation of class-scoped fixtures defined as instance methods in pytest 9.1,
*all* higher-scoped fixtures (``module``, ``package``, and ``session``) defined
as instance methods are now deprecated.
as instance methods are now deprecated and will be removed in pytest 11.

They suffer from the same issue the original deprecation only fixed for
class-scoped fixtures, see :issue:`10819` and :issue:`14011`.
2 changes: 1 addition & 1 deletion changelog/14808.deprecation.rst
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Passing a non-string value to a ``string``-typed ini option now emits a ``pytest.PytestRemovedIn10Warning``. This affects ``[tool.pytest.ini_options]`` in ``pyproject.toml``, where TOML arrays are kept as lists by ``make_scalar`` instead of being converted to strings. In pytest 10 this will raise a ``TypeError``, matching the behavior of the corresponding TOML config path.
Passing a non-string value to a ``string``-typed ini option now emits a ``pytest.PytestRemovedIn11Warning``. This affects ``[tool.pytest.ini_options]`` in ``pyproject.toml``, where TOML arrays are kept as lists by ``make_scalar`` instead of being converted to strings. In pytest 11 this will raise a ``TypeError``, matching the behavior of the corresponding TOML config path.
7 changes: 7 additions & 0 deletions changelog/15200.deprecation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Added :class:`pytest.PytestRemovedIn11Warning`.

Deprecations that have not been part of a release yet now use it, so they are removed in pytest 11 instead of turning into errors in pytest 10 without ever having been released as warnings:

- module-, package- and session-scoped fixtures defined as instance methods (class-scoped ones stay scheduled for pytest 10);
- non-string values for ``string``-typed ini options;
- the ``_pytest.python.CallSpec2`` alias.
8 changes: 4 additions & 4 deletions doc/en/deprecations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ Below is a complete list of all pytest features which are considered deprecated.
``_pytest.python.CallSpec2`` renamed to ``CallSpec``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. deprecated:: 9.1
.. deprecated:: 9.2

The private ``_pytest.python.CallSpec2`` name has been renamed to ``CallSpec``.

Plugins that import ``CallSpec2`` should update to ``CallSpec``. The old
``CallSpec2`` alias remains available for now and will be removed in pytest 10.
``CallSpec2`` alias remains available for now and will be removed in pytest 11.


.. _fixture-nodeid-deprecated:
Expand Down Expand Up @@ -137,7 +137,7 @@ be retrieved while they remain active, though this is discouraged.
``config.inicfg``
~~~~~~~~~~~~~~~~~

.. deprecated:: 9.0
.. deprecated:: 9.1

The private ``config.inicfg`` attribute is deprecated.
Use :meth:`config.getini() <pytest.Config.getini>` to access configuration values instead.
Expand Down Expand Up @@ -280,7 +280,7 @@ to all test methods.

Similarly, using a scope higher than ``class`` (``module``, ``package`` or ``session``)
without using ``@classmethod`` (or ``@staticmethod``) is deprecated and will be
removed in pytest 10.0.
removed in pytest 11.0.

.. _monkeypatch-fixup-namespace-packages:

Expand Down
3 changes: 3 additions & 0 deletions doc/en/reference/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,9 @@ Custom warnings generated in some situations such as improper usage or deprecate
.. autoclass:: pytest.PytestRemovedIn10Warning
:show-inheritance:

.. autoclass:: pytest.PytestRemovedIn11Warning
:show-inheritance:

.. autoclass:: pytest.PytestUnknownMarkWarning
:show-inheritance:

Expand Down
14 changes: 11 additions & 3 deletions src/_pytest/deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from _pytest.warning_types import PytestDeprecationWarning
from _pytest.warning_types import PytestRemovedIn10Warning
from _pytest.warning_types import PytestRemovedIn11Warning
from _pytest.warning_types import UnformattedWarning


Expand Down Expand Up @@ -46,6 +47,13 @@
"See https://docs.pytest.org/en/stable/deprecations.html#class-scoped-fixture-as-instance-method",
)

# Same as CLASS_FIXTURE_INSTANCE_METHOD, but for module/package/session scope,
# which was deprecated later and so is removed later.
HIGHER_SCOPED_FIXTURE_INSTANCE_METHOD = UnformattedWarning(
PytestRemovedIn11Warning,
CLASS_FIXTURE_INSTANCE_METHOD.template,
)

# This deprecation is never really meant to be removed.
PRIVATE = UnformattedWarning(
PytestDeprecationWarning,
Expand Down Expand Up @@ -106,7 +114,7 @@
"See https://docs.pytest.org/en/stable/deprecations.html#the-pastebin-option",
)

INI_STRING_TYPE_NON_STR_VALUE = PytestRemovedIn10Warning(
INI_STRING_TYPE_NON_STR_VALUE = PytestRemovedIn11Warning(
"Passing a value that is not a string to a 'string'-typed ini option is deprecated.\n"
"In a future version this will raise a TypeError, matching the behavior of the "
"corresponding TOML config path.\n"
Expand Down Expand Up @@ -157,9 +165,9 @@
)

CALLSPEC2_RENAMED = UnformattedWarning(
PytestRemovedIn10Warning,
PytestRemovedIn11Warning,
"_pytest.python.CallSpec2 has been renamed to CallSpec.\n"
"The CallSpec2 alias will be removed in pytest 10.\n"
"The CallSpec2 alias will be removed in pytest 11.\n"
"Update imports to use CallSpec instead.\n"
"See https://docs.pytest.org/en/stable/deprecations.html#callspec2-renamed",
)
Expand Down
16 changes: 14 additions & 2 deletions src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
from _pytest.deprecated import FIXTURE_GETFIXTUREVALUE_DURING_TEARDOWN
from _pytest.deprecated import FIXTURE_NODEID_DEPRECATED
from _pytest.deprecated import FIXTUREDEF_HAS_LOCATION_DEPRECATED
from _pytest.deprecated import HIGHER_SCOPED_FIXTURE_INSTANCE_METHOD
from _pytest.deprecated import PARSEFACTORIES_NODEID_DEPRECATED
from _pytest.deprecated import YIELD_FIXTURE
from _pytest.main import Session
Expand Down Expand Up @@ -1335,7 +1336,13 @@ def resolve_fixture_function(
value."""

def __tracebackhide__(e):
return issubclass(e.type, CLASS_FIXTURE_INSTANCE_METHOD.category)
return issubclass(
e.type,
(
CLASS_FIXTURE_INSTANCE_METHOD.category,
HIGHER_SCOPED_FIXTURE_INSTANCE_METHOD.category,
),
)

fixturefunc = fixturedef.func
# The fixture function needs to be bound to the actual
Expand All @@ -1350,8 +1357,13 @@ def __tracebackhide__(e):
# classmethod: bound_to is the class itself (a type)
# instance method: bound_to is an instance (not a type)
if not isinstance(bound_to, type):
warning = (
CLASS_FIXTURE_INSTANCE_METHOD
if fixturedef._scope is Scope.Class
else HIGHER_SCOPED_FIXTURE_INSTANCE_METHOD
)
warnings.warn(
CLASS_FIXTURE_INSTANCE_METHOD.format(
warning.format(
scope=fixturedef._scope.name.capitalize(),
fixturename=request.fixturename,
),
Expand Down
6 changes: 6 additions & 0 deletions src/_pytest/warning_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ class PytestRemovedIn10Warning(PytestDeprecationWarning):
__module__ = "pytest"


class PytestRemovedIn11Warning(PytestDeprecationWarning):
"""Warning class for features that will be removed in pytest 11."""

__module__ = "pytest"


@final
class PytestExperimentalApiWarning(PytestWarning, FutureWarning):
"""Warning category used to denote experiments in pytest.
Expand Down
2 changes: 2 additions & 0 deletions src/pytest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
from _pytest.warning_types import PytestExperimentalApiWarning
from _pytest.warning_types import PytestFDWarning
from _pytest.warning_types import PytestRemovedIn10Warning
from _pytest.warning_types import PytestRemovedIn11Warning
from _pytest.warning_types import PytestReturnNotNoneWarning
from _pytest.warning_types import PytestUnhandledThreadExceptionWarning
from _pytest.warning_types import PytestUnknownMarkWarning
Expand Down Expand Up @@ -141,6 +142,7 @@
"PytestFDWarning",
"PytestPluginManager",
"PytestRemovedIn10Warning",
"PytestRemovedIn11Warning",
"PytestReturnNotNoneWarning",
"PytestUnhandledThreadExceptionWarning",
"PytestUnknownMarkWarning",
Expand Down
23 changes: 17 additions & 6 deletions testing/deprecated_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,15 @@ def test_foo(self, fix):
pass
"""
)
result = pytester.runpytest("-Werror::pytest.PytestRemovedIn10Warning")
category = (
"PytestRemovedIn10Warning"
if scope is Scope.Class
else "PytestRemovedIn11Warning"
)
result = pytester.runpytest(f"-Werror::pytest.{category}")
result.assert_outcomes(errors=1)
result.stdout.fnmatch_lines(
["*PytestRemovedIn10Warning: *-scoped fixtures defined as instance methods*"]
[f"*{category}: *-scoped fixtures defined as instance methods*"]
)


Expand All @@ -146,7 +151,10 @@ def test_foo(self, fix):
assert type(self).attr is True
"""
)
result = pytester.runpytest("-Werror::pytest.PytestRemovedIn10Warning")
result = pytester.runpytest(
"-Werror::pytest.PytestRemovedIn10Warning",
"-Werror::pytest.PytestRemovedIn11Warning",
)
result.assert_outcomes(passed=1)


Expand All @@ -167,7 +175,10 @@ def test_foo(self, fix):
pass
"""
)
result = pytester.runpytest("-Werror::pytest.PytestRemovedIn10Warning")
result = pytester.runpytest(
"-Werror::pytest.PytestRemovedIn10Warning",
"-Werror::pytest.PytestRemovedIn11Warning",
)
result.assert_outcomes(passed=1)


Expand Down Expand Up @@ -360,12 +371,12 @@ def test_callspec2_renamed() -> None:
import _pytest.python as python_mod
from _pytest.python import CallSpec

with pytest.warns(pytest.PytestRemovedIn10Warning, match="CallSpec2"):
with pytest.warns(pytest.PytestRemovedIn11Warning, match="CallSpec2"):
from _pytest.python import CallSpec2

assert CallSpec2 is CallSpec

with pytest.warns(pytest.PytestRemovedIn10Warning, match="CallSpec2"):
with pytest.warns(pytest.PytestRemovedIn11Warning, match="CallSpec2"):
assert python_mod.CallSpec2 is CallSpec


Expand Down
2 changes: 1 addition & 1 deletion testing/plugins_integration/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ filterwarnings =
error::pytest.PytestWarning
ignore:usefixtures.* without arguments has no effect:pytest.PytestWarning
ignore:.*.fspath is deprecated and will be replaced by .*.path.*:pytest.PytestDeprecationWarning
ignore:_pytest.python.CallSpec2 has been renamed to CallSpec.:pytest.PytestRemovedIn10Warning
ignore:_pytest.python.CallSpec2 has been renamed to CallSpec.:pytest.PytestRemovedIn11Warning
4 changes: 2 additions & 2 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ def pytest_addoption(parser):
def test_addini_string_non_str_deprecated(self, pytester: Pytester) -> None:
"""Passing a non-string value to a 'string'-typed ini option emits a
deprecation warning. The value is still returned as-is for now, but will
raise TypeError in pytest 10."""
raise TypeError in pytest 11."""
pytester.makeconftest(
"""
def pytest_addoption(parser):
Expand All @@ -1175,7 +1175,7 @@ def pytest_addoption(parser):
)
config = pytester.parseconfig()
with pytest.warns(
pytest.PytestRemovedIn10Warning,
pytest.PytestRemovedIn11Warning,
match="Passing a value that is not a string to a 'string'-typed ini option",
):
result = config.getini("myname")
Expand Down
Loading