void python_script_error_jump(const char *filepath, int *lineno, int *offset) { PyObject *exception, *value; PyTracebackObject *tb; *lineno = -1; *offset = 0; PyErr_Fetch(&exception, &value, (PyObject **)&tb); if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { /* no traceback available when SyntaxError. * python has no api's to this. reference parse_syntax_error() from pythonrun.c */ PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ if (value) { /* should always be true */ PyObject *message; PyObject *filename_py, *text_py; if (parse_syntax_error(value, &message, &filename_py, lineno, offset, &text_py)) { const char *filename = _PyUnicode_AsString(filename_py); /* python adds a '/', prefix, so check for both */ if ((BLI_path_cmp(filename, filepath) == 0) || ((filename[0] == '\\' || filename[0] == '/') && BLI_path_cmp(filename + 1, filepath) == 0)) { /* good */ } else { *lineno = -1; } } else { *lineno = -1; } } } else { PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ PyErr_Print(); for (tb = (PyTracebackObject *)PySys_GetObject("last_traceback"); tb && (PyObject *)tb != Py_None; tb = tb->tb_next) { PyObject *coerce; const char *tb_filepath = traceback_filepath(tb, &coerce); const int match = ((BLI_path_cmp(tb_filepath, filepath) == 0) || ((tb_filepath[0] == '\\' || tb_filepath[0] == '/') && BLI_path_cmp(tb_filepath + 1, filepath) == 0)); Py_DECREF(coerce); if (match) { *lineno = tb->tb_lineno; /* used to break here, but better find the inner most line */ } } } }
void python_script_error_jump(const char *filepath, int *lineno, int *offset) { PyObject *exception, *value; PyTracebackObject *tb; *lineno= -1; *offset= 0; PyErr_Fetch(&exception, &value, (PyObject **)&tb); if(exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { /* no traceback available when SyntaxError. * python has no api's to this. reference parse_syntax_error() from pythonrun.c */ PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ if(value) { /* should always be true */ PyObject *message; const char *filename, *text; if(parse_syntax_error(value, &message, &filename, lineno, offset, &text)) { /* python adds a '/', prefix, so check for both */ if( (strcmp(filename, filepath) == 0) || ((filename[0] == '\\' || filename[0] == '/') && strcmp(filename + 1, filepath) == 0) ) { /* good */ } else { *lineno= -1; } } else { *lineno= -1; } } } else { PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ PyErr_Print(); for(tb= (PyTracebackObject *)PySys_GetObject("last_traceback"); tb && (PyObject *)tb != Py_None; tb= tb->tb_next) { if(strcmp(traceback_filepath(tb), filepath) != 0) { *lineno= tb->tb_lineno; break; } } } }