[Python-checkins] cpython: Issue #16382: Improve exception message of warnings.warn() for bad category.

berker.peksag python-checkins at python.org
Fri Jul 11 18:50:28 CEST 2014


http://hg.python.org/cpython/rev/c4a86fe52006
changeset:   91648:c4a86fe52006
user:        Berker Peksag <berker.peksag at gmail.com>
date:        Fri Jul 11 19:50:25 2014 +0300
summary:
  Issue #16382: Improve exception message of warnings.warn() for bad category.

Initial patch by Phil Elson.

files:
  Lib/test/test_warnings.py |  35 +++++++++++++++++++++++++++
  Lib/warnings.py           |   4 ++-
  Misc/NEWS                 |   3 ++
  Python/_warnings.c        |  13 +++++----
  4 files changed, 48 insertions(+), 7 deletions(-)


diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
--- a/Lib/test/test_warnings.py
+++ b/Lib/test/test_warnings.py
@@ -370,6 +370,41 @@
         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
diff --git a/Lib/warnings.py b/Lib/warnings.py
--- a/Lib/warnings.py
+++ b/Lib/warnings.py
@@ -162,7 +162,9 @@
     # 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)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -108,6 +108,9 @@
 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
diff --git a/Python/_warnings.c b/Python/_warnings.c
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -619,16 +619,17 @@
 
     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;
     }
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list