Adding length() YAQL function

* Switched YAQL to version 0.2.3
* Refactored expressions to use custome YAQL contexts
  with additional functions
* Added unit tests

Change-Id: I12f4d56308a011a3a588028df20becb519e2e684
This commit is contained in:
Renat Akhmerov 2014-10-09 14:19:35 +07:00
parent 143702e0f0
commit f779dbaf29
4 changed files with 56 additions and 7 deletions

View File

@ -21,6 +21,7 @@ import six
import yaql import yaql
from mistral.openstack.common import log as logging from mistral.openstack.common import log as logging
from mistral import yaql_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -56,11 +57,14 @@ class Evaluator(object):
class YAQLEvaluator(Evaluator): class YAQLEvaluator(Evaluator):
@classmethod @classmethod
def evaluate(cls, expression, context): def evaluate(cls, expression, data_context):
LOG.debug("Evaluating YAQL expression [expression='%s', context=%s]" LOG.debug("Evaluating YAQL expression [expression='%s', context=%s]"
% (expression, context)) % (expression, data_context))
return yaql.parse(expression).evaluate(context) return yaql.parse(expression).evaluate(
data=data_context,
context=yaql_utils.create_yaql_context()
)
@classmethod @classmethod
def is_expression(cls, s): def is_expression(cls, s):
@ -74,10 +78,10 @@ class InlineYAQLEvaluator(YAQLEvaluator):
find_expression_pattern = re.compile("\{\$\.*[^\}]*\}") find_expression_pattern = re.compile("\{\$\.*[^\}]*\}")
@classmethod @classmethod
def evaluate(cls, expression, context): def evaluate(cls, expression, data_context):
if super(InlineYAQLEvaluator, cls).is_expression(expression): if super(InlineYAQLEvaluator, cls).is_expression(expression):
return super(InlineYAQLEvaluator, return super(InlineYAQLEvaluator,
cls).evaluate(expression, context) cls).evaluate(expression, data_context)
result = expression result = expression
found_expressions = cls.find_inline_expressions(expression) found_expressions = cls.find_inline_expressions(expression)
@ -86,7 +90,7 @@ class InlineYAQLEvaluator(YAQLEvaluator):
for expr in found_expressions: for expr in found_expressions:
trim_expr = expr.strip("{}") trim_expr = expr.strip("{}")
evaluated = super(InlineYAQLEvaluator, evaluated = super(InlineYAQLEvaluator,
cls).evaluate(trim_expr, context) cls).evaluate(trim_expr, data_context)
replacement = str(evaluated) if evaluated else expr replacement = str(evaluated) if evaluated else expr
result = result.replace(expr, replacement) result = result.replace(expr, replacement)

View File

@ -138,3 +138,11 @@ class YaqlEvaluatorTest(base.BaseTest):
}, },
applied applied
) )
def test_function_length(self):
self.assertEqual(3, expr.evaluate('$.length()', [1, 2, 3]))
self.assertEqual(2, expr.evaluate('$.length()', ['one', 'two']))
self.assertEqual(4, expr.evaluate(
'$.array.length()',
{'array': ['1', '2', '3', '4']})
)

37
mistral/yaql_utils.py Normal file
View File

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
#
# Copyright 2014 - Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import yaql
def create_yaql_context():
ctx = yaql.create_context()
_register_functions(ctx)
return ctx
def _register_functions(yaql_ctx):
yaql_ctx.register_function(length, 'length')
yaql_ctx.register_function(length, 'size')
# Additional convenience YAQL functions.
def length(a):
return len(a())

View File

@ -24,7 +24,7 @@ networkx>=1.8
six>=1.7.0 six>=1.7.0
SQLAlchemy>=0.8.4,<=0.8.99,>=0.9.7,<=0.9.99 SQLAlchemy>=0.8.4,<=0.8.99,>=0.9.7,<=0.9.99
stevedore>=1.0.0 # Apache-2.0 stevedore>=1.0.0 # Apache-2.0
yaql==0.2.1 # This is not in global requirements yaql==0.2.3 # This is not in global requirements
jsonschema>=2.0.0,<3.0.0 jsonschema>=2.0.0,<3.0.0
mock>=1.0 mock>=1.0
keystonemiddleware>=1.0.0 keystonemiddleware>=1.0.0