mirror of
https://github.com/python/cpython.git
synced 2025-11-24 12:20:42 +00:00
gh-134716: Support regular expressions in -W and PYTHONWARNINGS (GH-138149)
Some checks are pending
Tests / Windows MSI (push) Blocked by required conditions
Tests / Change detection (push) Waiting to run
Tests / Docs (push) Blocked by required conditions
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / Ubuntu SSL tests with AWS-LC (push) Blocked by required conditions
Tests / Android (aarch64) (push) Blocked by required conditions
Tests / Android (x86_64) (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / Sanitizers (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/jit (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run
Some checks are pending
Tests / Windows MSI (push) Blocked by required conditions
Tests / Change detection (push) Waiting to run
Tests / Docs (push) Blocked by required conditions
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / Ubuntu SSL tests with AWS-LC (push) Blocked by required conditions
Tests / Android (aarch64) (push) Blocked by required conditions
Tests / Android (x86_64) (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / Sanitizers (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/jit (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run
This commit is contained in:
parent
530ddd3e06
commit
cf9ef73121
6 changed files with 83 additions and 8 deletions
|
|
@ -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*.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
===========
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -755,6 +755,10 @@ class WCmdLineTests(BaseTest):
|
|||
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 @@ class WCmdLineTests(BaseTest):
|
|||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Add support of regular expressions in the :option:`-W` option and the
|
||||
:envvar:`PYTHONWARNINGS` environment variable.
|
||||
Loading…
Add table
Add a link
Reference in a new issue