]> gerrit.simantics Code Review - simantics/python.git/commitdiff
Get Python traceback output in the messages of exceptions from the pythonlink feature.
authortuorjr <tuorjr@e36c2e66-7d30-0410-bdb2-d9e1f5a6d952>
Thu, 1 Dec 2016 16:31:57 +0000 (16:31 +0000)
committerReino Ruusu <reino.ruusu@vtt.fi>
Tue, 3 Jan 2017 15:09:33 +0000 (17:09 +0200)
git-svn-id: https://www.simantics.org/svn/simantics-incubator/reino@1703 e36c2e66-7d30-0410-bdb2-d9e1f5a6d952

org.simantics.pythonlink.win32.x86_64/jnipython.dll
org.simantics.pythonlink.win32.x86_64/src/sclpy.c
org.simantics.pythonlink.win32.x86_64/src/sclpy.h
org.simantics.pythonlink/src/org/simantics/pythonlink/PythonException.java [new file with mode: 0644]

index 76fe378a6e2aeb6b316acfbebe60d961a520b73d..7fff774adac1bb1b1d2c5ffbffa6043e44d877e1 100644 (file)
Binary files a/org.simantics.pythonlink.win32.x86_64/jnipython.dll and b/org.simantics.pythonlink.win32.x86_64/jnipython.dll differ
index 565b6fab3d3aa07cf386e0100e5d6158f3375165..b10b36f5d3c1103aeda3c6e7582ff44bdb6670b5 100644 (file)
@@ -24,6 +24,10 @@ jint throwException( JNIEnv *env, char *className, char *message )
     return (*env)->ThrowNew( env, exClass, message );\r
 }\r
 \r
+jint throwPythonException( JNIEnv *env, char *message ) {\r
+       return throwException( env, PYTHON_EXCEPTION, message );\r
+}\r
+\r
 jint throwIllegalArgumentException( JNIEnv *env, char *message ) {\r
        return throwException( env, ILLEGAL_ARGUMENT_EXCEPTION, message );\r
 }\r
@@ -581,7 +585,7 @@ jobjectArray pythonSequenceAsStringArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetObjectArrayElement(env, array, i, value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not a string");\r
+                       throwPythonException(env, "List item not a string");\r
                        return NULL;\r
                }\r
        }\r
@@ -603,7 +607,7 @@ jdoubleArray pythonSequenceAsDoubleArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetDoubleArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not a floating point value");\r
+                       throwPythonException(env, "List item not a floating point value");\r
                        return NULL;\r
                }\r
        }\r
@@ -662,7 +666,7 @@ jbooleanArray pythonSequenceAsBooleanArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetBooleanArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not a boolean");\r
+                       throwPythonException(env, "List item not a boolean");\r
                        return NULL;\r
                }\r
        }\r
@@ -684,7 +688,7 @@ jintArray pythonSequenceAsIntegerArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetIntArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
+                       throwPythonException(env, "List item not an integer");\r
                        return NULL;\r
                }\r
        }\r
@@ -706,7 +710,7 @@ jlongArray pythonSequenceAsLongArray(JNIEnv *env, PyObject *seq) {
                        (*env)->SetLongArrayRegion(env, array, i, 1, &value);\r
                }\r
                else {\r
-                       throwException(env, RUNTIME_EXCEPTION, "List item not an integer");\r
+                       throwPythonException(env, "List item not an integer");\r
                        return NULL;\r
                }\r
        }\r
@@ -729,7 +733,7 @@ jobject pythonArrayAsNDArray(JNIEnv *env, PyArrayObject *array) {
        int i;\r
 \r
        if (len > JAVA_MAXINT) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Array too large");\r
+               throwPythonException(env, "Array too large");\r
                return NULL;\r
        }\r
 \r
@@ -872,7 +876,7 @@ JNIEXPORT void JNICALL Java_org_simantics_pythonlink_PythonContext_setPythonNDAr
        PyObject *module = (PyObject*)contextID;\r
 \r
        if (!hasNumpy) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
+               throwPythonException(env, "Importing numpy failed");\r
                return;\r
        }\r
 \r
@@ -909,11 +913,40 @@ JNIEXPORT jint JNICALL Java_org_simantics_pythonlink_PythonContext_executePython
 \r
                        PyObject *exceptionType = PyErr_Occurred();\r
                        if (exceptionType != NULL) {\r
-                               PyObject *exception, *stackTrace;\r
-                               char *message;\r
-                               PyErr_Fetch(&exceptionType, &exception, &stackTrace);\r
-                               message = PyUnicode_AsUTF8(exception);\r
-                               throwException(env, RUNTIME_EXCEPTION, message);\r
+                               PyObject *exception, *traceback;\r
+                               PyErr_Fetch(&exceptionType, &exception, &traceback);\r
+\r
+                               {\r
+                                       PyObject *tracebackModule = PyImport_ImportModule("traceback");\r
+                                       if (tracebackModule != NULL) {\r
+                                               PyObject *formatExc = PyDict_GetItemString(PyModule_GetDict(tracebackModule), "format_exception");\r
+                                               if (formatExc != NULL) {\r
+                                                       PyObject *args = PyTuple_Pack(3, exceptionType, exception, traceback);\r
+                                                       PyObject *message = PyObject_CallObject(formatExc, args);\r
+                                                       if (message != NULL) {\r
+                                                               PyObject *emptyStr = PyUnicode_FromString("");\r
+                                                               PyObject *joined = PyUnicode_Join(emptyStr, message);\r
+                                                               char *messageStr = PyUnicode_AsUTF8(joined);\r
+                                                               throwPythonException(env, messageStr);\r
+                                                               Py_DECREF(joined);\r
+                                                               Py_DECREF(emptyStr);\r
+                                                               Py_DECREF(message);\r
+                                                       }\r
+                                                       else {\r
+                                                               throwPythonException(env, "Internal error, no message");\r
+                                                       }\r
+                                                       Py_DECREF(args);\r
+                                                       Py_DECREF(formatExc);\r
+                                               }\r
+                                               else {\r
+                                                       throwPythonException(env, "Internal error, no format_exc function");\r
+                                               }\r
+                                               Py_DECREF(tracebackModule);\r
+                                       }\r
+                                       else {\r
+                                               throwPythonException(env, "Internal error, no traceback module");\r
+                                       }\r
+                               }\r
                        }\r
 \r
                        (*env)->ReleaseStringUTFChars(env, statement, utfchars);\r
@@ -930,12 +963,12 @@ JNIEXPORT jstring JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonS
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PyUnicode_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a string");\r
+               throwPythonException(env, "Python variable not a string");\r
                return 0;\r
        }\r
 \r
@@ -952,12 +985,12 @@ JNIEXPORT jobjectArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return 0;\r
        }\r
 \r
@@ -974,12 +1007,12 @@ JNIEXPORT jboolean JNICALL Java_org_simantics_pythonlink_PythonContext_getPython
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PyBool_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a boolean");\r
+               throwPythonException(env, "Python variable not a boolean");\r
                return 0;\r
        }\r
 \r
@@ -993,12 +1026,12 @@ JNIEXPORT jbooleanArray JNICALL Java_org_simantics_pythonlink_PythonContext_getP
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return 0;\r
        }\r
 \r
@@ -1015,12 +1048,12 @@ JNIEXPORT jlong JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonLon
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0;\r
        }\r
 \r
        if (!PyLong_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not an integer");\r
+               throwPythonException(env, "Python variable not an integer");\r
                return 0;\r
        }\r
 \r
@@ -1037,12 +1070,12 @@ JNIEXPORT jintArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPytho
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return NULL;\r
        }\r
 \r
@@ -1059,12 +1092,12 @@ JNIEXPORT jlongArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPyth
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return NULL;\r
        }\r
 \r
@@ -1081,12 +1114,12 @@ JNIEXPORT jdouble JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonD
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return 0.0;\r
        }\r
 \r
        if (!PyFloat_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a float");\r
+               throwPythonException(env, "Python variable not a float");\r
                return 0.0;\r
        }\r
 \r
@@ -1103,12 +1136,12 @@ JNIEXPORT jdoubleArray JNICALL Java_org_simantics_pythonlink_PythonContext_getPy
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r
        if (!PySequence_Check(value)) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not a sequence");\r
+               throwPythonException(env, "Python variable not a sequence");\r
                return NULL;\r
        }\r
 \r
@@ -1122,7 +1155,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonN
        PyObject *module = (PyObject*)contextID;\r
 \r
        if (!hasNumpy) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Importing numpy failed");\r
+               throwPythonException(env, "Importing numpy failed");\r
                return NULL;\r
        }\r
 \r
@@ -1131,17 +1164,17 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonN
 \r
                PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
                if (value == NULL) {\r
-                       throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+                       throwPythonException(env, "Python variable not found");\r
                        return NULL;\r
                }\r
 \r
                if (!PyArray_Check(value)) {\r
-                       throwException(env, RUNTIME_EXCEPTION, "Python variable not an ndarray");\r
+                       throwPythonException(env, "Python variable not an ndarray");\r
                        return NULL;\r
                }\r
 \r
                if (PyArray_TYPE((PyArrayObject*)value) != NPY_DOUBLE) {\r
-                       throwException(env, RUNTIME_EXCEPTION, "Only ndarrays of type double are supported");\r
+                       throwPythonException(env, "Only ndarrays of type double are supported");\r
                        return NULL;\r
                }\r
 \r
@@ -1159,7 +1192,7 @@ JNIEXPORT jobject JNICALL Java_org_simantics_pythonlink_PythonContext_getPythonV
 \r
        PyObject *value = PyDict_GetItem(PyModule_GetDict(module), pythonName);\r
        if (value == NULL) {\r
-               throwException(env, RUNTIME_EXCEPTION, "Python variable not found");\r
+               throwPythonException(env, "Python variable not found");\r
                return NULL;\r
        }\r
 \r
index 4a2c7de919bcd90700bb9f17f968b7db8c3ff726..4032d4854512fb27fa18008e6a1c23b894140e63 100644 (file)
@@ -27,7 +27,7 @@
 \r
 #define JAVA_MAXINT (0x7fffffff)\r
 \r
-#define RUNTIME_EXCEPTION "java/lang/RuntimeException"\r
+#define PYTHON_EXCEPTION "org/simantics/pythonlink/PythonException"\r
 #define ILLEGAL_ARGUMENT_EXCEPTION "java/lang/IllegalArgumentException"\r
 #define OBJECT_CLASS "java/lang/Object"\r
 #define STRING_CLASS "java/lang/String"\r
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 (file)
index 0000000..7c4d2a5
--- /dev/null
@@ -0,0 +1,21 @@
+package org.simantics.pythonlink;\r
+\r
+public class PythonException extends RuntimeException {\r
+       private static final long serialVersionUID = 3015300166106850889L;\r
+       \r
+       public PythonException() {\r
+               super();\r
+       }\r
+       \r
+       public PythonException(String message) {\r
+               super(message);\r
+       }\r
+       \r
+       public PythonException(String message, Throwable cause) {\r
+               super(message, cause);\r
+       }\r
+       \r
+       public PythonException(Throwable cause) {\r
+               super(cause);\r
+       }\r
+}\r