1717
1818
1919if TYPE_CHECKING :
20+ from typing_extensions import ParamSpec
2021 from typing_extensions import Self
2122
23+ P = ParamSpec ("P" )
24+
2225import warnings
2326
2427from _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
5558def deprecated_call (
@@ -67,23 +70,23 @@ 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
71- It can also be used by passing a function and ``*args`` and ``**kwargs``,
72- in which case it will ensure calling ``func(*args, **kwargs)`` produces one of
73- the warnings types above. The return value is the return value of the function.
74-
75- In the context manager form you may use the keyword argument ``match`` to assert
76+ You may use the keyword argument ``match`` to assert
7677 that the warning matches a text or regex.
7778
78- The context manager produces a list of :class:`warnings.WarningMessage` objects,
79- one for each warning raised.
79+ The return value is a list of :class:`warnings.WarningMessage` objects,
80+ one for each warning emitted
81+ (regardless of whether it is an ``expected_warning`` or not).
8082 """
8183 __tracebackhide__ = True
82- if func is not None :
83- args = (func , * args )
84- return warns (
85- (DeprecationWarning , PendingDeprecationWarning , FutureWarning ), * args , ** kwargs
86- )
84+ dep_warnings = (DeprecationWarning , PendingDeprecationWarning , FutureWarning )
85+ if func is None :
86+ return warns (dep_warnings , * args , ** kwargs )
87+
88+ with warns (dep_warnings ):
89+ return func (* args , ** kwargs )
8790
8891
8992@overload
@@ -97,16 +100,16 @@ def warns(
97100@overload
98101def warns (
99102 expected_warning : type [Warning ] | tuple [type [Warning ], ...],
100- func : Callable [... , T ],
101- * args : Any ,
102- ** kwargs : Any ,
103+ func : Callable [P , T ],
104+ * args : P . args ,
105+ ** kwargs : P . kwargs ,
103106) -> T : ...
104107
105108
106109def warns (
107110 expected_warning : type [Warning ] | tuple [type [Warning ], ...] = Warning ,
111+ func : Callable [..., object ] | None = None ,
108112 * args : Any ,
109- match : str | re .Pattern [str ] | None = None ,
110113 ** kwargs : Any ,
111114) -> WarningsChecker | Any :
112115 r"""Assert that code raises a particular class of warning.
@@ -119,13 +122,13 @@ def warns(
119122 each warning emitted (regardless of whether it is an ``expected_warning`` or not).
120123 Since pytest 8.0, unmatched warnings are also re-emitted when the context closes.
121124
122- This function can be used as a context manager::
125+ This function should be used as a context manager::
123126
124127 >>> import pytest
125128 >>> with pytest.warns(RuntimeWarning):
126129 ... warnings.warn("my warning", RuntimeWarning)
127130
128- In the context manager form you may use the keyword argument ``match`` to assert
131+ The ``match`` keyword argument can be used to assert
129132 that the warning matches a text or regex::
130133
131134 >>> with pytest.warns(UserWarning, match='must be 0 or None'):
@@ -153,7 +156,8 @@ def warns(
153156
154157 """
155158 __tracebackhide__ = True
156- if not args :
159+ if func is None and not args :
160+ match : str | re .Pattern [str ] | None = kwargs .pop ("match" , None )
157161 if kwargs :
158162 argnames = ", " .join (sorted (kwargs ))
159163 raise TypeError (
@@ -162,11 +166,10 @@ def warns(
162166 )
163167 return WarningsChecker (expected_warning , match_expr = match , _ispytest = True )
164168 else :
165- func = args [0 ]
166169 if not callable (func ):
167170 raise TypeError (f"{ func !r} object (type: { type (func )} ) must be callable" )
168171 with WarningsChecker (expected_warning , _ispytest = True ):
169- return func (* args [ 1 :] , ** kwargs )
172+ return func (* args , ** kwargs )
170173
171174
172175class WarningsRecorder (warnings .catch_warnings ):
0 commit comments