Skip to content

Commit e34945a

Browse files
[3.14] gh-146358: Fix warnings.catch_warnings on Free Threading (GH-146374) (#146418)
gh-146358: Fix warnings.catch_warnings on Free Threading (GH-146374) catch_warnings now also overrides warnings.showwarning() on Free Threading to support custom warnings.showwarning(). (cherry picked from commit 0055140) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent ce78904 commit e34945a

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
@@ -647,18 +647,18 @@ def __enter__(self):
647647
context = None
648648
self._filters = self._module.filters
649649
self._module.filters = self._filters[:]
650-
self._showwarning = self._module.showwarning
651650
self._showwarnmsg_impl = self._module._showwarnmsg_impl
651+
self._showwarning = self._module.showwarning
652652
self._module._filters_mutated_lock_held()
653653
if self._record:
654654
if _use_context:
655655
context.log = log = []
656656
else:
657657
log = []
658658
self._module._showwarnmsg_impl = log.append
659-
# Reset showwarning() to the default implementation to make sure
660-
# that _showwarnmsg() calls _showwarnmsg_impl()
661-
self._module.showwarning = self._module._showwarning_orig
659+
# Reset showwarning() to the default implementation to make sure
660+
# that _showwarnmsg() calls _showwarnmsg_impl()
661+
self._module.showwarning = self._module._showwarning_orig
662662
else:
663663
log = None
664664
if self._filter is not None:
@@ -673,8 +673,8 @@ def __exit__(self, *exc_info):
673673
self._module._warnings_context.set(self._saved_context)
674674
else:
675675
self._module.filters = self._filters
676-
self._module.showwarning = self._showwarning
677676
self._module._showwarnmsg_impl = self._showwarnmsg_impl
677+
self._module.showwarning = self._showwarning
678678
self._module._filters_mutated_lock_held()
679679

680680

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
@@ -498,6 +499,47 @@ def test_catchwarnings_with_simplefilter_error(self):
498499
stderr = stderr.getvalue()
499500
self.assertIn(error_msg, stderr)
500501

502+
def test_catchwarnings_with_showwarning(self):
503+
# gh-146358: catch_warnings must override warnings.showwarning()
504+
# if it's not the default implementation.
505+
506+
warns = []
507+
def custom_showwarning(message, category, filename, lineno,
508+
file=None, line=None):
509+
warns.append(message)
510+
511+
with self.module.catch_warnings():
512+
self.module.resetwarnings()
513+
514+
with support.swap_attr(self.module, 'showwarning',
515+
custom_showwarning):
516+
with self.module.catch_warnings(record=True) as recorded:
517+
self.module.warn("recorded")
518+
self.assertEqual(len(recorded), 1)
519+
self.assertEqual(str(recorded[0].message), 'recorded')
520+
self.assertIs(self.module.showwarning, custom_showwarning)
521+
522+
self.module.warn("custom")
523+
524+
self.assertEqual(len(warns), 1)
525+
self.assertEqual(str(warns[0]), "custom")
526+
527+
def test_catchwarnings_logging(self):
528+
# gh-146358: catch_warnings(record=True) must replace the
529+
# showwarning() function set by logging.captureWarnings(True).
530+
531+
with self.module.catch_warnings():
532+
self.module.resetwarnings()
533+
logging.captureWarnings(True)
534+
535+
with self.module.catch_warnings(record=True) as recorded:
536+
self.module.warn("recorded")
537+
self.assertEqual(len(recorded), 1)
538+
self.assertEqual(str(recorded[0].message), 'recorded')
539+
540+
logging.captureWarnings(False)
541+
542+
501543
class CFilterTests(FilterTests, unittest.TestCase):
502544
module = c_warnings
503545

0 commit comments

Comments
 (0)