Skip to content

Commit b55ea9e

Browse files
committed
Improve type error messages. Refs #330
1 parent 1784361 commit b55ea9e

File tree

5 files changed

+37
-6
lines changed

5 files changed

+37
-6
lines changed

src/greenlet/greenlet_exceptions.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#define PY_SSIZE_T_CLEAN
55
#include <Python.h>
66
#include <stdexcept>
7+
#include <string>
78

89
#ifdef __clang__
910
# pragma clang diagnostic push
@@ -25,6 +26,13 @@ namespace greenlet {
2526
{
2627
PyErr_SetString(exc_kind, msg);
2728
}
29+
PyErrOccurred(PyObject* exc_kind, const std::string msg)
30+
: std::runtime_error(msg)
31+
{
32+
// This copies the c_str, so we don't have any lifetime
33+
// issues to worry about.
34+
PyErr_SetString(exc_kind, msg.c_str());
35+
}
2836
};
2937

3038
class TypeError : public PyErrOccurred
@@ -34,6 +42,10 @@ namespace greenlet {
3442
: PyErrOccurred(PyExc_TypeError, what)
3543
{
3644
}
45+
TypeError(const std::string what)
46+
: PyErrOccurred(PyExc_TypeError, what)
47+
{
48+
}
3749
};
3850

3951
class ValueError : public PyErrOccurred

src/greenlet/greenlet_internal.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "greenlet_allocator.hpp"
2222

2323
#include <vector>
24+
#include <string>
2425

2526
#define GREENLET_MODULE
2627
struct _greenlet;
@@ -45,7 +46,9 @@ greenlet::refs::MainGreenletExactChecker(void *p)
4546
}
4647
// We control the class of the main greenlet exactly.
4748
if (Py_TYPE(p) != &PyGreenlet_Type) {
48-
throw greenlet::TypeError("Expected a greenlet");
49+
std::string err("MainGreenlet: Expected exactly a greenlet, not a ");
50+
err += Py_TYPE(p)->tp_name;
51+
throw greenlet::TypeError(err);
4952
}
5053

5154
// Greenlets from dead threads no longer respond to main() with a
@@ -56,7 +59,9 @@ greenlet::refs::MainGreenletExactChecker(void *p)
5659
return;
5760
}
5861
if (!dynamic_cast<MainGreenlet*>(g)) {
59-
throw greenlet::TypeError("Expected a main greenlet");
62+
std::string err("MainGreenlet: Expected exactly a main greenlet, not a ");
63+
err += Py_TYPE(p)->tp_name;
64+
throw greenlet::TypeError(err);
6065
}
6166
}
6267

src/greenlet/greenlet_refs.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ namespace greenlet
5757
}
5858

5959
if (!PyObject_TypeCheck(p, &PyGreenlet_Type)) {
60-
throw TypeError("Expected a greenlet");
60+
std::string err("GreenletChecker: Expected any type of greenlet, not ");
61+
err += Py_TYPE(p)->tp_name;
62+
throw TypeError(err);
6163
}
6264
}
6365

src/greenlet/tests/test_cpp.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,17 @@ def _do_test_unhandled_exception(self, target):
5454
# https://devblogs.microsoft.com/oldnewthing/20110519-00/?p=10623
5555
# and
5656
# https://docs.microsoft.com/en-us/previous-versions/k089yyh0(v=vs.140)?redirectedfrom=MSDN
57-
expected_exit = -signal.SIGABRT if not WIN else 3
58-
self.assertEqual(p.exitcode, expected_exit)
57+
expected_exit = (
58+
-signal.SIGABRT,
59+
# But beginning on Python 3.11, the faulthandler
60+
# that prints the C backtraces sometimes segfaults after
61+
# reporting the exception but before printing the stack.
62+
# This has only been seen on linux/gcc.
63+
-signal.SIGSEGV
64+
) if not WIN else (
65+
3,
66+
)
67+
self.assertIn(p.exitcode, expected_exit)
5968

6069
def test_unhandled_exception_aborts(self):
6170
# verify that plain unhandled throw aborts

src/greenlet/tests/test_greenlet.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,10 @@ def check(glet):
972972
for p in None, 1, self, "42":
973973
with self.assertRaises(TypeError) as exc:
974974
glet.parent = p
975-
self.assertEqual(str(exc.exception), "Expected a greenlet")
975+
976+
self.assertEqual(
977+
str(exc.exception),
978+
"GreenletChecker: Expected any type of greenlet, not " + type(p).__name__)
976979

977980
# First, not running
978981
g = greenlet(bg)

0 commit comments

Comments
 (0)