summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Panter <vadmium+py@gmail.com>2016-05-26 09:10:55 (GMT)
committerMartin Panter <vadmium+py@gmail.com>2016-05-26 09:10:55 (GMT)
commit43593a1892b73754e509713799a043ac756ae1e1 (patch)
tree1f4a2dbb7b86019c9dacc445e25877ce4a5bc8df
parent46f50726a0047ae81d478c3a206f587b8f35ed08 (diff)
downloadcpython-43593a1892b73754e509713799a043ac756ae1e1.zip
cpython-43593a1892b73754e509713799a043ac756ae1e1.tar.gz
cpython-43593a1892b73754e509713799a043ac756ae1e1.tar.bz2
Issue #18383: Avoid adding duplicate filters when warnings is reloaded
Based on patch by Alex Shkop.
-rw-r--r--Lib/test/test_warnings/__init__.py47
-rw-r--r--Lib/warnings.py26
-rw-r--r--Misc/NEWS3
3 files changed, 65 insertions, 11 deletions
diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py
index fffadad..712f9cd 100644
--- a/Lib/test/test_warnings/__init__.py
+++ b/Lib/test/test_warnings/__init__.py
@@ -265,6 +265,53 @@ class FilterTests(BaseTest):
self.module.warn_explicit(UserWarning("b"), None, "f.py", 42)
self.assertEqual(str(w[-1].message), "b")
+ def test_filterwarnings_duplicate_filters(self):
+ with original_warnings.catch_warnings(module=self.module):
+ self.module.resetwarnings()
+ self.module.filterwarnings("error", category=UserWarning)
+ self.assertEqual(len(self.module.filters), 1)
+ self.module.filterwarnings("ignore", category=UserWarning)
+ self.module.filterwarnings("error", category=UserWarning)
+ self.assertEqual(
+ len(self.module.filters), 2,
+ "filterwarnings inserted duplicate filter"
+ )
+ self.assertEqual(
+ self.module.filters[0][0], "error",
+ "filterwarnings did not promote filter to "
+ "the beginning of list"
+ )
+
+ def test_simplefilter_duplicate_filters(self):
+ with original_warnings.catch_warnings(module=self.module):
+ self.module.resetwarnings()
+ self.module.simplefilter("error", category=UserWarning)
+ self.assertEqual(len(self.module.filters), 1)
+ self.module.simplefilter("ignore", category=UserWarning)
+ self.module.simplefilter("error", category=UserWarning)
+ self.assertEqual(
+ len(self.module.filters), 2,
+ "simplefilter inserted duplicate filter"
+ )
+ self.assertEqual(
+ self.module.filters[0][0], "error",
+ "simplefilter did not promote filter to the beginning of list"
+ )
+ def test_append_duplicate(self):
+ with original_warnings.catch_warnings(module=self.module,
+ record=True) as w:
+ self.module.resetwarnings()
+ self.module.simplefilter("ignore")
+ self.module.simplefilter("error", append=True)
+ self.module.simplefilter("ignore", append=True)
+ self.module.warn("test_append_duplicate", category=UserWarning)
+ self.assertEqual(len(self.module.filters), 2,
+ "simplefilter inserted duplicate filter"
+ )
+ self.assertEqual(len(w), 0,
+ "appended duplicate changed order of filters"
+ )
+
class CFilterTests(FilterTests, unittest.TestCase):
module = c_warnings
diff --git a/Lib/warnings.py b/Lib/warnings.py
index dfa13ee..c6631fc 100644
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -56,13 +56,8 @@ def filterwarnings(action, message="", category=Warning, module="", lineno=0,
assert isinstance(module, str), "module must be a string"
assert isinstance(lineno, int) and lineno >= 0, \
"lineno must be an int >= 0"
- item = (action, re.compile(message, re.I), category,
- re.compile(module), lineno)
- if append:
- filters.append(item)
- else:
- filters.insert(0, item)
- _filters_mutated()
+ _add_filter(action, re.compile(message, re.I), category,
+ re.compile(module), lineno, append=append)
def simplefilter(action, category=Warning, lineno=0, append=False):
"""Insert a simple entry into the list of warnings filters (at the front).
@@ -78,11 +73,20 @@ def simplefilter(action, category=Warning, lineno=0, append=False):
"once"), "invalid action: %r" % (action,)
assert isinstance(lineno, int) and lineno >= 0, \
"lineno must be an int >= 0"
- item = (action, None, category, None, lineno)
- if append:
- filters.append(item)
- else:
+ _add_filter(action, None, category, None, lineno, append=append)
+
+def _add_filter(*item, append):
+ # Remove possible duplicate filters, so new one will be placed
+ # in correct place. If append=True and duplicate exists, do nothing.
+ if not append:
+ try:
+ filters.remove(item)
+ except ValueError:
+ pass
filters.insert(0, item)
+ else:
+ if item not in filters:
+ filters.append(item)
_filters_mutated()
def resetwarnings():
diff --git a/Misc/NEWS b/Misc/NEWS
index bf9843f..4918265 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -126,6 +126,9 @@ Core and Builtins
Library
-------
+- Issue #18383: Avoid creating duplicate filters when using filterwarnings
+ and simplefilter. Based on patch by Alex Shkop.
+
- Issue #27057: Fix os.set_inheritable() on Android, ioctl() is blocked by
SELinux and fails with EACCESS. The function now falls back to fcntl().
Patch written by MichaƂ Bednarski.