(original) (raw)

changeset: 105474:726308cfe3b5 branch: 3.6 parent: 105472:ab66423c3581 user: Victor Stinner victor.stinner@gmail.com date: Tue Dec 06 10:53:52 2016 +0100 files: Lib/test/test_warnings/__init__.py Lib/warnings.py Misc/NEWS description: catch_warnings() calls showwarning() if overriden Issue #28089: Fix a regression introduced in warnings.catch_warnings(): call warnings.showwarning() if it was overriden inside the context manager. diff -r ab66423c3581 -r 726308cfe3b5 Lib/test/test_warnings/__init__.py --- a/Lib/test/test_warnings/__init__.py Mon Dec 05 22:31:12 2016 -0800 +++ b/Lib/test/test_warnings/__init__.py Tue Dec 06 10:53:52 2016 +0100 @@ -944,6 +944,51 @@ 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 diff -r ab66423c3581 -r 726308cfe3b5 Lib/warnings.py --- a/Lib/warnings.py Mon Dec 05 22:31:12 2016 -0800 +++ b/Lib/warnings.py Tue Dec 06 10:53:52 2016 +0100 @@ -447,11 +447,20 @@ 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 @@ 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 diff -r ab66423c3581 -r 726308cfe3b5 Misc/NEWS --- a/Misc/NEWS Mon Dec 05 22:31:12 2016 -0800 +++ b/Misc/NEWS Tue Dec 06 10:53:52 2016 +0100 @@ -26,6 +26,9 @@ 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 /victor.stinner@gmail.com