Issue #18383: Avoid adding duplicate filters when warnings is reloaded

Based on patch by Alex Shkop.
This commit is contained in:
Martin Panter 2016-05-26 09:10:55 +00:00
parent 46f50726a0
commit 43593a1892
3 changed files with 65 additions and 11 deletions

View File

@ -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

View File

@ -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():

View File

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