@@ -90,6 +90,7 @@ def warns(
90
90
expected_warning : type [Warning ] | tuple [type [Warning ], ...] = ...,
91
91
* ,
92
92
match : str | Pattern [str ] | None = ...,
93
+ keep_ignores : bool = ...,
93
94
) -> WarningsChecker : ...
94
95
95
96
@@ -106,6 +107,7 @@ def warns(
106
107
expected_warning : type [Warning ] | tuple [type [Warning ], ...] = Warning ,
107
108
* args : Any ,
108
109
match : str | Pattern [str ] | None = None ,
110
+ keep_ignores : bool = False ,
109
111
** kwargs : Any ,
110
112
) -> WarningsChecker | Any :
111
113
r"""Assert that code raises a particular class of warning.
@@ -140,6 +142,22 @@ def warns(
140
142
...
141
143
Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...
142
144
145
+ You may also set the keyword argument ``keep_ignores`` to avoid catching warnings
146
+ which were filtered out, in pytest configuration or otherwise::
147
+
148
+ >>> warnings.simplefilter("ignore", category=FutureWarning)
149
+ >>> with pytest.warns(UserWarning, keep_ignores=True):
150
+ ... warnings.warn("ignore this warning", UserWarning)
151
+ Traceback (most recent call last):
152
+ ...
153
+ Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted...
154
+
155
+ >>> with pytest.warns(RuntimeWarning):
156
+ >>> warnings.simplefilter("ignore", category=FutureWarning)
157
+ >>> with pytest.warns(UserWarning, keep_ignores=True):
158
+ ... warnings.warn("ignore this warning", UserWarning)
159
+ warnings.warn("keep this warning", RuntimeWarning)
160
+
143
161
**Using with** ``pytest.mark.parametrize``
144
162
145
163
When using :ref:`pytest.mark.parametrize ref` it is possible to parametrize tests
@@ -157,7 +175,12 @@ def warns(
157
175
f"Unexpected keyword arguments passed to pytest.warns: { argnames } "
158
176
"\n Use context-manager form instead?"
159
177
)
160
- return WarningsChecker (expected_warning , match_expr = match , _ispytest = True )
178
+ return WarningsChecker (
179
+ expected_warning ,
180
+ match_expr = match ,
181
+ keep_ignores = keep_ignores ,
182
+ _ispytest = True ,
183
+ )
161
184
else :
162
185
func = args [0 ]
163
186
if not callable (func ):
@@ -179,11 +202,12 @@ class WarningsRecorder(warnings.catch_warnings): # type:ignore[type-arg]
179
202
180
203
"""
181
204
182
- def __init__ (self , * , _ispytest : bool = False ) -> None :
205
+ def __init__ (self , * , keep_ignores : bool = False , _ispytest : bool = False ) -> None :
183
206
check_ispytest (_ispytest )
184
207
super ().__init__ (record = True )
185
208
self ._entered = False
186
209
self ._list : list [warnings .WarningMessage ] = []
210
+ self ._keep_ignores = keep_ignores
187
211
188
212
@property
189
213
def list (self ) -> list [warnings .WarningMessage ]:
@@ -233,7 +257,20 @@ def __enter__(self) -> Self:
233
257
# record=True means it's None.
234
258
assert _list is not None
235
259
self ._list = _list
236
- warnings .simplefilter ("always" )
260
+
261
+ if self ._keep_ignores :
262
+ for action , message , category , module , lineno in reversed (warnings .filters ):
263
+ if isinstance (module , re .Pattern ):
264
+ module = getattr (module , "pattern" , None ) # type: ignore[unreachable]
265
+ warnings .filterwarnings (
266
+ action = "always" if action != "ignore" else "ignore" ,
267
+ message = message if isinstance (message , str ) else "" ,
268
+ category = category ,
269
+ module = module if isinstance (module , str ) else "" ,
270
+ lineno = lineno ,
271
+ )
272
+ else :
273
+ warnings .simplefilter ("always" )
237
274
return self
238
275
239
276
def __exit__ (
@@ -259,11 +296,12 @@ def __init__(
259
296
self ,
260
297
expected_warning : type [Warning ] | tuple [type [Warning ], ...] = Warning ,
261
298
match_expr : str | Pattern [str ] | None = None ,
299
+ keep_ignores : bool = False ,
262
300
* ,
263
301
_ispytest : bool = False ,
264
302
) -> None :
265
303
check_ispytest (_ispytest )
266
- super ().__init__ (_ispytest = True )
304
+ super ().__init__ (keep_ignores = keep_ignores , _ispytest = True )
267
305
268
306
msg = "exceptions must be derived from Warning, not %s"
269
307
if isinstance (expected_warning , tuple ):
0 commit comments