Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Lib/test/test_warnings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,29 @@ class NonWarningSubclass:
self.module.warn('good warning category', MyWarningClass)
self.assertIsInstance(cm.warning, Warning)

def test_simplefilter_invalid_category(self):
class MyWarningClass(Warning):
pass

class NonWarningSubclass:
pass

msg_regex = 'category must be a Warning subclass, not (.*)'

with self.assertRaisesRegex(TypeError, msg_regex):
self.module.simplefilter('always', '')

with self.assertRaisesRegex(TypeError, msg_regex):
self.module.simplefilter('always', NonWarningSubclass)

with self.assertRaisesRegex(TypeError, msg_regex):
self.module.simplefilter('always', MyWarningClass())

with original_warnings.catch_warnings(module=self.module, record=True) as w:
self.module.simplefilter('always', MyWarningClass)
self.assertEqual(len(w), 0)


class CWarnTests(WarnTests, unittest.TestCase):
module = c_warnings

Expand Down
6 changes: 5 additions & 1 deletion Lib/unittest/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,11 @@ def __enter__(self):
v.__warningregistry__ = {}
self.warnings_manager = warnings.catch_warnings(record=True)
self.warnings = self.warnings_manager.__enter__()
warnings.simplefilter("always", self.expected)
if isinstance(self.expected, tuple):
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be done in a separate PR, but issubclass does not support a tuple. However, the type of the category parameter of warnings.simplefilter doesn't really indicate that it should support a tuple anyway.
I could also change it so that the issubclass checks for tuples before doing the check, but I'm not sure if that is actually correct.

Let me know!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that there may be a third-party code which uses simplefilter() with a tuple. Instead of changing unittest, it is better to make the argument check in simplefilter() more lenient.

It would be nice to make also filterwarnings() accepting a tuple.

for expected in self.expected:
warnings.simplefilter("always", expected)
else:
warnings.simplefilter("always", self.expected)
return self

def __exit__(self, exc_type, exc_value, tb):
Expand Down
3 changes: 3 additions & 0 deletions Lib/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ 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"
if not (isinstance(category, type) and issubclass(category, Warning)):
raise TypeError('category must be a Warning subclass, '
'not {!r}'.format(category))
_add_filter(action, None, category, None, lineno, append=append)

def _add_filter(*item, append):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Validate the category of warnings.simplefilter sooner