Skip to content

Commit d63d560

Browse files
committedJun 23, 2017
Add support for VirtualErrorHandlers in core sip
Unfortunately requires a bunch of code to be duplicated from QgsPythonUtilsImpl::getTraceback() into core.sip, but there's no way to avoid this
1 parent 53e7ef8 commit d63d560

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
 

‎python/core/core.sip

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,93 @@
11
%Module(name=qgis._core,
22
keyword_arguments="Optional")
33

4+
%ModuleCode
5+
6+
#include "qgsprocessingexception.h"
7+
8+
QString getTraceback()
9+
{
10+
#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
11+
12+
// acquire global interpreter lock to ensure we are in a consistent state
13+
PyGILState_STATE gstate;
14+
gstate = PyGILState_Ensure();
15+
16+
QString errMsg;
17+
QString result;
18+
19+
PyObject *modStringIO = nullptr;
20+
PyObject *modTB = nullptr;
21+
PyObject *obStringIO = nullptr;
22+
PyObject *obResult = nullptr;
23+
24+
PyObject *type, *value, *traceback;
25+
26+
PyErr_Fetch( &type, &value, &traceback );
27+
PyErr_NormalizeException( &type, &value, &traceback );
28+
29+
const char *iomod = "io";
30+
31+
modStringIO = PyImport_ImportModule( iomod );
32+
if ( !modStringIO )
33+
TRACEBACK_FETCH_ERROR( QString( "can't import %1" ).arg( iomod ) );
34+
35+
obStringIO = PyObject_CallMethod( modStringIO, ( char * ) "StringIO", nullptr );
36+
37+
/* Construct a cStringIO object */
38+
if ( !obStringIO )
39+
TRACEBACK_FETCH_ERROR( "cStringIO.StringIO() failed" );
40+
41+
modTB = PyImport_ImportModule( "traceback" );
42+
if ( !modTB )
43+
TRACEBACK_FETCH_ERROR( "can't import traceback" );
44+
45+
obResult = PyObject_CallMethod( modTB, ( char * ) "print_exception",
46+
( char * ) "OOOOO",
47+
type, value ? value : Py_None,
48+
traceback ? traceback : Py_None,
49+
Py_None,
50+
obStringIO );
51+
52+
if ( !obResult )
53+
TRACEBACK_FETCH_ERROR( "traceback.print_exception() failed" );
54+
55+
Py_DECREF( obResult );
56+
57+
obResult = PyObject_CallMethod( obStringIO, ( char * ) "getvalue", nullptr );
58+
if ( !obResult )
59+
TRACEBACK_FETCH_ERROR( "getvalue() failed." );
60+
61+
/* And it should be a string all ready to go - duplicate it. */
62+
if ( !PyUnicode_Check( obResult ) )
63+
TRACEBACK_FETCH_ERROR( "getvalue() did not return a string" );
64+
65+
result = QString::fromUtf8( PyUnicode_AsUTF8( obResult ) );
66+
67+
done:
68+
69+
// All finished - first see if we encountered an error
70+
if ( result.isEmpty() && !errMsg.isEmpty() )
71+
{
72+
result = errMsg;
73+
}
74+
75+
Py_XDECREF( modStringIO );
76+
Py_XDECREF( modTB );
77+
Py_XDECREF( obStringIO );
78+
Py_XDECREF( obResult );
79+
Py_XDECREF( value );
80+
Py_XDECREF( traceback );
81+
Py_XDECREF( type );
82+
83+
// we are done calling python API, release global interpreter lock
84+
PyGILState_Release( gstate );
85+
86+
return result;
87+
}
88+
89+
%End
90+
491
%Import QtXml/QtXmlmod.sip
592
%Import QtNetwork/QtNetworkmod.sip
693
%Import QtSql/QtSqlmod.sip
@@ -413,3 +500,7 @@
413500
%Include expression/qgsexpressionnodeimpl.sip
414501
%Include expression/qgsexpressionnode.sip
415502
%Include expression/qgsexpressionfunction.sip
503+
504+
%VirtualErrorHandler processing_exception_handler
505+
throw QgsProcessingException( getTraceback() );
506+
%End

0 commit comments

Comments
 (0)