From 6a17a60ae23a0b7010682d91aa7fa2de795bd748 Mon Sep 17 00:00:00 2001 From: Nathan Woodrow Date: Sat, 29 Nov 2014 18:37:23 +1000 Subject: [PATCH] Move qgsfunction to qgis.core. Add new register_function method when not using decorator Wrap function call in try block to catch and report errors --- python/core/__init__.py | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/python/core/__init__.py b/python/core/__init__.py index cbb1303c357..0263f39f7a1 100644 --- a/python/core/__init__.py +++ b/python/core/__init__.py @@ -1 +1,89 @@ +import string from qgis._core import * + + +def register_function(function, arg_count, group, usesgeometry=False, **kwargs): + """ + Register a Python function to be used as a expression function. + + Functions should take (values, feature, parent) as args: + + Example: + def myfunc(values, feature, parent): + pass + + They can also shortcut naming feature and parent args by using *args + if they are not needed in the function. + + Example: + def myfunc(values, *args): + pass + + Functions should return a value compatible with QVariant + + Eval errors can be raised using parent.setEvalErrorString("Error message") + + :param function: + :param arg_count: + :param group: + :param usesgeometry: + :return: + """ + class QgsExpressionFunction(QgsExpression.Function): + def __init__(self, func, name, args, group, helptext='', usesgeometry=False): + QgsExpression.Function.__init__(self, name, args, group, helptext, usesgeometry) + self.function = func + + def func(self, values, feature, parent): + try: + return self.function(values, feature, parent) + except Exception as ex: + parent.setEvalErrorString(ex.message) + + helptemplate = string.Template("""

$name function


$doc""") + name = kwargs.get('name', function.__name__) + helptext = function.__doc__ or '' + helptext = helptext.strip() + if arg_count == 0 and not name[0] == '$': + name = '${0}'.format(name) + + if QgsExpression.isFunctionName(name): + if not QgsExpression.unregisterFunction(name): + raise TypeError("Unable to unregister function") + + function.__name__ = name + helptext = helptemplate.safe_substitute(name=name, doc=helptext) + f = QgsExpressionFunction(function, name, arg_count, group, helptext, usesgeometry) + + # This doesn't really make any sense here but does when used from a decorator context + # so it can stay. + register = kwargs.get('register', True) + if register: + QgsExpression.registerFunction(f) + return f + + +def qgsfunction(args, group, **kwargs): + """ + Decorator function used to define a user expression function. + + Example: + @qgsfunction(2, 'test'): + def add(values, feature, parent): + pass + + Will create and register a function in QgsExpression called 'add' in the + 'test' group that takes two arguments. + + or not using feature and parent: + + Example: + @qgsfunction(2, 'test'): + def add(values, *args): + pass + """ + + def wrapper(func): + usesgeometry = kwargs.get('usesgeometry', False) + return register_function(func, args, group, usesgeometry, **kwargs) + return wrapper