]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #16382: Improve exception message of warnings.warn() for bad category.
authorBerker Peksag <berker.peksag@gmail.com>
Fri, 11 Jul 2014 16:50:25 +0000 (19:50 +0300)
committerBerker Peksag <berker.peksag@gmail.com>
Fri, 11 Jul 2014 16:50:25 +0000 (19:50 +0300)
Initial patch by Phil Elson.

Lib/test/test_warnings.py
Lib/warnings.py
Misc/NEWS
Python/_warnings.c

index cf7f747753c011c0d794cd1d66d6376fd667efbc..cd3288b6b596e95b7bdb35897b2b9e25fac618ce 100644 (file)
@@ -370,6 +370,41 @@ class WarnTests(BaseTest):
         with self.assertRaises(ValueError):
             self.module.warn(BadStrWarning())
 
+    def test_warning_classes(self):
+        class MyWarningClass(Warning):
+            pass
+
+        class NonWarningSubclass:
+            pass
+
+        # passing a non-subclass of Warning should raise a TypeError
+        with self.assertRaises(TypeError) as cm:
+            self.module.warn('bad warning category', '')
+        self.assertIn('category must be a Warning subclass, not ',
+                      str(cm.exception))
+
+        with self.assertRaises(TypeError) as cm:
+            self.module.warn('bad warning category', NonWarningSubclass)
+        self.assertIn('category must be a Warning subclass, not ',
+                      str(cm.exception))
+
+        # check that warning instances also raise a TypeError
+        with self.assertRaises(TypeError) as cm:
+            self.module.warn('bad warning category', MyWarningClass())
+        self.assertIn('category must be a Warning subclass, not ',
+                      str(cm.exception))
+
+        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))
+
+        with self.assertWarns(MyWarningClass) as cm:
+            self.module.warn('good warning category', MyWarningClass)
+        self.assertIsInstance(cm.warning, Warning)
 
 class CWarnTests(WarnTests, unittest.TestCase):
     module = c_warnings
index a427e3510ecaaa6dadeb2a4e957bb6d4880576c7..f37b8a771aa6c966f8410deebe41b45bb9e76ae8 100644 (file)
@@ -162,7 +162,9 @@ def warn(message, category=None, stacklevel=1):
     # Check category argument
     if category is None:
         category = UserWarning
-    assert issubclass(category, Warning)
+    if not (isinstance(category, type) and issubclass(category, Warning)):
+        raise TypeError("category must be a Warning subclass, "
+                        "not '{:s}'".format(type(category).__name__))
     # Get context information
     try:
         caller = sys._getframe(stacklevel)
index 16f0e6d43444d2c9456d8a9e9493655d4740723c..2d093366a67b720e0c355bc52ecc67616c4cc79f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -108,6 +108,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #16382: Improve exception message of warnings.warn() for bad
+  category. Initial patch by Phil Elson.
+
 - Issue #21932: os.read() now uses a :c:func:`Py_ssize_t` type instead of
   :c:type:`int` for the size to support reading more than 2 GB at once. On
   Windows, the size is truncted to INT_MAX. As any call to os.read(), the OS
index 6013d7d7d48c055da3d8fdabc313469efe4f3a8d..363c1f29bb5ab813c7dfb61437ac039ca55fdce9 100644 (file)
@@ -619,16 +619,17 @@ get_category(PyObject *message, PyObject *category)
 
     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");
+    /* category is not a subclass of PyExc_Warning or
+       PyObject_IsSubclass raised an error */
+    if (rc == -1 || rc == 0) {
+        PyErr_Format(PyExc_TypeError,
+                     "category must be a Warning subclass, not '%s'",
+                     Py_TYPE(category)->tp_name);
         return NULL;
     }