diff -r bff88c866886 Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py Thu Apr 09 10:27:25 2015 +0200 +++ b/Lib/test/test_warnings.py Tue Apr 14 09:11:34 2015 +0300 @@ -247,6 +247,25 @@ self.assertEqual(str(w[-1].message), text) self.assertTrue(w[-1].category is UserWarning) + def test_duplicate_filters(self): + with original_warnings.catch_warnings(module=self.module): + initial_len = len(self.module.filters) + self.module.filterwarnings("error", category=UserWarning) + self.assertEqual(len(self.module.filters), initial_len + 1) + self.module.filterwarnings("ignore", category=UserWarning) + self.module.filterwarnings("error", category=UserWarning) + self.assertEqual(len(self.module.filters), initial_len + 2, "filterwarnings inserted duplicate filter") + self.assertEqual(self.module.filters[0][0], 'error', "filterwarnings did not promote filter to the beginning of list") + + with original_warnings.catch_warnings(module=self.module): + initial_len = len(self.module.filters) + self.module.simplefilter("error", category=UserWarning) + self.assertEqual(len(self.module.filters), initial_len + 1) + self.module.simplefilter("ignore", category=UserWarning) + self.module.simplefilter("error", category=UserWarning) + self.assertEqual(len(self.module.filters), initial_len + 2, "simplefilter inserted duplicate filter") + self.assertEqual(self.module.filters[0][0], 'error', "simplefilter did not promote filter to the beginning of list") + class CFilterTests(FilterTests, unittest.TestCase): module = c_warnings @@ -456,20 +475,20 @@ self.assertIn('category must be a Warning subclass, not ', str(cm.exception)) - with original_warnings.catch_warnings(module=self.module): + with original_warnings.catch_warnings(module=self.module, record=True) as warns: self.module.resetwarnings() self.module.filterwarnings('default') - with self.assertWarns(MyWarningClass) as cm: - self.module.warn('good warning category', MyWarningClass) - self.assertEqual('good warning category', str(cm.warning)) - with self.assertWarns(UserWarning) as cm: - self.module.warn('good warning category', None) - self.assertEqual('good warning category', str(cm.warning)) + self.module.warn('good warning category', MyWarningClass) + self.assertIsInstance(warns[-1].message, MyWarningClass) + self.assertEqual('good warning category', str(warns[-1].message)) - with self.assertWarns(MyWarningClass) as cm: - self.module.warn('good warning category', MyWarningClass) - self.assertIsInstance(cm.warning, Warning) + self.module.warn('good warning category', None) + self.assertIsInstance(warns[-1].message, UserWarning) + self.assertEqual('good warning category', str(warns[-1].message)) + + self.module.warn('good warning category', MyWarningClass) + self.assertIsInstance(warns[-1].message, Warning) class CWarnTests(WarnTests, unittest.TestCase): module = c_warnings diff -r bff88c866886 Lib/warnings.py --- a/Lib/warnings.py Thu Apr 09 10:27:25 2015 +0200 +++ b/Lib/warnings.py Tue Apr 14 09:11:34 2015 +0300 @@ -52,6 +52,12 @@ "lineno must be an int >= 0" item = (action, re.compile(message, re.I), category, re.compile(module), lineno) + + # Remove possible duplicate filters, so new one will be placed in correct place + try: + filters.remove(item) + except ValueError: + pass if append: filters.append(item) else: @@ -73,6 +79,12 @@ assert isinstance(lineno, int) and lineno >= 0, \ "lineno must be an int >= 0" item = (action, None, category, None, lineno) + + # Remove possible duplicate filters, so new one will be placed in correct place + try: + filters.remove(item) + except ValueError: + pass if append: filters.append(item) else: