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 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 A context manager that copies and, upon exit, restores the warnings filter
and the :func:`showwarning` function. and the :func:`showwarning` function.
@ -507,6 +507,10 @@ Available Context Managers
protected. This argument exists primarily for testing the :mod:`warnings` protected. This argument exists primarily for testing the :mod:`warnings`
module itself. 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:: .. note::
The :class:`catch_warnings` manager works by replacing and The :class:`catch_warnings` manager works by replacing and
@ -514,3 +518,7 @@ Available Context Managers
:func:`showwarning` function and internal list of filter :func:`showwarning` function and internal list of filter
specifications. This means the context manager is modifying specifications. This means the context manager is modifying
global state and therefore is not thread-safe. 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. Third party code that also creates new virtual environments should do the same.
(Contributed by Miro Hrončok in :issue:`45413`.) (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 zipfile
------- -------

View file

@ -373,6 +373,25 @@ class FilterTests(BaseTest):
"appended duplicate changed order of filters" "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): class CFilterTests(FilterTests, unittest.TestCase):
module = c_warnings 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 named 'warnings' and imported under that name. This argument is only useful
when testing the warnings module itself. 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 """Specify whether to record warnings and if an alternative module
should be used other than sys.modules['warnings']. should be used other than sys.modules['warnings'].
@ -445,6 +449,10 @@ class catch_warnings(object):
self._record = record self._record = record
self._module = sys.modules['warnings'] if module is None else module self._module = sys.modules['warnings'] if module is None else module
self._entered = False self._entered = False
if action is None:
self._filter = None
else:
self._filter = (action, category, lineno, append)
def __repr__(self): def __repr__(self):
args = [] args = []
@ -464,6 +472,8 @@ class catch_warnings(object):
self._module._filters_mutated() self._module._filters_mutated()
self._showwarning = self._module.showwarning self._showwarning = self._module.showwarning
self._showwarnmsg_impl = self._module._showwarnmsg_impl self._showwarnmsg_impl = self._module._showwarnmsg_impl
if self._filter is not None:
simplefilter(*self._filter)
if self._record: if self._record:
log = [] log = []
self._module._showwarnmsg_impl = log.append 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.