]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
catch_warnings() calls showwarning() if overriden
authorVictor Stinner <victor.stinner@gmail.com>
Tue, 6 Dec 2016 09:53:52 +0000 (10:53 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Tue, 6 Dec 2016 09:53:52 +0000 (10:53 +0100)
Issue #28089: Fix a regression introduced in warnings.catch_warnings(): call
warnings.showwarning() if it was overriden inside the context manager.

Lib/test/test_warnings/__init__.py
Lib/warnings.py
Misc/NEWS

index c11ee400b5d6168ac058f250234746225f125ff2..60fa780633eb8892a849d91743929e9cf934d383 100644 (file)
@@ -944,6 +944,51 @@ class CatchWarningTests(BaseTest):
                 self.assertTrue(wmod.filters is not orig_filters)
             self.assertTrue(wmod.filters is orig_filters)
 
+    def test_record_override_showwarning_before(self):
+        # Issue #28089: If warnings.showwarning() was overriden, make sure
+        # that catch_warnings(record=True) overrides it again.
+        text = "This is a warning"
+        wmod = self.module
+        my_log = []
+
+        def my_logger(message, category, filename, lineno, file=None, line=None):
+            nonlocal my_log
+            my_log.append(message)
+
+        # Override warnings.showwarning() before calling catch_warnings()
+        with support.swap_attr(wmod, 'showwarning', my_logger):
+            with wmod.catch_warnings(module=wmod, record=True) as log:
+                self.assertIsNot(wmod.showwarning, my_logger)
+
+                wmod.simplefilter("always")
+                wmod.warn(text)
+
+            self.assertIs(wmod.showwarning, my_logger)
+
+        self.assertEqual(len(log), 1, log)
+        self.assertEqual(log[0].message.args[0], text)
+        self.assertEqual(my_log, [])
+
+    def test_record_override_showwarning_inside(self):
+        # Issue #28089: It is possible to override warnings.showwarning()
+        # in the catch_warnings(record=True) context manager.
+        text = "This is a warning"
+        wmod = self.module
+        my_log = []
+
+        def my_logger(message, category, filename, lineno, file=None, line=None):
+            nonlocal my_log
+            my_log.append(message)
+
+        with wmod.catch_warnings(module=wmod, record=True) as log:
+            wmod.simplefilter("always")
+            wmod.showwarning = my_logger
+            wmod.warn(text)
+
+        self.assertEqual(len(my_log), 1, my_log)
+        self.assertEqual(my_log[0].args[0], text)
+        self.assertEqual(log, [])
+
     def test_check_warnings(self):
         # Explicit tests for the test.support convenience wrapper
         wmod = self.module
index 2b407ffed93f1733bbb743ea76aaeae6a4b4fe8c..0d167667d138d92b78016bb0124fa6cef91fbf61 100644 (file)
@@ -447,11 +447,20 @@ class catch_warnings(object):
         self._module._filters_mutated()
         self._showwarning = self._module.showwarning
         self._showwarnmsg = self._module._showwarnmsg
+        self._showwarnmsg_impl = self._module._showwarnmsg_impl
         if self._record:
             log = []
-            def showarnmsg(msg):
+
+            def showarnmsg_logger(msg):
+                nonlocal log
                 log.append(msg)
-            self._module._showwarnmsg = showarnmsg
+
+            self._module._showwarnmsg_impl = showarnmsg_logger
+
+            # Reset showwarning() to the default implementation to make sure
+            # that _showwarnmsg() calls _showwarnmsg_impl()
+            self._module.showwarning = self._module._showwarning
+
             return log
         else:
             return None
@@ -463,6 +472,7 @@ class catch_warnings(object):
         self._module._filters_mutated()
         self._module.showwarning = self._showwarning
         self._module._showwarnmsg = self._showwarnmsg
+        self._module._showwarnmsg_impl = self._showwarnmsg_impl
 
 
 # filters contains a sequence of filter 5-tuples
index a29e50af4108aa0651cfa1049e1c25260fdf4e50..bfe3cc9284826c3cd1a73e47b46d9550703ceb61 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -26,6 +26,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #28089: Fix a regression introduced in warnings.catch_warnings():
+  call warnings.showwarning() if it was overriden inside the context manager.
+
 - Issue #27172: To assist with upgrades from 2.7, the previously documented
   deprecation of ``inspect.getfullargspec()`` has been reversed. This decision
   may be revisited again after the Python 2.7 branch is no longer officially