""" *************************************************************************** qgsfunction.py --------------------- Date : May 2018 Copyright : (C) 2018 by Denis Rouzaud Email : denis@opengis.ch *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * *************************************************************************** """ import inspect import string import traceback from qgis.PyQt.QtCore import QCoreApplication from qgis._core import QgsExpressionFunction, QgsExpression, QgsMessageLog, QgsFeatureRequest, Qgis class QgsPyExpressionFunction(QgsExpressionFunction): """Python expression function""" def __init__( self, function, name, group, helptext="", usesgeometry=False, referenced_columns=QgsFeatureRequest.ALL_ATTRIBUTES, handlesnull=False, params_as_list=False, ): # Call the parent constructor # -1 means that function can take any number of arguments QgsExpressionFunction.__init__(self, name, -1, group, helptext) self.function = function self.params_as_list = params_as_list self.usesgeometry = usesgeometry self.referenced_columns = referenced_columns self.handlesnull = handlesnull def func(self, values, context, parent, node): feature = None if context: feature = context.feature() try: # Inspect the inner function signature to get the list of parameters parameters = inspect.signature(self.function).parameters kwvalues = {} # Handle special parameters # those will not be inserted in the arguments list # if they are present in the function signature if "context" in parameters: kwvalues["context"] = context if "feature" in parameters: kwvalues["feature"] = feature if "parent" in parameters: kwvalues["parent"] = parent # In this context, values is a list of the parameters passed to the expression. # If self.params_as_list is True, values is passed as is to the inner function. if self.params_as_list: return self.function(values, **kwvalues) # Otherwise (default), the parameters are expanded return self.function(*values, **kwvalues) except Exception as ex: tb = traceback.format_exception(None, ex, ex.__traceback__) formatted_traceback = "".join(tb) formatted_exception = f"{ex}:
{formatted_traceback}"
parent.setEvalErrorString(formatted_exception)
return None
def usesGeometry(self, node):
return self.usesgeometry
def referencedColumns(self, node):
return self.referenced_columns
def handlesNull(self):
return self.handlesnull
def register_function(
function,
args="auto",
group="custom",
usesgeometry=False,
referenced_columns=[QgsFeatureRequest.ALL_ATTRIBUTES],
handlesnull=False,
params_as_list=None,
**kwargs,
):
"""
Register a Python function to be used as a expression function.
The function signature may contain special parameters (in any order at the end of the signature):
- feature: the QgsFeature related to the current evaluation
- parent: the QgsExpressionFunction parent
- context: the QgsExpressionContext related to the current evaluation
If those parameters are present in the function signature, they will be automatically passed to the function,
without the need to specify them in the expression.
Functions should return a value compatible with QVariant
Eval errors can be raised using parent.setEvalErrorString("Error message")
:param function: the Python function to be used as an expression function
:param args: DEPRECATED since QGIS 3.32. Use ``params_as_list`` if you want to pass parameters as a list.
:param group: the expression group in which the function should be added
:param usesgeometry: Defines if this expression requires the geometry. By default False.
:param referenced_columns: An array of names of fields on which this expression works. By default ``[QgsFeatureRequest.ALL_ATTRIBUTES]``. Specifying a subset of fields or an empty list will result in a faster execution.
:param handlesnull: Defines if this expression has custom handling for NULL values. If False, the result will always be NULL as soon as any parameter is NULL. False by default.
:param params_as_list: If True, the function will receive the expression parameters as a list. If False, the function will receive the parameters as individual arguments. False by default.
:Keyword Arguments:
* *register* (``bool``) --
Set to False to create the QgsPyExpressionFunction without registering it. Useful for testing puposes. By default True.
* *name* (``str``) --
If provided, replace the function name
* *helpText* (``str``) --
If provided, used in the help tooltip instead of the function docstring
:return:
"""
# Format the help text
helptemplate = string.Template("