gh-91230: Concise catch_warnings with simplefilter (#91435)

This commit is contained in:
Zac Hatfield-Dodds 2022-04-23 17:55:22 -07:00 committed by GitHub
parent 692e9078a1
commit b4e048411f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 2 deletions

View File

@ -491,7 +491,7 @@ Available Functions
Available Context Managers
--------------------------
.. class:: catch_warnings(*, record=False, module=None)
.. class:: catch_warnings(*, record=False, module=None, action=None, category=Warning, lineno=0, append=False)
A context manager that copies and, upon exit, restores the warnings filter
and the :func:`showwarning` function.
@ -507,6 +507,10 @@ Available Context Managers
protected. This argument exists primarily for testing the :mod:`warnings`
module itself.
If the *action* argument is not ``None``, the remaining arguments are
passed to :func:`simplefilter` as if it were called immediately on
entering the context.
.. note::
The :class:`catch_warnings` manager works by replacing and
@ -514,3 +518,7 @@ Available Context Managers
:func:`showwarning` function and internal list of filter
specifications. This means the context manager is modifying
global state and therefore is not thread-safe.
.. versionchanged:: 3.11
Added the *action*, *category*, *lineno*, and *append* parameters.

View File

@ -529,6 +529,13 @@ venv
Third party code that also creates new virtual environments should do the same.
(Contributed by Miro Hrončok in :issue:`45413`.)
warnings
--------
* :func:`warnings.catch_warnings` now accepts arguments for :func:`warnings.simplefilter`,
providing a more concise way to locally ignore warnings or convert them to errors.
(Contributed by Zac Hatfield-Dodds in :issue:`47074`.)
zipfile
-------

View File

@ -373,6 +373,25 @@ class FilterTests(BaseTest):
"appended duplicate changed order of filters"
)
def test_catchwarnings_with_simplefilter_ignore(self):
with original_warnings.catch_warnings(module=self.module):
self.module.resetwarnings()
self.module.simplefilter("error")
with self.module.catch_warnings(
module=self.module, action="ignore"
):
self.module.warn("This will be ignored")
def test_catchwarnings_with_simplefilter_error(self):
with original_warnings.catch_warnings(module=self.module):
self.module.resetwarnings()
with self.module.catch_warnings(
module=self.module, action="error", category=FutureWarning
):
self.module.warn("Other types of warnings are not errors")
self.assertRaises(FutureWarning,
self.module.warn, FutureWarning("msg"))
class CFilterTests(FilterTests, unittest.TestCase):
module = c_warnings

View File

@ -432,9 +432,13 @@ class catch_warnings(object):
named 'warnings' and imported under that name. This argument is only useful
when testing the warnings module itself.
If the 'action' argument is not None, the remaining arguments are passed
to warnings.simplefilter() as if it were called immediately on entering the
context.
"""
def __init__(self, *, record=False, module=None):
def __init__(self, *, record=False, module=None,
action=None, category=Warning, lineno=0, append=False):
"""Specify whether to record warnings and if an alternative module
should be used other than sys.modules['warnings'].
@ -445,6 +449,10 @@ class catch_warnings(object):
self._record = record
self._module = sys.modules['warnings'] if module is None else module
self._entered = False
if action is None:
self._filter = None
else:
self._filter = (action, category, lineno, append)
def __repr__(self):
args = []
@ -464,6 +472,8 @@ class catch_warnings(object):
self._module._filters_mutated()
self._showwarning = self._module.showwarning
self._showwarnmsg_impl = self._module._showwarnmsg_impl
if self._filter is not None:
simplefilter(*self._filter)
if self._record:
log = []
self._module._showwarnmsg_impl = log.append

View File

@ -0,0 +1,3 @@
:func:`warnings.catch_warnings` now accepts arguments for
:func:`warnings.simplefilter`, providing a more concise way to
locally ignore warnings or convert them to errors.