summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Madden <jamadden@gmail.com>2023-01-28 07:09:26 -0600
committerJason Madden <jamadden@gmail.com>2023-01-28 07:55:06 -0600
commitb55ea9e05172e5cfd91ca00dda38895024104ce1 (patch)
tree469fe59c6124d5557a0b8d716927b8a302550752
parent1784361e97545c520384cfe50796136c337d1763 (diff)
downloadgreenlet-b55ea9e05172e5cfd91ca00dda38895024104ce1.tar.gz
Improve type error messages. Refs #330
-rw-r--r--src/greenlet/greenlet_exceptions.hpp12
-rw-r--r--src/greenlet/greenlet_internal.hpp9
-rw-r--r--src/greenlet/greenlet_refs.hpp4
-rw-r--r--src/greenlet/tests/test_cpp.py13
-rw-r--r--src/greenlet/tests/test_greenlet.py5
5 files changed, 37 insertions, 6 deletions
diff --git a/src/greenlet/greenlet_exceptions.hpp b/src/greenlet/greenlet_exceptions.hpp
index 46a63cf..697df00 100644
--- a/src/greenlet/greenlet_exceptions.hpp
+++ b/src/greenlet/greenlet_exceptions.hpp
@@ -4,6 +4,7 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdexcept>
+#include <string>
#ifdef __clang__
# pragma clang diagnostic push
@@ -25,6 +26,13 @@ namespace greenlet {
{
PyErr_SetString(exc_kind, msg);
}
+ PyErrOccurred(PyObject* exc_kind, const std::string msg)
+ : std::runtime_error(msg)
+ {
+ // This copies the c_str, so we don't have any lifetime
+ // issues to worry about.
+ PyErr_SetString(exc_kind, msg.c_str());
+ }
};
class TypeError : public PyErrOccurred
@@ -34,6 +42,10 @@ namespace greenlet {
: PyErrOccurred(PyExc_TypeError, what)
{
}
+ TypeError(const std::string what)
+ : PyErrOccurred(PyExc_TypeError, what)
+ {
+ }
};
class ValueError : public PyErrOccurred
diff --git a/src/greenlet/greenlet_internal.hpp b/src/greenlet/greenlet_internal.hpp
index c53ecc5..4f7fe6b 100644
--- a/src/greenlet/greenlet_internal.hpp
+++ b/src/greenlet/greenlet_internal.hpp
@@ -21,6 +21,7 @@
#include "greenlet_allocator.hpp"
#include <vector>
+#include <string>
#define GREENLET_MODULE
struct _greenlet;
@@ -45,7 +46,9 @@ greenlet::refs::MainGreenletExactChecker(void *p)
}
// We control the class of the main greenlet exactly.
if (Py_TYPE(p) != &PyGreenlet_Type) {
- throw greenlet::TypeError("Expected a greenlet");
+ std::string err("MainGreenlet: Expected exactly a greenlet, not a ");
+ err += Py_TYPE(p)->tp_name;
+ throw greenlet::TypeError(err);
}
// Greenlets from dead threads no longer respond to main() with a
@@ -56,7 +59,9 @@ greenlet::refs::MainGreenletExactChecker(void *p)
return;
}
if (!dynamic_cast<MainGreenlet*>(g)) {
- throw greenlet::TypeError("Expected a main greenlet");
+ std::string err("MainGreenlet: Expected exactly a main greenlet, not a ");
+ err += Py_TYPE(p)->tp_name;
+ throw greenlet::TypeError(err);
}
}
diff --git a/src/greenlet/greenlet_refs.hpp b/src/greenlet/greenlet_refs.hpp
index 36f2991..ed1ef19 100644
--- a/src/greenlet/greenlet_refs.hpp
+++ b/src/greenlet/greenlet_refs.hpp
@@ -57,7 +57,9 @@ namespace greenlet
}
if (!PyObject_TypeCheck(p, &PyGreenlet_Type)) {
- throw TypeError("Expected a greenlet");
+ std::string err("GreenletChecker: Expected any type of greenlet, not ");
+ err += Py_TYPE(p)->tp_name;
+ throw TypeError(err);
}
}
diff --git a/src/greenlet/tests/test_cpp.py b/src/greenlet/tests/test_cpp.py
index 955566b..7aaeb0b 100644
--- a/src/greenlet/tests/test_cpp.py
+++ b/src/greenlet/tests/test_cpp.py
@@ -54,8 +54,17 @@ class CPPTests(TestCase):
# https://devblogs.microsoft.com/oldnewthing/20110519-00/?p=10623
# and
# https://docs.microsoft.com/en-us/previous-versions/k089yyh0(v=vs.140)?redirectedfrom=MSDN
- expected_exit = -signal.SIGABRT if not WIN else 3
- self.assertEqual(p.exitcode, expected_exit)
+ expected_exit = (
+ -signal.SIGABRT,
+ # But beginning on Python 3.11, the faulthandler
+ # that prints the C backtraces sometimes segfaults after
+ # reporting the exception but before printing the stack.
+ # This has only been seen on linux/gcc.
+ -signal.SIGSEGV
+ ) if not WIN else (
+ 3,
+ )
+ self.assertIn(p.exitcode, expected_exit)
def test_unhandled_exception_aborts(self):
# verify that plain unhandled throw aborts
diff --git a/src/greenlet/tests/test_greenlet.py b/src/greenlet/tests/test_greenlet.py
index 6057185..3185b39 100644
--- a/src/greenlet/tests/test_greenlet.py
+++ b/src/greenlet/tests/test_greenlet.py
@@ -972,7 +972,10 @@ class TestGreenletSetParentErrors(TestCase):
for p in None, 1, self, "42":
with self.assertRaises(TypeError) as exc:
glet.parent = p
- self.assertEqual(str(exc.exception), "Expected a greenlet")
+
+ self.assertEqual(
+ str(exc.exception),
+ "GreenletChecker: Expected any type of greenlet, not " + type(p).__name__)
# First, not running
g = greenlet(bg)