From fe41edd4c699511a778faec1d034d90f98e66d0f Mon Sep 17 00:00:00 2001 From: Jake Wallin Date: Tue, 20 Oct 2026 01:33:41 +0000 Subject: [PATCH] gh-159792: Suppress once-filtered warnings across modules --- Lib/test/test_warnings/__init__.py | 9 +++++++++ .../2026-10-20-02-00-00.gh-issue-159792.Ym3k6B.rst | 2 ++ Python/_warnings.c | 8 +++----- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-20-02-00-00.gh-issue-159792.Ym3k6B.rst diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 7262fb0d38344c0..077a0ade689591d 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -244,6 +244,15 @@ def test_once(self): 42) self.assertEqual(len(w), 0) + def test_once_across_modules(self): + with self.module.catch_warnings(record=True) as w: + self.module.simplefilter("once", UserWarning) + for name in ("module_a", "module_b"): + namespace = {"__name__": name, "warnings": self.module} + exec("warnings.warn('once across modules')\n" + "warnings.warn('once across modules')", namespace) + self.assertEqual(len(w), 1) + def test_filter_module(self): MS_WINDOWS = (sys.platform == 'win32') with self.module.catch_warnings(record=True) as w: diff --git a/Misc/NEWS.d/next/Library/2026-10-20-02-00-00.gh-issue-159792.Ym3k6B.rst b/Misc/NEWS.d/next/Library/2026-10-20-02-00-00.gh-issue-159792.Ym3k6B.rst new file mode 100644 index 000000000000000..ef13ecab0069666 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-20-02-00-00.gh-issue-159792.Ym3k6B.rst @@ -0,0 +1,2 @@ +Fix the ``"once"`` warning filter to suppress repeated warnings across +modules, matching the documented behavior and the pure-Python implementation. diff --git a/Python/_warnings.c b/Python/_warnings.c index 8fecff060fdad93..79ebdc99a749c16 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -873,11 +873,9 @@ warn_explicit(PyThreadState *tstate, PyObject *category, PyObject *message, } if (_PyUnicode_EqualToASCIIString(action, "once")) { - if (registry == NULL || registry == Py_None) { - registry = get_once_registry(interp); - if (registry == NULL) - goto cleanup; - } + registry = get_once_registry(interp); + if (registry == NULL) + goto cleanup; /* WarningsState.once_registry[(text, category)] = 1 */ rc = update_registry(interp, registry, text, category, 0); }