@@ -49,18 +49,8 @@ QgsPythonUtilsImpl::~QgsPythonUtilsImpl()
4949#endif
5050}
5151
52- void QgsPythonUtilsImpl::initPython ( QgisInterface* interface )
53- {
54- // initialize python
55- Py_Initialize ();
56-
57- // initialize threading AND acquire GIL
58- PyEval_InitThreads ();
59-
60- mPythonEnabled = true ;
52+ bool QgsPythonUtilsImpl::checkSystemImports () {
6153
62- mMainModule = PyImport_AddModule ( " __main__" ); // borrowed reference
63- mMainDict = PyModule_GetDict ( mMainModule ); // borrowed reference
6454
6555 runString ( " import sys" ); // import sys module (for display / exception hooks)
6656 runString ( " import os" ); // import os module (for user paths)
@@ -116,8 +106,7 @@ void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
116106 if ( !runString ( " import sip" ,
117107 QObject::tr ( " Couldn't load SIP module." ) + " \n " + QObject::tr ( " Python support will be disabled." ) ) )
118108 {
119- exitPython ();
120- return ;
109+ return false ;
121110 }
122111
123112 // set PyQt4 api versions
@@ -128,36 +117,40 @@ void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
128117 if ( !runString ( QString ( " sip.setapi('%1', 2)" ).arg ( clsName ),
129118 QObject::tr ( " Couldn't set SIP API versions." ) + " \n " + QObject::tr ( " Python support will be disabled." ) ) )
130119 {
131- exitPython ();
132- return ;
120+ return false ;
133121 }
134122 }
135123
136124 // import Qt bindings
137125 if ( !runString ( " from PyQt4 import QtCore, QtGui" ,
138126 QObject::tr ( " Couldn't load PyQt4." ) + " \n " + QObject::tr ( " Python support will be disabled." ) ) )
139127 {
140- exitPython ();
141- return ;
128+ return false ;
142129 }
143130
144131 // import QGIS bindings
145132 QString error_msg = QObject::tr ( " Couldn't load PyQGIS." ) + " \n " + QObject::tr ( " Python support will be disabled." );
146133 if ( !runString ( " from qgis.core import *" , error_msg ) || !runString ( " from qgis.gui import *" , error_msg ) )
147134 {
148- exitPython ();
149- return ;
135+ return false ;
150136 }
151137
138+ #ifdef HAVE_SERVER_PYTHON_PLUGINS
139+ // This is the main difference with initInterface() for desktop plugins
140+ // import QGIS Server bindings
141+ error_msg = QObject::tr ( " Couldn't load PyQGIS Server." ) + " \n " + QObject::tr ( " Python support will be disabled." );
142+ if ( !runString ( " from qgis.server import *" , error_msg ) )
143+ {
144+ return false ;
145+ }
146+ #endif
152147 // import QGIS utils
153148 error_msg = QObject::tr ( " Couldn't load QGIS utils." ) + " \n " + QObject::tr ( " Python support will be disabled." );
154149 if ( !runString ( " import qgis.utils" , error_msg ) )
155150 {
156- exitPython ();
157- return ;
151+ return false ;
158152 }
159153
160-
161154 // tell the utils script where to look for the plugins
162155 runString ( " qgis.utils.plugin_paths = [" + pluginpaths.join ( " ," ) + " ]" );
163156 runString ( " qgis.utils.sys_plugin_path = \" " + pluginsPath () + " \" " );
@@ -167,167 +160,78 @@ void QgsPythonUtilsImpl::initPython( QgisInterface* interface )
167160 runString ( " if oldhome: os.environ['HOME']=oldhome\n " );
168161#endif
169162
170- // initialize 'iface' object
171- runString ( " qgis.utils.initInterface(" + QString::number (( unsigned long ) interface ) + " )" );
172-
173- // import QGIS user
174- error_msg = QObject::tr ( " Couldn't load qgis.user." ) + " \n " + QObject::tr ( " Python support will be disabled." );
175- if ( !runString ( " import qgis.user" , error_msg ) )
176- {
177- // Should we really bail because of this?!
178- exitPython ();
179- return ;
180- }
181-
182- // release GIL!
183- // Later on, we acquire GIL just before doing some Python calls and
184- // release GIL again when the work with Python API is done.
185- // (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
186- // around any calls to Python API, otherwise we may segfault!)
187- _mainState = PyEval_SaveThread ();
163+ return true ;
188164}
189-
190-
191- #ifdef HAVE_SERVER_PYTHON_PLUGINS
192- void QgsPythonUtilsImpl::initServerPython ( QgsServerInterface* interface )
193- {
165+ void QgsPythonUtilsImpl::init () {
194166 // initialize python
195167 Py_Initialize ();
196-
197168 // initialize threading AND acquire GIL
198169 PyEval_InitThreads ();
199170
200171 mPythonEnabled = true ;
201172
202173 mMainModule = PyImport_AddModule ( " __main__" ); // borrowed reference
203174 mMainDict = PyModule_GetDict ( mMainModule ); // borrowed reference
175+ }
204176
205- runString ( " import sys" ); // import sys module (for display / exception hooks)
206- runString ( " import os" ); // import os module (for user paths)
207-
208- // support for PYTHONSTARTUP-like environment variable: PYQGIS_STARTUP
209- // (unlike PYTHONHOME and PYTHONPATH, PYTHONSTARTUP is not supported for embedded interpreter by default)
210- // this is different than user's 'startup.py' (below), since it is loaded just after Py_Initialize
211- // it is very useful for cleaning sys.path, which may have undesireable paths, or for
212- // isolating/loading the initial environ without requiring a virt env, e.g. homebrew or MacPorts installs on Mac
213- runString ( " pyqgstart = os.getenv('PYQGIS_STARTUP')\n " );
214- runString ( " if pyqgstart is not None and os.path.exists(pyqgstart): execfile(pyqgstart)\n " );
215-
216- #ifdef Q_OS_WIN
217- runString ( " oldhome=None" );
218- runString ( " if os.environ.has_key('HOME'): oldhome=os.environ['HOME']\n " );
219- runString ( " os.environ['HOME']=os.environ['USERPROFILE']\n " );
220- #endif
177+ void QgsPythonUtilsImpl::finish () {
178+ // release GIL!
179+ // Later on, we acquire GIL just before doing some Python calls and
180+ // release GIL again when the work with Python API is done.
181+ // (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
182+ // around any calls to Python API, otherwise we may segfault!)
183+ _mainState = PyEval_SaveThread ();
184+ }
221185
222- // construct a list of plugin paths
223- // plugin dirs passed in QGIS_PLUGINPATH env. variable have highest priority (usually empty)
224- // locally installed plugins have priority over the system plugins
225- // use os.path.expanduser to support usernames with special characters (see #2512)
226- QStringList pluginpaths;
227- foreach ( QString p, extraPluginsPaths () )
186+ bool QgsPythonUtilsImpl::checkQgisUser () {
187+ // import QGIS user
188+ QString error_msg = QObject::tr ( " Couldn't load qgis.user." ) + " \n " + QObject::tr ( " Python support will be disabled." );
189+ if ( !runString ( " import qgis.user" , error_msg ) )
228190 {
229- if ( !QDir ( p ).exists () )
230- {
231- QgsMessageOutput* msg = QgsMessageOutput::createMessageOutput ();
232- msg->setTitle ( QObject::tr ( " Python error" ) );
233- msg->setMessage ( QString ( QObject::tr ( " The extra plugin path '%1' does not exist !" ) ).arg ( p ), QgsMessageOutput::MessageText );
234- msg->showMessage ();
235- }
236- #ifdef Q_OS_WIN
237- p = p.replace ( ' \\ ' , " \\\\ " );
238- #endif
239- // we store here paths in unicode strings
240- // the str constant will contain utf8 code (through runString)
241- // so we call '...'.decode('utf-8') to make a unicode string
242- pluginpaths << ' "' + p + " \" .decode('utf-8')" ;
191+ // Should we really bail because of this?!
192+ return false ;
243193 }
244- pluginpaths << homePluginsPath () ;
245- pluginpaths << ' " ' + pluginsPath () + ' " ' ;
194+ return true ;
195+ }
246196
247- // expect that bindings are installed locally, so add the path to modules
248- // also add path to plugins
249- QStringList newpaths;
250- newpaths << ' "' + pythonPath () + ' "' ;
251- newpaths << homePythonPath ();
252- newpaths << pluginpaths;
253- runString ( " sys.path = [" + newpaths.join ( " ," ) + " ] + sys.path" );
197+ void QgsPythonUtilsImpl::doUserImports () {
254198
255- // import SIP
256- if ( !runString ( " import sip" ,
257- QObject::tr ( " Couldn't load SIP module." ) + " \n " + QObject::tr ( " Python support will be disabled." ) ) )
258- {
259- exitPython ();
260- return ;
261- }
199+ QString startuppath = homePythonPath () + " + \" /startup.py\" " ;
200+ runString ( " if os.path.exists(" + startuppath + " ): from startup import *\n " );
201+ }
262202
263- // set PyQt4 api versions
264- QStringList apiV2classes;
265- apiV2classes << " QDate" << " QDateTime" << " QString" << " QTextStream" << " QTime" << " QUrl" << " QVariant" ;
266- foreach ( const QString& clsName, apiV2classes )
267- {
268- if ( !runString ( QString ( " sip.setapi('%1', 2)" ).arg ( clsName ),
269- QObject::tr ( " Couldn't set SIP API versions." ) + " \n " + QObject::tr ( " Python support will be disabled." ) ) )
270- {
203+ void QgsPythonUtilsImpl::initPython ( QgisInterface* interface )
204+ {
205+ init ();
206+ if (!checkSystemImports ()){
271207 exitPython ();
272208 return ;
273- }
274- }
275-
276- // import Qt bindings
277- if ( !runString ( " from PyQt4 import QtCore, QtGui" ,
278- QObject::tr ( " Couldn't load PyQt4." ) + " \n " + QObject::tr ( " Python support will be disabled." ) ) )
279- {
280- exitPython ();
281- return ;
282209 }
283-
284- // import QGIS bindings
285- QString error_msg = QObject::tr ( " Couldn't load PyQGIS." ) + " \n " + QObject::tr ( " Python support will be disabled." );
286- if ( !runString ( " from qgis.core import *" , error_msg ) || !runString ( " from qgis.gui import *" , error_msg ) )
287- {
288- exitPython ();
289- return ;
210+ // initialize 'iface' object
211+ runString ( " qgis.utils.initInterface(" + QString::number (( unsigned long ) interface ) + " )" );
212+ if (!checkQgisUser ()) {
213+ exitPython ();
214+ return ;
290215 }
216+ doUserImports ();
217+ finish ();
218+ }
291219
292- // This is the main difference with initInterface() for desktop plugins
293- // import QGIS Server bindings
294- error_msg = QObject::tr ( " Couldn't load PyQGIS Server." ) + " \n " + QObject::tr ( " Python support will be disabled." );
295- if ( !runString ( " from qgis.server import *" , error_msg ) )
296- {
297- exitPython ();
298- return ;
299- }
300220
221+ #ifdef HAVE_SERVER_PYTHON_PLUGINS
222+ void QgsPythonUtilsImpl::initServerPython ( QgsServerInterface* interface )
223+ {
301224
302- // import QGIS utils
303- error_msg = QObject::tr ( " Couldn't load QGIS utils." ) + " \n " + QObject::tr ( " Python support will be disabled." );
304- if ( !runString ( " import qgis.utils" , error_msg ) )
305- {
306- exitPython ();
307- return ;
225+ init ();
226+ if (!checkSystemImports ()){
227+ exitPython ();
228+ return ;
308229 }
309-
310- // tell the utils script where to look for the plugins
311- runString ( " qgis.utils.plugin_paths = [" + pluginpaths.join ( " ," ) + " ]" );
312- runString ( " qgis.utils.sys_plugin_path = \" " + pluginsPath () + " \" " );
313- runString ( " qgis.utils.home_plugin_path = " + homePluginsPath () );
314-
315- #ifdef Q_OS_WIN
316- runString ( " if oldhome: os.environ['HOME']=oldhome\n " );
317- #endif
318-
319230 // This is the other main difference with initInterface() for desktop plugins
320231 runString ( " qgis.utils.initServerInterface(" + QString::number (( unsigned long ) interface ) + " )" );
321232
322- QString startuppath = homePythonPath () + " + \" /startup.py\" " ;
323- runString ( " if os.path.exists(" + startuppath + " ): from startup import *\n " );
324-
325- // release GIL!
326- // Later on, we acquire GIL just before doing some Python calls and
327- // release GIL again when the work with Python API is done.
328- // (i.e. there must be PyGILState_Ensure + PyGILState_Release pair
329- // around any calls to Python API, otherwise we may segfault!)
330- _mainState = PyEval_SaveThread ();
233+ doUserImports ();
234+ finish ();
331235}
332236
333237bool QgsPythonUtilsImpl::startServerPlugin ( QString packageName )
0 commit comments