Skip to content
Permalink
Browse files

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
  • Loading branch information
NathanW2 committed Nov 29, 2014
1 parent d532af0 commit 6a17a60ae23a0b7010682d91aa7fa2de795bd748
Showing with 88 additions and 0 deletions.
  1. +88 −0 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("""<h3>$name function</h3><br>$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

4 comments on commit 6a17a60

@enricofer

This comment has been minimized.

Copy link

@enricofer enricofer replied Jan 6, 2015

Registering functions seems to be changed.
Old method now try exception when using 'usesgeometry' directive:
return register_function(func, args, group, usesgeometry, **kwargs)
TypeError: register_function() got multiple values for keyword argument 'usesgeometry'

What is now the new registering method?

@enricofer

This comment has been minimized.

Copy link

@enricofer enricofer replied Jan 6, 2015

Ah! Congrats. I know you have other to think about.....

@NathanW2

This comment has been minimized.

Copy link
Member Author

@NathanW2 NathanW2 replied Jan 7, 2015

@NathanW2

This comment has been minimized.

Copy link
Member Author

@NathanW2 NathanW2 replied Jan 10, 2015

Fixed in d9042f5

Please sign in to comment.
You can’t perform that action at this time.