https://github.com/python/cpython/commit/cf9ef73121cd2b96dd514e09b3ad253d841d91dd
commit: cf9ef73121cd2b96dd514e09b3ad253d841d91dd
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-09-16T17:06:44Z
summary:
gh-134716: Support regular expressions in -W and PYTHONWARNINGS (GH-138149)
files:
A Misc/NEWS.d/next/Library/2025-08-25-22-38-03.gh-issue-134716.kyYKeX.rst
M Doc/library/warnings.rst
M Doc/using/cmdline.rst
M Doc/whatsnew/3.15.rst
M Lib/_py_warnings.py
M Lib/test/test_warnings/__init__.py
diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst
index b6392450a1722f..5b17bd009b36e7 100644
--- a/Doc/library/warnings.rst
+++ b/Doc/library/warnings.rst
@@ -159,8 +159,10 @@ the disposition of the match. Each entry is a tuple of
the form (*action*,
* *message* is a string containing a regular expression that the start of
the warning message must match, case-insensitively. In :option:`-W` and
- :envvar:`PYTHONWARNINGS`, *message* is a literal string that the start of the
- warning message must contain (case-insensitively), ignoring any whitespace at
+ :envvar:`PYTHONWARNINGS`, if *message* starts and ends with a forward slash
+ (``/``), it specifies a regular expression as above;
+ otherwise it is a literal string that the start of the
+ warning message must match (case-insensitively), ignoring any whitespace at
the start or end of *message*.
* *category* is a class (a subclass of :exc:`Warning`) of which the warning
@@ -168,7 +170,9 @@ the disposition of the match. Each entry is a tuple of the
form (*action*,
* *module* is a string containing a regular expression that the start of the
fully qualified module name must match, case-sensitively. In :option:`-W`
and
- :envvar:`PYTHONWARNINGS`, *module* is a literal string that the
+ :envvar:`PYTHONWARNINGS`, if *module* starts and ends with a forward slash
+ (``/``), it specifies a regular expression as above;
+ otherwise it is a literal string that the
fully qualified module name must be equal to (case-sensitively), ignoring any
whitespace at the start or end of *module*.
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst
index 3f8b52e2345b25..74c18c2a6ede9c 100644
--- a/Doc/using/cmdline.rst
+++ b/Doc/using/cmdline.rst
@@ -479,8 +479,10 @@ Miscellaneous options
The *action* field is as explained above but only applies to warnings that
match the remaining fields.
- The *message* field must match the whole warning message; this match is
- case-insensitive.
+ The *message* field must match the start of the warning message;
+ this match is case-insensitive.
+ If it starts and ends with a forward slash (``/``), it specifies
+ a regular expression, otherwise it specifies a literal string.
The *category* field matches the warning category
(ex: ``DeprecationWarning``). This must be a class name; the match test
@@ -489,6 +491,10 @@ Miscellaneous options
The *module* field matches the (fully qualified) module name; this match is
case-sensitive.
+ If it starts and ends with a forward slash (``/``), it specifies
+ a regular expression that the start of the fully qualified module name
+ must match, otherwise it specifies a literal string that the fully
+ qualified module name must be equal to.
The *lineno* field matches the line number, where zero matches all line
numbers and is thus equivalent to an omitted line number.
@@ -506,6 +512,9 @@ Miscellaneous options
See :ref:`warning-filter` and :ref:`describing-warning-filters` for more
details.
+ .. versionchanged:: next
+ Added regular expression support for *message* and *module*.
+
.. option:: -x
@@ -980,6 +989,9 @@ conflict.
See :ref:`warning-filter` and :ref:`describing-warning-filters` for more
details.
+ .. versionchanged:: next
+ Added regular expression support for *message* and *module*.
+
.. envvar:: PYTHONFAULTHANDLER
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index ac09c57441e540..dc16c944886bd0 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -273,6 +273,12 @@ Other language changes
This speeds up class creation, and helps avoid reference cycles.
(Contributed by Petr Viktorin in :gh:`135228`.)
+* The :option:`-W` option and the :envvar:`PYTHONWARNINGS` environment variable
+ can now specify regular expressions instead of literal strings to match
+ the warning message and the module name, if the corresponding field starts
+ and ends with a forward slash (``/``).
+ (Contributed by Serhiy Storchaka in :gh:`134716`.)
+
New modules
===========
diff --git a/Lib/_py_warnings.py b/Lib/_py_warnings.py
index 2e7113a637a2ac..576a17ea7b8501 100644
--- a/Lib/_py_warnings.py
+++ b/Lib/_py_warnings.py
@@ -369,9 +369,15 @@ def _setoption(arg):
if message or module:
import re
if message:
- message = re.escape(message)
+ if len(message) >= 2 and message[0] == message[-1] == '/':
+ message = message[1:-1]
+ else:
+ message = re.escape(message)
if module:
- module = re.escape(module) + r'\z'
+ if len(module) >= 2 and module[0] == module[-1] == '/':
+ module = module[1:-1]
+ else:
+ module = re.escape(module) + r'\z'
if lineno:
try:
lineno = int(lineno)
@@ -381,7 +387,23 @@ def _setoption(arg):
raise _wm._OptionError("invalid lineno %r" % (lineno,)) from None
else:
lineno = 0
- _wm.filterwarnings(action, message, category, module, lineno)
+ try:
+ _wm.filterwarnings(action, message, category, module, lineno)
+ except re.PatternError if message or module else ():
+ if message:
+ try:
+ re.compile(message)
+ except re.PatternError:
+ raise _wm._OptionError(f"invalid regular expression for "
+ f"message: {message!r}") from None
+ if module:
+ try:
+ re.compile(module)
+ except re.PatternError:
+ raise _wm._OptionError(f"invalid regular expression for "
+ f"module: {module!r}") from None
+ # Should never happen.
+ raise
# Helper for _setoption()
diff --git a/Lib/test/test_warnings/__init__.py
b/Lib/test/test_warnings/__init__.py
index 256713365286c2..260fae8fe243b6 100644
--- a/Lib/test/test_warnings/__init__.py
+++ b/Lib/test/test_warnings/__init__.py
@@ -755,6 +755,10 @@ def test_improper_input(self):
self.module._setoption('ignore::===')
with self.assertRaisesRegex(self.module._OptionError, 'Wärning'):
self.module._setoption('ignore::Wärning')
+ with self.assertRaisesRegex(self.module._OptionError, 'message'):
+ self.module._setoption('ignore:/?/:Warning')
+ with self.assertRaisesRegex(self.module._OptionError, 'module'):
+ self.module._setoption('ignore::Warning:/?/')
self.module._setoption('error::Warning::0')
self.assertRaises(UserWarning, self.module.warn, 'convert to
error')
@@ -769,6 +773,31 @@ def test_import_from_module(self):
with self.assertRaises(TestWarning):
self.module.warn('test warning', TestWarning)
+ def test_message(self):
+ # Match prefix, case-insensitive.
+ with self.module.catch_warnings():
+ self.module._setoption('error:TEST WARN:UserWarning')
+ with self.assertRaises(UserWarning):
+ self.module.warn('Test Warning')
+ with self.module.catch_warnings():
+ self.module._setoption(r'error:/TE.*WARN/:UserWarning')
+ with self.assertRaises(UserWarning):
+ self.module.warn('Test Warning')
+
+ def test_module(self):
+ with self.module.catch_warnings():
+ self.module._setoption(f'error::UserWarning:{__name__}')
+ with self.assertRaises(UserWarning):
+ self.module.warn('test warning')
+ # Only full match.
+ self.module._setoption(f'ignore::UserWarning:{__name__[:-2]}')
+ with self.assertRaises(UserWarning):
+ self.module.warn('test warning')
+ with self.module.catch_warnings():
+
self.module._setoption(f'error::UserWarning:/{re.escape(__name__[:-2])}./')
+ with self.assertRaises(UserWarning):
+ self.module.warn('test warning')
+
class CWCmdLineTests(WCmdLineTests, unittest.TestCase):
module = c_warnings
diff --git
a/Misc/NEWS.d/next/Library/2025-08-25-22-38-03.gh-issue-134716.kyYKeX.rst
b/Misc/NEWS.d/next/Library/2025-08-25-22-38-03.gh-issue-134716.kyYKeX.rst
new file mode 100644
index 00000000000000..8a65080973a19e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-08-25-22-38-03.gh-issue-134716.kyYKeX.rst
@@ -0,0 +1,2 @@
+Add support of regular expressions in the :option:`-W` option and the
+:envvar:`PYTHONWARNINGS` environment variable.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]