diff -r 90d318d40a83 Lib/test/test_warnings/__init__.py --- a/Lib/test/test_warnings/__init__.py Mon Dec 05 18:23:27 2016 +0100 +++ b/Lib/test/test_warnings/__init__.py Mon Dec 05 23:27:29 2016 +0100 @@ -944,6 +944,26 @@ class CatchWarningTests(BaseTest): self.assertTrue(wmod.filters is not orig_filters) self.assertTrue(wmod.filters is orig_filters) + def test_record_override_showwarning(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.showwarning = my_logger + wmod.warn(text) + + self.assertEqual(len(my_log), 1, my_log) + message = my_log[0] + self.assertEqual(message.args[0], text) + self.assertEqual(log, []) + def test_check_warnings(self): # Explicit tests for the test.support convenience wrapper wmod = self.module diff -r 90d318d40a83 Lib/warnings.py --- a/Lib/warnings.py Mon Dec 05 18:23:27 2016 +0100 +++ b/Lib/warnings.py Mon Dec 05 23:27:29 2016 +0100 @@ -447,11 +447,12 @@ class catch_warnings(object): self._module._filters_mutated() self._showwarning = self._module.showwarning self._showwarnmsg = self._module._showwarnmsg + self._showwarnmsg_impl = self._module._showwarnmsg if self._record: log = [] def showarnmsg(msg): log.append(msg) - self._module._showwarnmsg = showarnmsg + self._module._showwarnmsg_impl = showarnmsg return log else: return None @@ -463,6 +464,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