+static PyObject *getExceptionMessage(PyObject *exceptionType, PyObject *exception, PyObject *traceback) {
+ PyObject *formatExc = NULL, *args = NULL;
+ PyObject *tracebackModule = PyImport_ImportModule("traceback");
+ if (!tracebackModule) {
+ fputs("Python: No traceback module\n", stderr);
+ return NULL;
+ }
+
+ PyErr_NormalizeException(&exceptionType, &exception, &traceback);
+
+ if (exception && traceback) {
+ formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception");
+ args = PyTuple_Pack(3, exceptionType, exception, traceback);
+ }
+ else if (exception) {
+ formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception_only");
+ args = PyTuple_Pack(2, exceptionType, exception);
+ }
+
+ if (formatExc != NULL && args != NULL) {
+ PyObject *result = PyObject_CallObject(formatExc, args);
+ if (!result) {
+ fputs("Python: No result from format_exception\n", stderr);
+ // Fallback to a direct string representation of the exception object
+ result = PyObject_Str(exception);
+ }
+ Py_XDECREF(args);
+ // Py_XDECREF(formatExc) - Borrowed reference
+ Py_DECREF(tracebackModule);
+
+ return result;
+ }
+ else {
+ if (!formatExc) fputs("Python: No format_exception\n", stderr);
+
+ Py_XDECREF(args);
+ // Py_XDECREF(formatExc) - Borrowed reference
+ Py_DECREF(tracebackModule);
+
+ return NULL;
+ }
+}
+
+static void throwExceptionType(JNIEnv *env, PyObject *exceptionType) {
+ PyObject *ty_name = exceptionType ? PyObject_GetAttrString(exceptionType, "__name__") : NULL;
+ PyObject *str = ty_name ? PyUnicode_AsEncodedString(ty_name, "utf-8", "ignore") : NULL;
+
+ throwPythonException(env, str ? PyBytes_AsString(str) : "Internal error - no exception type");
+
+ Py_XDECREF(str);
+ Py_XDECREF(ty_name);
+}
+