Skip to content

Commit ee00946

Browse files
committed
undo deprecation
1 parent 01de0c1 commit ee00946

26 files changed

+276
-168
lines changed

.coveragerc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ exclude_lines =
2727
^\s*assert False(,|$)
2828
^\s*assert_never\(
2929

30-
^\s*if TYPE_CHECKING:
30+
^\s*(el)?if TYPE_CHECKING:
3131
^\s*@overload( |$)
3232
^\s*def .+: \.\.\.$
3333

doc/en/conf.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@
9797
# TypeVars
9898
("py:class", "_pytest._code.code.E"),
9999
("py:class", "E"), # due to delayed annotation
100+
("py:class", "T"),
101+
("py:class", "P"),
102+
("py:class", "P.args"),
103+
("py:class", "P.kwargs"),
100104
("py:class", "_pytest.fixtures.FixtureFunction"),
101105
("py:class", "_pytest.nodes._NodeType"),
102106
("py:class", "_NodeType"), # due to delayed annotation

doc/en/how-to/assert.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ exception at a specific level; exceptions contained directly in the top
282282
Alternate `pytest.raises` form (legacy)
283283
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
284284

285+
.. warning::
286+
This will be deprecated and removed in a future release.
287+
288+
285289
There is an alternate form of :func:`pytest.raises` where you pass
286290
a function that will be executed, along with ``*args`` and ``**kwargs``. :func:`pytest.raises`
287291
will then execute the function with those arguments and assert that the given exception is raised:
@@ -301,7 +305,6 @@ exception* or *wrong exception*.
301305
This form was the original :func:`pytest.raises` API, developed before the ``with`` statement was
302306
added to the Python language. Nowadays, this form is rarely used, with the context-manager form (using ``with``)
303307
being considered more readable.
304-
Nonetheless, this form is fully supported and not deprecated in any way.
305308

306309
xfail mark and pytest.raises
307310
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

doc/en/how-to/capture-warnings.rst

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,6 @@ Some examples:
338338
... warnings.warn("issue with foo() func")
339339
...
340340
341-
You can also call :func:`pytest.warns` on a function or code string:
342-
343-
.. code-block:: python
344-
345-
pytest.warns(expected_warning, func, *args, **kwargs)
346-
pytest.warns(expected_warning, "func(*args, **kwargs)")
347-
348341
The function also returns a list of all raised warnings (as
349342
``warnings.WarningMessage`` objects), which you can query for
350343
additional information:

src/_pytest/python_api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
if TYPE_CHECKING:
1818
from numpy import ndarray
19+
from typing_extensions import ParamSpec
20+
21+
P = ParamSpec("P")
1922

2023

2124
def _compare_approx(

src/_pytest/raises.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,15 @@ def raises(*, check: Callable[[BaseException], bool]) -> RaisesExc[BaseException
9595
@overload
9696
def raises(
9797
expected_exception: type[E] | tuple[type[E], ...],
98-
func: Callable[..., Any],
99-
*args: Any,
100-
**kwargs: Any,
98+
func: Callable[P, object],
99+
*args: P.args,
100+
**kwargs: P.kwargs,
101101
) -> ExceptionInfo[E]: ...
102102

103103

104104
def raises(
105105
expected_exception: type[E] | tuple[type[E], ...] | None = None,
106+
func: Callable[P, object] | None = None,
106107
*args: Any,
107108
**kwargs: Any,
108109
) -> RaisesExc[BaseException] | ExceptionInfo[E]:
@@ -253,7 +254,7 @@ def raises(
253254
>>> raises(ZeroDivisionError, f, x=0)
254255
<ExceptionInfo ...>
255256
256-
The form above is fully supported but discouraged for new code because the
257+
The form above is going to be deprecated in a future pytest release as the
257258
context manager form is regarded as more readable and less error-prone.
258259
259260
.. note::
@@ -272,7 +273,7 @@ def raises(
272273
"""
273274
__tracebackhide__ = True
274275

275-
if not args:
276+
if func is None and not args:
276277
if set(kwargs) - {"match", "check", "expected_exception"}:
277278
msg = "Unexpected keyword arguments passed to pytest.raises: "
278279
msg += ", ".join(sorted(kwargs))
@@ -289,11 +290,10 @@ def raises(
289290
f"Raising exceptions is already understood as failing the test, so you don't need "
290291
f"any special code to say 'this should never raise an exception'."
291292
)
292-
func = args[0]
293293
if not callable(func):
294294
raise TypeError(f"{func!r} object (type: {type(func)}) must be callable")
295295
with RaisesExc(expected_exception) as excinfo:
296-
func(*args[1:], **kwargs)
296+
func(*args, **kwargs)
297297
try:
298298
return excinfo
299299
finally:

src/_pytest/recwarn.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@
1717

1818

1919
if TYPE_CHECKING:
20+
from typing_extensions import ParamSpec
2021
from typing_extensions import Self
2122

23+
P = ParamSpec("P")
24+
2225
import warnings
2326

2427
from _pytest.deprecated import check_ispytest
@@ -49,7 +52,7 @@ def deprecated_call(
4952

5053

5154
@overload
52-
def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: ...
55+
def deprecated_call(func: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T: ...
5356

5457

5558
def deprecated_call(
@@ -67,6 +70,8 @@ def deprecated_call(
6770
>>> import pytest
6871
>>> with pytest.deprecated_call():
6972
... assert api_call_v2() == 200
73+
>>> with pytest.deprecated_call(match="^use v3 of this api$") as warning_messages:
74+
... assert api_call_v2() == 200
7075
7176
It can also be used by passing a function and ``*args`` and ``**kwargs``,
7277
in which case it will ensure calling ``func(*args, **kwargs)`` produces one of
@@ -76,14 +81,17 @@ def deprecated_call(
7681
that the warning matches a text or regex.
7782
7883
The context manager produces a list of :class:`warnings.WarningMessage` objects,
79-
one for each warning raised.
84+
one for each warning emitted
85+
(regardless of whether it is an ``expected_warning`` or not).
8086
"""
8187
__tracebackhide__ = True
82-
if func is not None:
83-
args = (func, *args)
84-
return warns(
85-
(DeprecationWarning, PendingDeprecationWarning, FutureWarning), *args, **kwargs
86-
)
88+
# Potential QoL: allow `with deprecated_call:` - i.e. no parens
89+
dep_warnings = (DeprecationWarning, PendingDeprecationWarning, FutureWarning)
90+
if func is None:
91+
return warns(dep_warnings, *args, **kwargs)
92+
93+
with warns(dep_warnings):
94+
return func(*args, **kwargs)
8795

8896

8997
@overload
@@ -97,16 +105,16 @@ def warns(
97105
@overload
98106
def warns(
99107
expected_warning: type[Warning] | tuple[type[Warning], ...],
100-
func: Callable[..., T],
101-
*args: Any,
102-
**kwargs: Any,
108+
func: Callable[P, T],
109+
*args: P.args,
110+
**kwargs: P.kwargs,
103111
) -> T: ...
104112

105113

106114
def warns(
107115
expected_warning: type[Warning] | tuple[type[Warning], ...] = Warning,
116+
func: Callable[..., object] | None = None,
108117
*args: Any,
109-
match: str | re.Pattern[str] | None = None,
110118
**kwargs: Any,
111119
) -> WarningsChecker | Any:
112120
r"""Assert that code raises a particular class of warning.
@@ -151,7 +159,8 @@ def warns(
151159
152160
"""
153161
__tracebackhide__ = True
154-
if not args:
162+
if func is None and not args:
163+
match: str | re.Pattern[str] | None = kwargs.pop("match", None)
155164
if kwargs:
156165
argnames = ", ".join(sorted(kwargs))
157166
raise TypeError(
@@ -160,11 +169,10 @@ def warns(
160169
)
161170
return WarningsChecker(expected_warning, match_expr=match, _ispytest=True)
162171
else:
163-
func = args[0]
164172
if not callable(func):
165173
raise TypeError(f"{func!r} object (type: {type(func)}) must be callable")
166174
with WarningsChecker(expected_warning, _ispytest=True):
167-
return func(*args[1:], **kwargs)
175+
return func(*args, **kwargs)
168176

169177

170178
class WarningsRecorder(warnings.catch_warnings):

testing/_py/test_local.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,8 @@ def test_chdir_gone(self, path1):
625625
p = path1.ensure("dir_to_be_removed", dir=1)
626626
p.chdir()
627627
p.remove()
628-
pytest.raises(error.ENOENT, local)
628+
with pytest.raises(error.ENOENT):
629+
local()
629630
assert path1.chdir() is None
630631
assert os.getcwd() == str(path1)
631632

@@ -998,8 +999,10 @@ def test_locked_make_numbered_dir(self, tmpdir):
998999
assert numdir.new(ext=str(j)).check()
9991000

10001001
def test_error_preservation(self, path1):
1001-
pytest.raises(EnvironmentError, path1.join("qwoeqiwe").mtime)
1002-
pytest.raises(EnvironmentError, path1.join("qwoeqiwe").read)
1002+
with pytest.raises(EnvironmentError):
1003+
path1.join("qwoeqiwe").mtime()
1004+
with pytest.raises(EnvironmentError):
1005+
path1.join("qwoeqiwe").read()
10031006

10041007
# def test_parentdirmatch(self):
10051008
# local.parentdirmatch('std', startmodule=__name__)
@@ -1099,7 +1102,8 @@ def test_pyimport_check_filepath_consistency(self, monkeypatch, tmpdir):
10991102
pseudopath = tmpdir.ensure(name + "123.py")
11001103
mod.__file__ = str(pseudopath)
11011104
monkeypatch.setitem(sys.modules, name, mod)
1102-
excinfo = pytest.raises(pseudopath.ImportMismatchError, p.pyimport)
1105+
with pytest.raises(pseudopath.ImportMismatchError) as excinfo:
1106+
p.pyimport()
11031107
modname, modfile, orig = excinfo.value.args
11041108
assert modname == name
11051109
assert modfile == pseudopath
@@ -1397,7 +1401,8 @@ def test_stat_helpers(self, tmpdir, monkeypatch):
13971401

13981402
def test_stat_non_raising(self, tmpdir):
13991403
path1 = tmpdir.join("file")
1400-
pytest.raises(error.ENOENT, lambda: path1.stat())
1404+
with pytest.raises(error.ENOENT):
1405+
path1.stat()
14011406
res = path1.stat(raising=False)
14021407
assert res is None
14031408

testing/code/test_code.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,8 @@ def test_code_from_func() -> None:
8585
def test_unicode_handling() -> None:
8686
value = "ąć".encode()
8787

88-
def f() -> None:
88+
with pytest.raises(Exception) as excinfo:
8989
raise Exception(value)
90-
91-
excinfo = pytest.raises(Exception, f)
9290
str(excinfo)
9391

9492

0 commit comments

Comments
 (0)