Skip to content

Commit 0055140

Browse files
authored
gh-146358: Fix warnings.catch_warnings on Free Threading (#146374)
catch_warnings now also overrides warnings.showwarning() on Free Threading to support custom warnings.showwarning().
1 parent 04bd543 commit 0055140

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

Lib/_py_warnings.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -703,18 +703,18 @@ def __enter__(self):
703703
context = None
704704
self._filters = self._module.filters
705705
self._module.filters = self._filters[:]
706-
self._showwarning = self._module.showwarning
707706
self._showwarnmsg_impl = self._module._showwarnmsg_impl
707+
self._showwarning = self._module.showwarning
708708
self._module._filters_mutated_lock_held()
709709
if self._record:
710710
if _use_context:
711711
context.log = log = []
712712
else:
713713
log = []
714714
self._module._showwarnmsg_impl = log.append
715-
# Reset showwarning() to the default implementation to make sure
716-
# that _showwarnmsg() calls _showwarnmsg_impl()
717-
self._module.showwarning = self._module._showwarning_orig
715+
# Reset showwarning() to the default implementation to make sure
716+
# that _showwarnmsg() calls _showwarnmsg_impl()
717+
self._module.showwarning = self._module._showwarning_orig
718718
else:
719719
log = None
720720
if self._filter is not None:
@@ -729,8 +729,8 @@ def __exit__(self, *exc_info):
729729
self._module._warnings_context.set(self._saved_context)
730730
else:
731731
self._module.filters = self._filters
732-
self._module.showwarning = self._showwarning
733732
self._module._showwarnmsg_impl = self._showwarnmsg_impl
733+
self._module.showwarning = self._showwarning
734734
self._module._filters_mutated_lock_held()
735735

736736

Lib/test/test_warnings/__init__.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from contextlib import contextmanager
22
import linecache
3+
import logging
34
import os
45
import importlib
56
import inspect
@@ -509,6 +510,47 @@ def test_catchwarnings_with_simplefilter_error(self):
509510
stderr = stderr.getvalue()
510511
self.assertIn(error_msg, stderr)
511512

513+
def test_catchwarnings_with_showwarning(self):
514+
# gh-146358: catch_warnings must override warnings.showwarning()
515+
# if it's not the default implementation.
516+
517+
warns = []
518+
def custom_showwarning(message, category, filename, lineno,
519+
file=None, line=None):
520+
warns.append(message)
521+
522+
with self.module.catch_warnings():
523+
self.module.resetwarnings()
524+
525+
with support.swap_attr(self.module, 'showwarning',
526+
custom_showwarning):
527+
with self.module.catch_warnings(record=True) as recorded:
528+
self.module.warn("recorded")
529+
self.assertEqual(len(recorded), 1)
530+
self.assertEqual(str(recorded[0].message), 'recorded')
531+
self.assertIs(self.module.showwarning, custom_showwarning)
532+
533+
self.module.warn("custom")
534+
535+
self.assertEqual(len(warns), 1)
536+
self.assertEqual(str(warns[0]), "custom")
537+
538+
def test_catchwarnings_logging(self):
539+
# gh-146358: catch_warnings(record=True) must replace the
540+
# showwarning() function set by logging.captureWarnings(True).
541+
542+
with self.module.catch_warnings():
543+
self.module.resetwarnings()
544+
logging.captureWarnings(True)
545+
546+
with self.module.catch_warnings(record=True) as recorded:
547+
self.module.warn("recorded")
548+
self.assertEqual(len(recorded), 1)
549+
self.assertEqual(str(recorded[0].message), 'recorded')
550+
551+
logging.captureWarnings(False)
552+
553+
512554
class CFilterTests(FilterTests, unittest.TestCase):
513555
module = c_warnings
514556

0 commit comments

Comments
 (0)