41
41
import codecs
42
42
import time
43
43
44
- #######################
44
+ # ######################
45
45
# ERROR HANDLING
46
46
47
47
warnings .simplefilter ('default' )
48
48
warnings .filterwarnings ("ignore" , "the sets module is deprecated" )
49
49
50
+
50
51
def showWarning (message , category , filename , lineno , file = None , line = None ):
51
- stk = ""
52
- for s in traceback .format_stack ()[:- 2 ]:
53
- stk += s .decode ('utf-8' , 'replace' )
54
- QgsMessageLog .logMessage (
55
- "warning:%s\n traceback:%s" % ( warnings .formatwarning (message , category , filename , lineno ), stk ),
56
- QCoreApplication .translate ( "Python" , "Python warning" )
57
- )
52
+ stk = ""
53
+ for s in traceback .format_stack ()[:- 2 ]:
54
+ stk += s .decode ('utf-8' , 'replace' )
55
+ QgsMessageLog .logMessage (
56
+ "warning:%s\n traceback:%s" % ( warnings .formatwarning (message , category , filename , lineno ), stk ),
57
+ QCoreApplication .translate ("Python" , "Python warning" )
58
+ )
59
+
60
+
58
61
warnings .showwarning = showWarning
59
62
63
+
60
64
def showException (type , value , tb , msg ):
61
- lst = traceback .format_exception (type , value , tb )
62
- if msg == None :
63
- msg = QCoreApplication .translate ('Python' , 'An error has occured while executing Python code:' )
64
- txt = '<font color="red">%s</font><br><br><pre>' % msg
65
- for s in lst :
66
- txt += s .decode ('utf-8' , 'replace' )
67
- txt += '</pre><br>%s<br>%s<br><br>' % (QCoreApplication .translate ('Python' ,'Python version:' ), sys .version )
68
- txt += '<br>%s<br>%s %s, %s<br><br>' % (QCoreApplication .translate ('Python' ,'QGIS version:' ), QGis .QGIS_VERSION , QGis .QGIS_RELEASE_NAME , QGis .QGIS_DEV_VERSION )
69
- txt += '%s %s' % (QCoreApplication .translate ('Python' ,'Python path:' ), str (sys .path ))
70
- txt = txt .replace ('\n ' , '<br>' )
71
- txt = txt .replace (' ' , ' ' ) # preserve whitespaces for nicer output
72
-
73
- from qgis .core import QgsMessageOutput
74
- msg = QgsMessageOutput .createMessageOutput ()
75
- msg .setTitle (QCoreApplication .translate ('Python' , 'Python error' ))
76
- msg .setMessage (txt , QgsMessageOutput .MessageHtml )
77
- msg .showMessage ()
65
+ lst = traceback .format_exception (type , value , tb )
66
+ if msg == None :
67
+ msg = QCoreApplication .translate ('Python' , 'An error has occured while executing Python code:' )
68
+ txt = '<font color="red">%s</font><br><br><pre>' % msg
69
+ for s in lst :
70
+ txt += s .decode ('utf-8' , 'replace' )
71
+ txt += '</pre><br>%s<br>%s<br><br>' % (QCoreApplication .translate ('Python' , 'Python version:' ), sys .version )
72
+ txt += '<br>%s<br>%s %s, %s<br><br>' % (
73
+ QCoreApplication .translate ('Python' , 'QGIS version:' ), QGis .QGIS_VERSION , QGis .QGIS_RELEASE_NAME ,
74
+ QGis .QGIS_DEV_VERSION )
75
+ txt += '%s %s' % (QCoreApplication .translate ('Python' , 'Python path:' ), str (sys .path ))
76
+ txt = txt .replace ('\n ' , '<br>' )
77
+ txt = txt .replace (' ' , ' ' ) # preserve whitespaces for nicer output
78
+
79
+ from qgis .core import QgsMessageOutput
80
+
81
+ msg = QgsMessageOutput .createMessageOutput ()
82
+ msg .setTitle (QCoreApplication .translate ('Python' , 'Python error' ))
83
+ msg .setMessage (txt , QgsMessageOutput .MessageHtml )
84
+ msg .showMessage ()
85
+
78
86
79
87
def qgis_excepthook (type , value , tb ):
80
- showException (type , value , tb , None )
88
+ showException (type , value , tb , None )
89
+
81
90
82
91
def installErrorHook ():
83
- sys .excepthook = qgis_excepthook
92
+ sys .excepthook = qgis_excepthook
93
+
84
94
85
95
def uninstallErrorHook ():
86
- sys .excepthook = sys .__excepthook__
96
+ sys .excepthook = sys .__excepthook__
87
97
88
98
# install error hook() on module load
89
99
installErrorHook ()
90
100
91
101
# initialize 'iface' object
92
102
iface = None
93
103
104
+
94
105
def initInterface (pointer ):
95
- from qgis .gui import QgisInterface
96
- from sip import wrapinstance
97
- global iface
98
- iface = wrapinstance (pointer , QgisInterface )
106
+ from qgis .gui import QgisInterface
107
+ from sip import wrapinstance
108
+
109
+ global iface
110
+ iface = wrapinstance (pointer , QgisInterface )
99
111
100
112
#######################
101
113
# PLUGINS
@@ -118,333 +130,343 @@ def initInterface(pointer):
118
130
# key = plugin package name, value = config parser instance
119
131
plugins_metadata_parser = {}
120
132
133
+
121
134
def findPlugins (path ):
122
- """ for internal use: return list of plugins in given path """
123
- for plugin in glob .glob (path + "/*" ):
124
- if not os .path .isdir (plugin ):
125
- continue
126
- if not os .path .exists (os .path .join (plugin , '__init__.py' )):
127
- continue
135
+ """ for internal use: return list of plugins in given path """
136
+ for plugin in glob .glob (path + "/*" ):
137
+ if not os .path .isdir (plugin ):
138
+ continue
139
+ if not os .path .exists (os .path .join (plugin , '__init__.py' )):
140
+ continue
128
141
129
- metadataFile = os .path .join (plugin , 'metadata.txt' )
130
- if not os .path .exists (metadataFile ):
131
- continue
142
+ metadataFile = os .path .join (plugin , 'metadata.txt' )
143
+ if not os .path .exists (metadataFile ):
144
+ continue
132
145
133
- cp = ConfigParser .ConfigParser ()
146
+ cp = ConfigParser .ConfigParser ()
134
147
135
- try :
136
- cp .readfp (codecs .open (metadataFile , "r" , "utf8" ))
137
- except :
138
- cp = None
148
+ try :
149
+ cp .readfp (codecs .open (metadataFile , "r" , "utf8" ))
150
+ except :
151
+ cp = None
139
152
140
- pluginName = os .path .basename (plugin )
141
- yield (pluginName , cp )
153
+ pluginName = os .path .basename (plugin )
154
+ yield (pluginName , cp )
142
155
143
156
144
157
def updateAvailablePlugins ():
145
- """ Go through the plugin_paths list and find out what plugins are available. """
146
- # merge the lists
147
- plugins = []
148
- metadata_parser = {}
149
- for pluginpath in plugin_paths :
150
- for pluginName , parser in findPlugins (pluginpath ):
151
- if parser is None : continue
152
- if pluginName not in plugins :
153
- plugins .append (pluginName )
154
- metadata_parser [pluginName ] = parser
155
-
156
- global available_plugins
157
- available_plugins = plugins
158
- global plugins_metadata_parser
159
- plugins_metadata_parser = metadata_parser
158
+ """ Go through the plugin_paths list and find out what plugins are available. """
159
+ # merge the lists
160
+ plugins = []
161
+ metadata_parser = {}
162
+ for pluginpath in plugin_paths :
163
+ for pluginName , parser in findPlugins (pluginpath ):
164
+ if parser is None : continue
165
+ if pluginName not in plugins :
166
+ plugins .append (pluginName )
167
+ metadata_parser [pluginName ] = parser
168
+
169
+ global available_plugins
170
+ available_plugins = plugins
171
+ global plugins_metadata_parser
172
+ plugins_metadata_parser = metadata_parser
160
173
161
174
162
175
def pluginMetadata (packageName , fct ):
163
- """ fetch metadata from a plugin - use values from metadata.txt """
164
- try :
165
- return plugins_metadata_parser [packageName ].get ('general' , fct )
166
- except Exception :
167
- return "__error__"
176
+ """ fetch metadata from a plugin - use values from metadata.txt """
177
+ try :
178
+ return plugins_metadata_parser [packageName ].get ('general' , fct )
179
+ except Exception :
180
+ return "__error__"
168
181
169
182
170
183
def loadPlugin (packageName ):
171
- """ load plugin's package """
184
+ """ load plugin's package """
172
185
173
- try :
174
- __import__ (packageName )
175
- return True
176
- except :
177
- pass # continue...
186
+ try :
187
+ __import__ (packageName )
188
+ return True
189
+ except :
190
+ pass # continue...
178
191
179
- # snake in the grass, we know it's there
180
- sys .path_importer_cache .clear ()
192
+ # snake in the grass, we know it's there
193
+ sys .path_importer_cache .clear ()
181
194
182
- # retry
183
- try :
184
- __import__ (packageName )
185
- return True
186
- except :
187
- msgTemplate = QCoreApplication .translate ("Python" , "Couldn't load plugin '%s' from ['%s']" )
188
- msg = msgTemplate % (packageName , "', '" .join (sys .path ))
189
- showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
190
- return False
195
+ # retry
196
+ try :
197
+ __import__ (packageName )
198
+ return True
199
+ except :
200
+ msgTemplate = QCoreApplication .translate ("Python" , "Couldn't load plugin '%s' from ['%s']" )
201
+ msg = msgTemplate % (packageName , "', '" .join (sys .path ))
202
+ showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
203
+ return False
191
204
192
205
193
206
def startPlugin (packageName ):
194
- """ initialize the plugin """
195
- global plugins , active_plugins , iface , plugin_times
207
+ """ initialize the plugin """
208
+ global plugins , active_plugins , iface , plugin_times
196
209
197
- if packageName in active_plugins : return False
198
- if packageName not in sys .modules : return False
210
+ if packageName in active_plugins : return False
211
+ if packageName not in sys .modules : return False
199
212
200
- package = sys .modules [packageName ]
213
+ package = sys .modules [packageName ]
201
214
202
- errMsg = QCoreApplication .translate ("Python" , "Couldn't load plugin %s" ) % packageName
215
+ errMsg = QCoreApplication .translate ("Python" , "Couldn't load plugin %s" ) % packageName
203
216
204
- start = time .clock ()
205
- # create an instance of the plugin
206
- try :
207
- plugins [packageName ] = package .classFactory (iface )
208
- except :
209
- _unloadPluginModules (packageName )
210
- msg = QCoreApplication .translate ("Python" , "%s due to an error when calling its classFactory() method" ) % errMsg
211
- showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
212
- return False
217
+ start = time .clock ()
218
+ # create an instance of the plugin
219
+ try :
220
+ plugins [packageName ] = package .classFactory (iface )
221
+ except :
222
+ _unloadPluginModules (packageName )
223
+ msg = QCoreApplication .translate ("Python" , "%s due to an error when calling its classFactory() method" ) % errMsg
224
+ showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
225
+ return False
213
226
214
- # initGui
215
- try :
216
- plugins [packageName ].initGui ()
217
- except :
218
- del plugins [packageName ]
219
- _unloadPluginModules (packageName )
220
- msg = QCoreApplication .translate ("Python" , "%s due to an error when calling its initGui() method" ) % errMsg
221
- showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
222
- return False
227
+ # initGui
228
+ try :
229
+ plugins [packageName ].initGui ()
230
+ except :
231
+ del plugins [packageName ]
232
+ _unloadPluginModules (packageName )
233
+ msg = QCoreApplication .translate ("Python" , "%s due to an error when calling its initGui() method" ) % errMsg
234
+ showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
235
+ return False
223
236
224
- # add to active plugins
225
- active_plugins .append (packageName )
226
- end = time .clock ()
227
- plugin_times [packageName ] = "{0:02f}s" .format (end - start )
237
+ # add to active plugins
238
+ active_plugins .append (packageName )
239
+ end = time .clock ()
240
+ plugin_times [packageName ] = "{0:02f}s" .format (end - start )
228
241
229
- return True
242
+ return True
230
243
231
244
232
245
def canUninstallPlugin (packageName ):
233
- """ confirm that the plugin can be uninstalled """
234
- global plugins , active_plugins
235
-
236
- if not plugins .has_key (packageName ): return False
237
- if packageName not in active_plugins : return False
238
-
239
- try :
240
- metadata = plugins [packageName ]
241
- if "canBeUninstalled" not in dir (metadata ):
242
- return True
243
- return bool (metadata .canBeUninstalled ())
244
- except :
245
- msg = "Error calling " + packageName + ".canBeUninstalled"
246
- showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
247
- return True
246
+ """ confirm that the plugin can be uninstalled """
247
+ global plugins , active_plugins
248
+
249
+ if not plugins .has_key (packageName ): return False
250
+ if packageName not in active_plugins : return False
251
+
252
+ try :
253
+ metadata = plugins [packageName ]
254
+ if "canBeUninstalled" not in dir (metadata ):
255
+ return True
256
+ return bool (metadata .canBeUninstalled ())
257
+ except :
258
+ msg = "Error calling " + packageName + ".canBeUninstalled"
259
+ showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
260
+ return True
248
261
249
262
250
263
def unloadPlugin (packageName ):
251
- """ unload and delete plugin! """
252
- global plugins , active_plugins
264
+ """ unload and delete plugin! """
265
+ global plugins , active_plugins
253
266
254
- if not plugins .has_key (packageName ): return False
255
- if packageName not in active_plugins : return False
267
+ if not plugins .has_key (packageName ): return False
268
+ if packageName not in active_plugins : return False
256
269
257
- try :
258
- plugins [packageName ].unload ()
259
- del plugins [packageName ]
260
- active_plugins .remove (packageName )
261
- _unloadPluginModules (packageName )
262
- return True
263
- except Exception , e :
264
- msg = QCoreApplication .translate ("Python" , "Error while unloading plugin %s" ) % packageName
265
- showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
266
- return False
270
+ try :
271
+ plugins [packageName ].unload ()
272
+ del plugins [packageName ]
273
+ active_plugins .remove (packageName )
274
+ _unloadPluginModules (packageName )
275
+ return True
276
+ except Exception , e :
277
+ msg = QCoreApplication .translate ("Python" , "Error while unloading plugin %s" ) % packageName
278
+ showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
279
+ return False
267
280
268
281
269
282
def _unloadPluginModules (packageName ):
270
- """ unload plugin package with all its modules (files) """
271
- global _plugin_modules
272
- mods = _plugin_modules [packageName ]
273
-
274
- for mod in mods :
275
- # if it looks like a Qt resource file, try to do a cleanup
276
- # otherwise we might experience a segfault next time the plugin is loaded
277
- # because Qt will try to access invalid plugin resource data
278
- try :
279
- if hasattr (sys .modules [mod ], 'qCleanupResources' ):
280
- sys .modules [mod ].qCleanupResources ()
281
- except :
282
- pass
283
- # try to remove the module from python
284
- try :
285
- del sys .modules [mod ]
286
- except :
287
- pass
288
- # remove the plugin entry
289
- del _plugin_modules [packageName ]
283
+ """ unload plugin package with all its modules (files) """
284
+ global _plugin_modules
285
+ mods = _plugin_modules [packageName ]
286
+
287
+ for mod in mods :
288
+ # if it looks like a Qt resource file, try to do a cleanup
289
+ # otherwise we might experience a segfault next time the plugin is loaded
290
+ # because Qt will try to access invalid plugin resource data
291
+ try :
292
+ if hasattr (sys .modules [mod ], 'qCleanupResources' ):
293
+ sys .modules [mod ].qCleanupResources ()
294
+ except :
295
+ pass
296
+ # try to remove the module from python
297
+ try :
298
+ del sys .modules [mod ]
299
+ except :
300
+ pass
301
+ # remove the plugin entry
302
+ del _plugin_modules [packageName ]
290
303
291
304
292
305
def isPluginLoaded (packageName ):
293
- """ find out whether a plugin is active (i.e. has been started) """
294
- global plugins , active_plugins
306
+ """ find out whether a plugin is active (i.e. has been started) """
307
+ global plugins , active_plugins
295
308
296
- if not plugins .has_key (packageName ): return False
297
- return (packageName in active_plugins )
309
+ if not plugins .has_key (packageName ): return False
310
+ return (packageName in active_plugins )
298
311
299
312
300
313
def reloadPlugin (packageName ):
301
- """ unload and start again a plugin """
302
- global active_plugins
303
- if packageName not in active_plugins :
304
- return # it's not active
305
-
306
- unloadPlugin (packageName )
307
- loadPlugin (packageName )
308
- startPlugin (packageName )
309
-
310
-
311
- def showPluginHelp (packageName = None ,filename = "index" ,section = "" ):
312
- """ show a help in the user's html browser. The help file should be named index-ll_CC.html or index-ll.html"""
313
- try :
314
- source = ""
315
- if packageName is None :
316
- import inspect
317
- source = inspect .currentframe ().f_back .f_code .co_filename
318
- else :
319
- source = sys .modules [packageName ].__file__
320
- except :
321
- return
322
- path = os .path .dirname (source )
323
- locale = str (QLocale ().name ())
324
- helpfile = os .path .join (path ,filename + "-" + locale + ".html" )
325
- if not os .path .exists (helpfile ):
326
- helpfile = os .path .join (path ,filename + "-" + locale .split ("_" )[0 ]+ ".html" )
327
- if not os .path .exists (helpfile ):
328
- helpfile = os .path .join (path ,filename + "-en.html" )
329
- if not os .path .exists (helpfile ):
330
- helpfile = os .path .join (path ,filename + "-en_US.html" )
331
- if not os .path .exists (helpfile ):
332
- helpfile = os .path .join (path ,filename + ".html" )
333
- if os .path .exists (helpfile ):
334
- url = "file://" + helpfile
335
- if section != "" :
336
- url = url + "#" + section
337
- iface .openURL (url ,False )
314
+ """ unload and start again a plugin """
315
+ global active_plugins
316
+ if packageName not in active_plugins :
317
+ return # it's not active
318
+
319
+ unloadPlugin (packageName )
320
+ loadPlugin (packageName )
321
+ startPlugin (packageName )
322
+
323
+
324
+ def showPluginHelp (packageName = None , filename = "index" , section = "" ):
325
+ """ show a help in the user's html browser. The help file should be named index-ll_CC.html or index-ll.html"""
326
+ try :
327
+ source = ""
328
+ if packageName is None :
329
+ import inspect
330
+
331
+ source = inspect .currentframe ().f_back .f_code .co_filename
332
+ else :
333
+ source = sys .modules [packageName ].__file__
334
+ except :
335
+ return
336
+ path = os .path .dirname (source )
337
+ locale = str (QLocale ().name ())
338
+ helpfile = os .path .join (path , filename + "-" + locale + ".html" )
339
+ if not os .path .exists (helpfile ):
340
+ helpfile = os .path .join (path , filename + "-" + locale .split ("_" )[0 ] + ".html" )
341
+ if not os .path .exists (helpfile ):
342
+ helpfile = os .path .join (path , filename + "-en.html" )
343
+ if not os .path .exists (helpfile ):
344
+ helpfile = os .path .join (path , filename + "-en_US.html" )
345
+ if not os .path .exists (helpfile ):
346
+ helpfile = os .path .join (path , filename + ".html" )
347
+ if os .path .exists (helpfile ):
348
+ url = "file://" + helpfile
349
+ if section != "" :
350
+ url = url + "#" + section
351
+ iface .openURL (url , False )
338
352
339
353
340
354
def pluginDirectory (packageName ):
341
- """ return directory where the plugin resides. Plugin must be loaded already """
342
- return os .path .dirname (sys .modules [packageName ].__file__ )
355
+ """ return directory where the plugin resides. Plugin must be loaded already """
356
+ return os .path .dirname (sys .modules [packageName ].__file__ )
357
+
343
358
344
359
def reloadProjectMacros ():
345
- # unload old macros
346
- unloadProjectMacros ()
360
+ # unload old macros
361
+ unloadProjectMacros ()
347
362
348
- from qgis .core import QgsProject
349
- code , ok = QgsProject .instance ().readEntry ("Macros" , "/pythonCode" )
350
- if not ok or not code or code == '' :
351
- return
363
+ from qgis .core import QgsProject
352
364
353
- # create a new empty python module
354
- import imp
355
- mod = imp . new_module ( "proj_macros_mod" )
365
+ code , ok = QgsProject . instance (). readEntry ( "Macros" , "/pythonCode" )
366
+ if not ok or not code or code == '' :
367
+ return
356
368
357
- # set the module code and store it sys.modules
358
- exec unicode (code ) in mod .__dict__
359
- sys .modules ["proj_macros_mod" ] = mod
369
+ # create a new empty python module
370
+ import imp
371
+
372
+ mod = imp .new_module ("proj_macros_mod" )
373
+
374
+ # set the module code and store it sys.modules
375
+ exec unicode (code ) in mod .__dict__
376
+ sys .modules ["proj_macros_mod" ] = mod
377
+
378
+ # load new macros
379
+ openProjectMacro ()
360
380
361
- # load new macros
362
- openProjectMacro ()
363
381
364
382
def unloadProjectMacros ():
365
- if "proj_macros_mod" not in sys .modules :
366
- return
367
- # unload old macros
368
- closeProjectMacro ()
369
- # destroy the reference to the module
370
- del sys .modules ["proj_macros_mod" ]
383
+ if "proj_macros_mod" not in sys .modules :
384
+ return
385
+ # unload old macros
386
+ closeProjectMacro ()
387
+ # destroy the reference to the module
388
+ del sys .modules ["proj_macros_mod" ]
371
389
372
390
373
391
def openProjectMacro ():
374
- if "proj_macros_mod" not in sys .modules :
375
- return
376
- mod = sys .modules ["proj_macros_mod" ]
377
- if hasattr (mod , 'openProject' ):
378
- mod .openProject ()
392
+ if "proj_macros_mod" not in sys .modules :
393
+ return
394
+ mod = sys .modules ["proj_macros_mod" ]
395
+ if hasattr (mod , 'openProject' ):
396
+ mod .openProject ()
397
+
379
398
380
399
def saveProjectMacro ():
381
- if "proj_macros_mod" not in sys .modules :
382
- return
383
- mod = sys .modules ["proj_macros_mod" ]
384
- if hasattr (mod , 'saveProject' ):
385
- mod .saveProject ()
400
+ if "proj_macros_mod" not in sys .modules :
401
+ return
402
+ mod = sys .modules ["proj_macros_mod" ]
403
+ if hasattr (mod , 'saveProject' ):
404
+ mod .saveProject ()
405
+
386
406
387
407
def closeProjectMacro ():
388
- if "proj_macros_mod" not in sys .modules :
389
- return
390
- mod = sys .modules ["proj_macros_mod" ]
391
- if hasattr (mod , 'closeProject' ):
392
- mod .closeProject ()
408
+ if "proj_macros_mod" not in sys .modules :
409
+ return
410
+ mod = sys .modules ["proj_macros_mod" ]
411
+ if hasattr (mod , 'closeProject' ):
412
+ mod .closeProject ()
393
413
394
414
395
415
def qgsfunction (args , group , ** kwargs ):
396
- """
397
- Decorator function used to define a user expression function.
398
-
399
- Custom functions should take (values, feature, parent) as args,
400
- they can also shortcut naming feature and parent args by using *args
401
- if they are not needed in the function.
402
-
403
- Functions should return a value compatible with QVariant
404
-
405
- Eval errors can be raised using parent.setEvalErrorString()
406
-
407
- Functions must be unregistered when no longer needed using
408
- QgsExpression.unregisterFunction
409
-
410
- Example:
411
- @qgsfunction(2, 'test'):
412
- def add(values, feature, parent):
413
- pass
414
-
415
- Will create and register a function in QgsExpression called 'add' in the
416
- 'test' group that takes two arguments.
417
-
418
- or not using feature and parent:
419
-
420
- @qgsfunction(2, 'test'):
421
- def add(values, *args):
422
- pass
423
- """
424
- helptemplate = Template ("""<h3>$name function</h3><br>$doc""" )
425
- class QgsExpressionFunction (QgsExpression .Function ):
426
- def __init__ (self , name , args , group , helptext = '' , usesgeometry = False ):
427
- QgsExpression .Function .__init__ (self , name , args , group , helptext , usesgeometry )
428
-
429
- def func (self , values , feature , parent ):
430
- pass
431
-
432
- def wrapper (func ):
433
- name = kwargs .get ('name' , func .__name__ )
434
- usesgeometry = kwargs .get ('usesgeometry' , False )
435
- help = func .__doc__ or ''
436
- help = help .strip ()
437
- if args == 0 and not name [0 ] == '$' :
438
- name = '${0}' .format (name )
439
- func .__name__ = name
440
- help = helptemplate .safe_substitute (name = name , doc = help )
441
- f = QgsExpressionFunction (name , args , group , help , usesgeometry )
442
- f .func = func
443
- register = kwargs .get ('register' , True )
444
- if register :
445
- QgsExpression .registerFunction (f )
446
- return f
447
- return wrapper
416
+ """
417
+ Decorator function used to define a user expression function.
418
+
419
+ Custom functions should take (values, feature, parent) as args,
420
+ they can also shortcut naming feature and parent args by using *args
421
+ if they are not needed in the function.
422
+
423
+ Functions should return a value compatible with QVariant
424
+
425
+ Eval errors can be raised using parent.setEvalErrorString()
426
+
427
+ Functions must be unregistered when no longer needed using
428
+ QgsExpression.unregisterFunction
429
+
430
+ Example:
431
+ @qgsfunction(2, 'test'):
432
+ def add(values, feature, parent):
433
+ pass
434
+
435
+ Will create and register a function in QgsExpression called 'add' in the
436
+ 'test' group that takes two arguments.
437
+
438
+ or not using feature and parent:
439
+
440
+ @qgsfunction(2, 'test'):
441
+ def add(values, *args):
442
+ pass
443
+ """
444
+ helptemplate = Template ("""<h3>$name function</h3><br>$doc""" )
445
+
446
+ class QgsExpressionFunction (QgsExpression .Function ):
447
+ def __init__ (self , name , args , group , helptext = '' , usesgeometry = False ):
448
+ QgsExpression .Function .__init__ (self , name , args , group , helptext , usesgeometry )
449
+
450
+ def func (self , values , feature , parent ):
451
+ pass
452
+
453
+ def wrapper (func ):
454
+ name = kwargs .get ('name' , func .__name__ )
455
+ usesgeometry = kwargs .get ('usesgeometry' , False )
456
+ help = func .__doc__ or ''
457
+ help = help .strip ()
458
+ if args == 0 and not name [0 ] == '$' :
459
+ name = '${0}' .format (name )
460
+ func .__name__ = name
461
+ help = helptemplate .safe_substitute (name = name , doc = help )
462
+ f = QgsExpressionFunction (name , args , group , help , usesgeometry )
463
+ f .func = func
464
+ register = kwargs .get ('register' , True )
465
+ if register :
466
+ QgsExpression .registerFunction (f )
467
+ return f
468
+
469
+ return wrapper
448
470
449
471
#######################
450
472
# SERVER PLUGINS
@@ -464,37 +486,39 @@ def wrapper(func):
464
486
# initialize 'serverIface' object
465
487
serverIface = None
466
488
489
+
467
490
def initServerInterface (pointer ):
468
- from qgis .server import QgsServerInterface
469
- from sip import wrapinstance
470
- global serverIface
471
- serverIface = wrapinstance (pointer , QgsServerInterface )
491
+ from qgis .server import QgsServerInterface
492
+ from sip import wrapinstance
472
493
494
+ global serverIface
495
+ serverIface = wrapinstance (pointer , QgsServerInterface )
473
496
474
497
475
498
def startServerPlugin (packageName ):
476
- """ initialize the plugin """
477
- global server_plugins , server_active_plugins , serverIface
499
+ """ initialize the plugin """
500
+ global server_plugins , server_active_plugins , serverIface
478
501
479
- if packageName in server_active_plugins : return False
480
- if packageName not in sys .modules : return False
502
+ if packageName in server_active_plugins : return False
503
+ if packageName not in sys .modules : return False
481
504
482
- package = sys .modules [packageName ]
505
+ package = sys .modules [packageName ]
483
506
484
- errMsg = QCoreApplication .translate ("Python" , "Couldn't load server plugin %s" ) % packageName
507
+ errMsg = QCoreApplication .translate ("Python" , "Couldn't load server plugin %s" ) % packageName
485
508
486
- # create an instance of the plugin
487
- try :
488
- server_plugins [packageName ] = package .serverClassFactory (serverIface )
489
- except :
490
- _unloadPluginModules (packageName )
491
- msg = QCoreApplication .translate ("Python" , "%s due to an error when calling its serverClassFactory() method" ) % errMsg
492
- showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
493
- return False
494
-
495
- # add to active plugins
496
- server_active_plugins .append (packageName )
497
- return True
509
+ # create an instance of the plugin
510
+ try :
511
+ server_plugins [packageName ] = package .serverClassFactory (serverIface )
512
+ except :
513
+ _unloadPluginModules (packageName )
514
+ msg = QCoreApplication .translate ("Python" ,
515
+ "%s due to an error when calling its serverClassFactory() method" ) % errMsg
516
+ showException (sys .exc_type , sys .exc_value , sys .exc_traceback , msg )
517
+ return False
518
+
519
+ # add to active plugins
520
+ server_active_plugins .append (packageName )
521
+ return True
498
522
499
523
500
524
#######################
@@ -503,27 +527,29 @@ def startServerPlugin(packageName):
503
527
import __builtin__
504
528
505
529
_builtin_import = __builtin__ .__import__
506
- _plugin_modules = { }
530
+ _plugin_modules = {}
531
+
507
532
508
533
def _import (name , globals = {}, locals = {}, fromlist = [], level = - 1 ):
509
- """ wrapper around builtin import that keeps track of loaded plugin modules """
510
- mod = _builtin_import (name , globals , locals , fromlist , level )
511
-
512
- if mod and '__file__' in mod .__dict__ :
513
- module_name = mod .__name__
514
- package_name = module_name .split ('.' )[0 ]
515
- # check whether the module belongs to one of our plugins
516
- if package_name in available_plugins :
517
- if package_name not in _plugin_modules :
518
- _plugin_modules [package_name ] = set ()
519
- _plugin_modules [package_name ].add (module_name )
520
- # check the fromlist for additional modules (from X import Y,Z)
521
- if fromlist :
522
- for fromitem in fromlist :
523
- frmod = module_name + "." + fromitem
524
- if frmod in sys .modules :
525
- _plugin_modules [package_name ].add (frmod )
526
-
527
- return mod
534
+ """ wrapper around builtin import that keeps track of loaded plugin modules """
535
+ mod = _builtin_import (name , globals , locals , fromlist , level )
536
+
537
+ if mod and '__file__' in mod .__dict__ :
538
+ module_name = mod .__name__
539
+ package_name = module_name .split ('.' )[0 ]
540
+ # check whether the module belongs to one of our plugins
541
+ if package_name in available_plugins :
542
+ if package_name not in _plugin_modules :
543
+ _plugin_modules [package_name ] = set ()
544
+ _plugin_modules [package_name ].add (module_name )
545
+ # check the fromlist for additional modules (from X import Y,Z)
546
+ if fromlist :
547
+ for fromitem in fromlist :
548
+ frmod = module_name + "." + fromitem
549
+ if frmod in sys .modules :
550
+ _plugin_modules [package_name ].add (frmod )
551
+
552
+ return mod
553
+
528
554
529
555
__builtin__ .__import__ = _import
0 commit comments