Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Doc/library/warnings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,20 @@ 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
category must be a subclass in order to match.

* *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*.

Expand Down
16 changes: 14 additions & 2 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -470,8 +470,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
Expand All @@ -480,6 +482,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.
Expand All @@ -497,6 +503,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

Expand Down Expand Up @@ -971,6 +980,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

Expand Down
16 changes: 16 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,22 @@ Other language changes
This speeds up class creation, and helps avoid reference cycles.
(Contributed by Petr Viktorin in :gh:`135228`.)

* Warning filters specified by the :option:`-W` option and the
:envvar:`PYTHONWARNINGS` environment variable can now use regular
expressions for message and module.
The corresponding field must be surrounded by slashes (``/``).

The :option:`-W` option and the :envvar:`PYTHONWARNINGS` environment
variable can now specify use regular expressions for matching warning
message and module if the corresponding field starts and ends by slashes
(``/``).

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
===========
Expand Down
28 changes: 25 additions & 3 deletions Lib/_py_warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
Expand Down
29 changes: 29 additions & 0 deletions Lib/test/test_warnings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add support of regular expressions in the :option:`-W` option and the
:envvar:`PYTHONWARNINGS` environment variable.
Loading