[Python-checkins] gh-91230: Concise catch_warnings with simplefilter (#91435)

JelleZijlstra webhook-mailer at python.org
Sat Apr 23 20:55:33 EDT 2022


https://github.com/python/cpython/commit/b4e048411f4c62ad7343bca32c307f0bf5ef74b4
commit: b4e048411f4c62ad7343bca32c307f0bf5ef74b4
branch: main
author: Zac Hatfield-Dodds <zac.hatfield.dodds at gmail.com>
committer: JelleZijlstra <jelle.zijlstra at gmail.com>
date: 2022-04-23T17:55:22-07:00
summary:

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

files:
A Misc/NEWS.d/next/Library/2022-04-10-17-12-23.gh-issue-91230.T1d_fG.rst
M Doc/library/warnings.rst
M Doc/whatsnew/3.11.rst
M Lib/test/test_warnings/__init__.py
M Lib/warnings.py

diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst
index 289b28229e1a0..f7a1f70833b7f 100644
--- a/Doc/library/warnings.rst
+++ b/Doc/library/warnings.rst
@@ -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.
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 34742515168c3..43d8e6b1cbf41 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -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
 -------
 
diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py
index f7f931130714c..0f960b82bfaeb 100644
--- a/Lib/test/test_warnings/__init__.py
+++ b/Lib/test/test_warnings/__init__.py
@@ -373,6 +373,25 @@ def test_append_duplicate(self):
                 "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
 
diff --git a/Lib/warnings.py b/Lib/warnings.py
index 887ca6ecd1a72..7d8c4400127f7 100644
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -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 @@ def __init__(self, *, record=False, module=None):
         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 @@ def __enter__(self):
         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
diff --git a/Misc/NEWS.d/next/Library/2022-04-10-17-12-23.gh-issue-91230.T1d_fG.rst b/Misc/NEWS.d/next/Library/2022-04-10-17-12-23.gh-issue-91230.T1d_fG.rst
new file mode 100644
index 0000000000000..1efc7afca4eb2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-10-17-12-23.gh-issue-91230.T1d_fG.rst
@@ -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.



More information about the Python-checkins mailing list