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 22 10:40:08 2012 +0000 @@ -359,6 +359,24 @@ 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 TypeError + with self.assertRaises(TypeError): + self.module.warn('bad warning category', '') + + # check that warning instances also raise a TypeError + with self.assertRaises(TypeError): + self.module.warn('bad warning category', MyWarningClass()) + + with self.assertWarnsRegex(MyWarningClass, 'good warning category'): + self.module.warn('good warning category', MyWarningClass) + + with self.assertWarnsRegex(Warning, 'good warning category'): + self.module.warn('good warning category', None) + 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 22 10:40:08 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 TypeError('category must be a Warning subclass. ' + 'Got {!r}.'.format(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 22 10:40:08 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_TypeError, + "category must be a Warning subclass. Got %R.", + category); return NULL; }