From e43adf8955a362dc6122fa6da31a7548c235fef3 Mon Sep 17 00:00:00 2001 From: Daniel Shimon Date: Wed, 12 Jul 2023 13:51:25 +0000 Subject: [PATCH 1/3] gh-93343: Expand warning filter examples Add examples of warning filters and the difference between programatic and environmental filters. --- Doc/library/warnings.rst | 28 +++++++++++++++++++ ...3-07-11-08-46-13.gh-issue-93343.fw_eyw.rst | 2 ++ 2 files changed, 30 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2023-07-11-08-46-13.gh-issue-93343.fw_eyw.rst diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index 884de08eab1b16..43de9790d2aab2 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -214,6 +214,34 @@ Some examples:: ignore,default:::mymodule # Only report warnings triggered by "mymodule" error:::mymodule # Convert warnings to errors in "mymodule" +.. _warning-filter-examples: + +Warning Filter Examples +~~~~~~~~~~~~~~~~~~~~~~~ + +Here are some complex examples for filtering warnings. + +Note that :func:`filterwarnings` filters have subtle differences +from :option:`-W` and :envvar:`PYTHONWARNINGS` regarding the *message* and *module* +parts of the filter (as described in :ref:`warning-filter`). + +:: + + filterwarnings("ignore", message=".*generic", module=r"yourmodule\.submodule") + # Ignore warnings in "yourmodule.submodule" which contain "generic" + filterwarnings("ignore", message="generic", module=r"yourmodule\.submodule") + # Ignore warnings in "yourmodule.submodule" which START with "generic" + filterwarnings("ignore", module="yourmodule.*") + # Ignore all warnings in "yourmodule" and its submodules + + -W "ignore:generic::yourmodule.submodule:" + # Ignore warnings in "yourmodule.submodule" which START with "generic" + # (but not those containing it). + # Also note that the '.' in the module does not need to be escaped + # since it is not a regex. + -W "ignore:::yourmodule:" + # Ignore all warnings in "yourmodule", but NOT in its submodules + .. _default-warning-filter: diff --git a/Misc/NEWS.d/next/Documentation/2023-07-11-08-46-13.gh-issue-93343.fw_eyw.rst b/Misc/NEWS.d/next/Documentation/2023-07-11-08-46-13.gh-issue-93343.fw_eyw.rst new file mode 100644 index 00000000000000..6dae32598cb5aa --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2023-07-11-08-46-13.gh-issue-93343.fw_eyw.rst @@ -0,0 +1,2 @@ +Add examples of warning filters and the difference between programmatic and +environmental filters. From f3684a6d8c81b75de1eb90194102309c32b2847f Mon Sep 17 00:00:00 2001 From: Daniel Shimon Date: Wed, 12 Jul 2023 14:40:33 +0000 Subject: [PATCH 2/3] gh-93343: Add warning filters tests --- Lib/test/test_warnings/__init__.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 9e680c847dab7b..e0eb8de47e0c4d 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -312,6 +312,18 @@ def test_message_matching(self): self.module.warn("something completely different") self.assertEqual(w, []) + def test_message_matching_regex(self): + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + self.module.simplefilter("ignore", UserWarning) + self.module.filterwarnings("error", ".*match", UserWarning) + self.assertRaises(UserWarning, self.module.warn, "match") + self.assertRaises(UserWarning, self.module.warn, "match prefix") + self.assertRaises(UserWarning, self.module.warn, "suffix match") + self.assertEqual(w, []) + self.module.warn("not a m4tch") + self.assertEqual(w, []) + def test_mutate_filter_list(self): class X: def match(self, a): @@ -1202,6 +1214,18 @@ def test_single_warning(self): PYTHONDEVMODE="") self.assertEqual(stdout, b"['ignore::DeprecationWarning']") + def test_string_literals(self): + # Ensure message/module are treated as string literals + rc, stdout, stderr = assert_python_ok("-c", + "import sys, warnings; " + "sys.stdout.write(warnings.filters[0][1].pattern); " + "sys.stderr.write(warnings.filters[0][3].pattern)", + PYTHONWARNINGS="ignore:.generic::yourmodule.submodule", + PYTHONDEVMODE="") + self.assertEqual(stdout, rb"\.generic") + # '\Z' is added to the module name, so check start of pattern: + self.assertTrue(stderr.startswith(rb"yourmodule\.submodule")) + def test_comma_separated_warnings(self): rc, stdout, stderr = assert_python_ok("-c", "import sys; sys.stdout.write(str(sys.warnoptions))", From f16ae2dbfc6b2063c4a6cbe0ad0e606dcbb2994b Mon Sep 17 00:00:00 2001 From: Daniel Shimon Date: Wed, 7 May 2025 00:08:32 +0200 Subject: [PATCH 3/3] Clarify escaped dots in regexes --- Doc/library/warnings.rst | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index 43de9790d2aab2..3219d15dab55f3 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -224,23 +224,28 @@ Here are some complex examples for filtering warnings. Note that :func:`filterwarnings` filters have subtle differences from :option:`-W` and :envvar:`PYTHONWARNINGS` regarding the *message* and *module* parts of the filter (as described in :ref:`warning-filter`). +Mainly, 'message' and 'module' are regular expressions in the former, +but literal strings in the latter two. :: filterwarnings("ignore", message=".*generic", module=r"yourmodule\.submodule") - # Ignore warnings in "yourmodule.submodule" which contain "generic" + # Ignore warnings in "yourmodule.submodule" which contain "generic". + # Note that the '.' in 'message' marks any character and in 'module' it is escaped, + # in order to match a literal dot character. filterwarnings("ignore", message="generic", module=r"yourmodule\.submodule") - # Ignore warnings in "yourmodule.submodule" which START with "generic" + # Ignore warnings in "yourmodule.submodule" which START with "generic". filterwarnings("ignore", module="yourmodule.*") - # Ignore all warnings in "yourmodule" and its submodules + # Ignore all warnings in "yourmodule" and its submodules. + # Note that the '.' in 'module' marks any character so is not escaped. -W "ignore:generic::yourmodule.submodule:" # Ignore warnings in "yourmodule.submodule" which START with "generic" # (but not those containing it). - # Also note that the '.' in the module does not need to be escaped - # since it is not a regex. + # Also note that the '.' in the module part does not need to be escaped + # since it is not a regular expression. -W "ignore:::yourmodule:" - # Ignore all warnings in "yourmodule", but NOT in its submodules + # Ignore all warnings in "yourmodule", but NOT in its submodules. .. _default-warning-filter: