From: tuorjr Date: Thu, 1 Dec 2016 16:31:57 +0000 (+0000) Subject: Get Python traceback output in the messages of exceptions from the pythonlink feature. X-Git-Tag: v1.31.0~10 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=f8f212403765ac5f8c4c08ab6b7d7a78c1c9a6f3;p=simantics%2Fpython.git Get Python traceback output in the messages of exceptions from the pythonlink feature. git-svn-id: https://www.simantics.org/svn/simantics-incubator/reino@1703 e36c2e66-7d30-0410-bdb2-d9e1f5a6d952 --- diff --git a/org.simantics.pythonlink.win32.x86_64/jnipython.dll b/org.simantics.pythonlink.win32.x86_64/jnipython.dll index 76fe378..7fff774 100644 Binary files a/org.simantics.pythonlink.win32.x86_64/jnipython.dll and b/org.simantics.pythonlink.win32.x86_64/jnipython.dll differ diff --git a/org.simantics.pythonlink.win32.x86_64/src/sclpy.c b/org.simantics.pythonlink.win32.x86_64/src/sclpy.c index 565b6fa..b10b36f 100644 --- a/org.simantics.pythonlink.win32.x86_64/src/sclpy.c +++ b/org.simantics.pythonlink.win32.x86_64/src/sclpy.c @@ -24,6 +24,10 @@ jint throwException( JNIEnv *env, char *className, char *message ) return (*env)->ThrowNew( env, exClass, message ); } +jint throwPythonException( JNIEnv *env, char *message ) { + return throwException( env, PYTHON_EXCEPTION, message ); +} + jint throwIllegalArgumentException( JNIEnv *env, char *message ) { return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message ); } @@ -581,7 +585,7 @@ jobjectArray pythonSequenceAsStringArray(JNIEnv *env, PyObject *seq) { (*env)->SetObjectArrayElement(env, array, i, value); } else { - throwException(env, RUNTIME_EXCEPTION, "List item not a string"); + throwPythonException(env, "List item not a string"); return NULL; } } @@ -603,7 +607,7 @@ jdoubleArray pythonSequenceAsDoubleArray(JNIEnv *env, PyObject *seq) { (*env)->SetDoubleArrayRegion(env, array, i, 1, &value); } else { - throwException(env, RUNTIME_EXCEPTION, "List item not a floating point value"); + throwPythonException(env, "List item not a floating point value"); return NULL; } } @@ -662,7 +666,7 @@ jbooleanArray pythonSequenceAsBooleanArray(JNIEnv *env, PyObject *seq) { (*env)->SetBooleanArrayRegion(env, array, i, 1, &value); } else { - throwException(env, RUNTIME_EXCEPTION, "List item not a boolean"); + throwPythonException(env, "List item not a boolean"); return NULL; } } @@ -684,7 +688,7 @@ jintArray pythonSequenceAsIntegerArray(JNIEnv *env, PyObject *seq) { (*env)->SetIntArrayRegion(env, array, i, 1, &value); } else { - throwException(env, RUNTIME_EXCEPTION, "List item not an integer"); + throwPythonException(env, "List item not an integer"); return NULL; } } @@ -706,7 +710,7 @@ jlongArray pythonSequenceAsLongArray(JNIEnv *env, PyObject *seq) { (*env)->SetLongArrayRegion(env, array, i, 1, &value); } else { - throwException(env, RUNTIME_EXCEPTION, "List item not an integer"); + throwPythonException(env, "List item not an integer"); return NULL; } } @@ -729,7 +733,7 @@ jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) { int i; if (len > JAVA_MAXINT) { - throwException(env, RUNTIME_EXCEPTION, "Array too large"); + throwPythonException(env, "Array too large"); return NULL; } @@ -872,7 +876,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDAr PyObject *module = (PyObject*)contextID; if (!hasNumpy) { - throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed"); + throwPythonException(env, "Importing numpy failed"); return; } @@ -909,11 +913,40 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePython PyObject *exceptionType = PyErr_Occurred(); if (exceptionType != NULL) { - PyObject *exception, *stackTrace; - char *message; - PyErr_Fetch(&exceptionType, &exception, &stackTrace); - message = PyUnicode_AsUTF8(exception); - throwException(env, RUNTIME_EXCEPTION, message); + PyObject *exception, *traceback; + PyErr_Fetch(&exceptionType, &exception, &traceback); + + { + PyObject *tracebackModule = PyImport_ImportModule("traceback"); + if (tracebackModule != NULL) { + PyObject *formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception"); + if (formatExc != NULL) { + PyObject *args = PyTuple_Pack(3, exceptionType, exception, traceback); + PyObject *message = PyObject_CallObject(formatExc, args); + if (message != NULL) { + PyObject *emptyStr = PyUnicode_FromString(""); + PyObject *joined = PyUnicode_Join(emptyStr, message); + char *messageStr = PyUnicode_AsUTF8(joined); + throwPythonException(env, messageStr); + Py_DECREF(joined); + Py_DECREF(emptyStr); + Py_DECREF(message); + } + else { + throwPythonException(env, "Internal error, no message"); + } + Py_DECREF(args); + Py_DECREF(formatExc); + } + else { + throwPythonException(env, "Internal error, no format_exc function"); + } + Py_DECREF(tracebackModule); + } + else { + throwPythonException(env, "Internal error, no traceback module"); + } + } } (*env)->ReleaseStringUTFChars(env, statement, utfchars); @@ -930,12 +963,12 @@ JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonS PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return 0; } if (!PyUnicode_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a string"); + throwPythonException(env, "Python variable not a string"); return 0; } @@ -952,12 +985,12 @@ JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return 0; } if (!PySequence_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence"); + throwPythonException(env, "Python variable not a sequence"); return 0; } @@ -974,12 +1007,12 @@ JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPython PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return 0; } if (!PyBool_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a boolean"); + throwPythonException(env, "Python variable not a boolean"); return 0; } @@ -993,12 +1026,12 @@ JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getP PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return 0; } if (!PySequence_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence"); + throwPythonException(env, "Python variable not a sequence"); return 0; } @@ -1015,12 +1048,12 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLon PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return 0; } if (!PyLong_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not an integer"); + throwPythonException(env, "Python variable not an integer"); return 0; } @@ -1037,12 +1070,12 @@ JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPytho PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return NULL; } if (!PySequence_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence"); + throwPythonException(env, "Python variable not a sequence"); return NULL; } @@ -1059,12 +1092,12 @@ JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPyth PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return NULL; } if (!PySequence_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence"); + throwPythonException(env, "Python variable not a sequence"); return NULL; } @@ -1081,12 +1114,12 @@ JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonD PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return 0.0; } if (!PyFloat_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a float"); + throwPythonException(env, "Python variable not a float"); return 0.0; } @@ -1103,12 +1136,12 @@ JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return NULL; } if (!PySequence_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence"); + throwPythonException(env, "Python variable not a sequence"); return NULL; } @@ -1122,7 +1155,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonN PyObject *module = (PyObject*)contextID; if (!hasNumpy) { - throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed"); + throwPythonException(env, "Importing numpy failed"); return NULL; } @@ -1131,17 +1164,17 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonN PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return NULL; } if (!PyArray_Check(value)) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not an ndarray"); + throwPythonException(env, "Python variable not an ndarray"); return NULL; } if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) { - throwException(env, RUNTIME_EXCEPTION, "Only ndarrays of type double are supported"); + throwPythonException(env, "Only ndarrays of type double are supported"); return NULL; } @@ -1159,7 +1192,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonV PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName); if (value == NULL) { - throwException(env, RUNTIME_EXCEPTION, "Python variable not found"); + throwPythonException(env, "Python variable not found"); return NULL; } diff --git a/org.simantics.pythonlink.win32.x86_64/src/sclpy.h b/org.simantics.pythonlink.win32.x86_64/src/sclpy.h index 4a2c7de..4032d48 100644 --- a/org.simantics.pythonlink.win32.x86_64/src/sclpy.h +++ b/org.simantics.pythonlink.win32.x86_64/src/sclpy.h @@ -27,7 +27,7 @@ #define JAVA_MAXINT (0x7fffffff) -#define RUNTIME_EXCEPTION "java/lang/RuntimeException" +#define PYTHON_EXCEPTION "org/simantics/pythonlink/PythonException" #define ILLEGAL_ARGUMENT_EXCEPTION "java/lang/IllegalArgumentException" #define OBJECT_CLASS "java/lang/Object" #define STRING_CLASS "java/lang/String" diff --git a/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonException.java b/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonException.java new file mode 100644 index 0000000..7c4d2a5 --- /dev/null +++ b/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonException.java @@ -0,0 +1,21 @@ +package org.simantics.pythonlink; + +public class PythonException extends RuntimeException { + private static final long serialVersionUID = 3015300166106850889L; + + public PythonException() { + super(); + } + + public PythonException(String message) { + super(message); + } + + public PythonException(String message, Throwable cause) { + super(message, cause); + } + + public PythonException(Throwable cause) { + super(cause); + } +}