QGIS/python/PyQt6/core/core.sip.in

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

160 lines
4.3 KiB
Plaintext
Raw Permalink Normal View History

%Module(name=qgis._core,
keyword_arguments="All")
${DEFAULTDOCSTRINGSIGNATURE}
%ModuleCode
#include "qgsexception.h"
#include "qgslogger.h"
QString getTraceback()
{
#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;}
// acquire global interpreter lock to ensure we are in a consistent state
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
QString errMsg;
QString result;
PyObject *modStringIO = nullptr;
PyObject *modTB = nullptr;
PyObject *obStringIO = nullptr;
PyObject *obResult = nullptr;
PyObject *type, *value, *traceback;
PyErr_Fetch( &type, &value, &traceback );
PyErr_NormalizeException( &type, &value, &traceback );
const char *iomod = "io";
modStringIO = PyImport_ImportModule( iomod );
if ( !modStringIO )
TRACEBACK_FETCH_ERROR( QString( "can't import %1" ).arg( iomod ) );
obStringIO = PyObject_CallMethod( modStringIO, ( char * ) "StringIO", nullptr );
/* Construct a cStringIO object */
if ( !obStringIO )
TRACEBACK_FETCH_ERROR( "cStringIO.StringIO() failed" );
modTB = PyImport_ImportModule( "traceback" );
if ( !modTB )
TRACEBACK_FETCH_ERROR( "can't import traceback" );
obResult = PyObject_CallMethod( modTB, ( char * ) "print_exception",
( char * ) "OOOOO",
type, value ? value : Py_None,
traceback ? traceback : Py_None,
Py_None,
obStringIO );
if ( !obResult )
TRACEBACK_FETCH_ERROR( "traceback.print_exception() failed" );
Py_DECREF( obResult );
obResult = PyObject_CallMethod( obStringIO, ( char * ) "getvalue", nullptr );
if ( !obResult )
TRACEBACK_FETCH_ERROR( "getvalue() failed." );
/* And it should be a string all ready to go - duplicate it. */
if ( !PyUnicode_Check( obResult ) )
TRACEBACK_FETCH_ERROR( "getvalue() did not return a string" );
result = QString::fromUtf8( PyUnicode_AsUTF8( obResult ) );
done:
// All finished - first see if we encountered an error
if ( result.isEmpty() && !errMsg.isEmpty() )
{
result = errMsg;
}
Py_XDECREF( modStringIO );
Py_XDECREF( modTB );
Py_XDECREF( obStringIO );
Py_XDECREF( obResult );
Py_XDECREF( value );
Py_XDECREF( traceback );
Py_XDECREF( type );
// we are done calling python API, release global interpreter lock
PyGILState_Release( gstate );
return result;
}
%End
%Feature HAVE_GUI
%Feature HAVE_QTSERIALPORT
%Feature HAVE_QTPRINTER
%Feature ANDROID
%Feature VECTOR_MAPPED_TYPE
%Feature HAVE_WEBENGINE_SIP
%Feature PYQT6
%Import QtXml/QtXmlmod.sip
%Import QtNetwork/QtNetworkmod.sip
%Import QtSql/QtSqlmod.sip
%Import QtPrintSupport/QtPrintSupportmod.sip
%Import QtWidgets/QtWidgetsmod.sip
%Import QtPositioning/QtPositioningmod.sip
%If (HAVE_QTSERIALPORT)
%Import QtSerialPort/QtSerialPortmod.sip
%End
%Include conversions.sip
%Include qgsexception.sip
%Include typedefs.sip
%Include std.sip
%Include core_auto.sip
%VirtualErrorHandler processing_exception_handler
// if an explicit QgsProcessingException was raised, we don't retrieve
// and append the trace. It's too noisy for these "expected" type errors.
// For all other exceptions, it's likely a coding error in the algorithm,
// so we DO retrieve the full traceback for debugging.
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
PyTypeObject* err = reinterpret_cast< PyTypeObject* >( PyErr_Occurred() );
const bool isProcessingException = err && QString( err->tp_name ) == QStringLiteral( "QgsProcessingException" );
QString what;
if ( isProcessingException )
{
PyObject *type, *value, *traceback;
PyErr_Fetch( &type, &value, &traceback );
// check whether the object is already a unicode string
if ( PyUnicode_Check( value) )
{
what = QString::fromUtf8( PyUnicode_AsUTF8( value ) );
}
else
{
PyObject* str = PyObject_Str( value );
what = QString::fromUtf8( PyUnicode_AsUTF8( str ) );
Py_XDECREF( str );
}
PyGILState_Release( gstate );
}
else
{
PyGILState_Release( gstate );
QString trace = getTraceback();
QgsLogger::critical( trace );
what = trace;
}
SIP_RELEASE_GIL( sipGILState );
throw QgsProcessingException( what );
%End