diff -r 9f464eff218a Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py Wed Oct 31 12:03:48 2012 +0200 +++ b/Lib/test/test_warnings.py Thu Nov 01 13:22:25 2012 +0000 @@ -359,6 +359,27 @@ with self.assertRaises(ValueError): self.module.warn(BadStrWarning()) + def test_warning_classes(self): + class MyWarningClass(Warning): + pass + + # passing a non-subclass of Warning should raise a ValueError + with self.assertRaises(ValueError): + self.module.warn('bad warning category', '') + # check that warning instances also raise a ValueError + with self.assertRaises(ValueError): + self.module.warn('bad warning category', MyWarningClass()) + + with warnings_state(self.module): + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + + self.module.warn('good warning category', MyWarningClass) + self.assertEqual(str(w[-1].message), 'good warning category') + + self.module.warn('good warning category', None) + self.assertEqual(str(w[-1].message), 'good warning category') + class CWarnTests(BaseTest, WarnTests): module = c_warnings diff -r 9f464eff218a Lib/warnings.py --- a/Lib/warnings.py Wed Oct 31 12:03:48 2012 +0200 +++ b/Lib/warnings.py Thu Nov 01 13:22:25 2012 +0000 @@ -165,7 +165,14 @@ # Check category argument if category is None: category = UserWarning - assert issubclass(category, Warning) + # user-error means that category could be either a class + # or some invalid object instance + try: + if not issubclass(category, Warning): + raise TypeError('') + except TypeError: + raise ValueError('category must be a subclass of {!s}.' + 'Got {!r}'.format(Warning, category)) from None # Get context information try: caller = sys._getframe(stacklevel) diff -r 9f464eff218a Python/_warnings.c --- a/Python/_warnings.c Wed Oct 31 12:03:48 2012 +0200 +++ b/Python/_warnings.c Thu Nov 01 13:22:25 2012 +0000 @@ -586,16 +586,16 @@ if (rc == 1) category = (PyObject*)message->ob_type; - else if (category == NULL) + else if (category == NULL || category == Py_None) category = PyExc_UserWarning; /* Validate category. */ rc = PyObject_IsSubclass(category, PyExc_Warning); - if (rc == -1) - return NULL; - if (rc == 0) { - PyErr_SetString(PyExc_ValueError, - "category is not a subclass of Warning"); + /* either not a subclass OR an error from IsSubclass */ + if (rc == -1 || rc == 0) { + PyErr_Format(PyExc_ValueError, + "category must be a subclass of %S. Got %R.", + PyExc_Warning, category); return NULL; }