deb-python-yaql/yaql/language/expressions.py

172 lines
5.0 KiB
Python

# Copyright (c) 2015 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 sys
import six
import yaql
from yaql.language import exceptions
from yaql.language import utils
class Expression(object):
def __call__(self, receiver, context, engine):
pass
@six.python_2_unicode_compatible
class Function(Expression):
def __init__(self, name, *args):
self.name = name
self.args = args
self.uses_receiver = True
def __call__(self, receiver, context, engine):
return context(self.name, engine, receiver, context)(*self.args)
def __str__(self):
return u'{0}({1})'.format(self.name, ', '.join(
map(six.text_type, self.args)))
class BinaryOperator(Function):
def __init__(self, op, obj1, obj2, alias):
if alias is None:
func_name = '#operator_' + op
else:
func_name = '*' + alias
self.operator = op
super(BinaryOperator, self).__init__(func_name, obj1, obj2)
self.uses_receiver = False
class UnaryOperator(Function):
def __init__(self, op, obj, alias):
if alias is None:
func_name = '#unary_operator_' + op
else:
func_name = '*' + alias
self.operator = op
super(UnaryOperator, self).__init__(func_name, obj)
self.uses_receiver = False
class IndexExpression(Function):
def __init__(self, value, *args):
super(IndexExpression, self).__init__('#indexer', value, *args)
self.uses_receiver = False
class ListExpression(Function):
def __init__(self, *args):
super(ListExpression, self).__init__('#list', *args)
self.uses_receiver = False
class MapExpression(Function):
def __init__(self, *args):
super(MapExpression, self).__init__('#map', *args)
self.uses_receiver = False
@six.python_2_unicode_compatible
class GetContextValue(Function):
def __init__(self, path):
super(GetContextValue, self).__init__('#get_context_data', path)
self.path = path
self.uses_receiver = False
def __str__(self):
return self.path.value
@six.python_2_unicode_compatible
class Constant(Expression):
def __init__(self, value):
self.value = value
self.uses_receiver = False
def __str__(self):
if isinstance(self.value, six.text_type):
return u"'{0}'".format(self.value)
return six.text_type(self.value)
def __call__(self, receiver, context, engine):
return self.value
class KeywordConstant(Constant):
pass
@six.python_2_unicode_compatible
class Wrap(Expression):
def __init__(self, expression):
self.expr = expression
self.uses_receiver = False
def __str__(self):
return str(self.expr)
def __call__(self, receiver, context, engine):
return self.expr(receiver, context, engine)
@six.python_2_unicode_compatible
class MappingRuleExpression(Expression):
def __init__(self, source, destination):
self.source = source
self.destination = destination
self.uses_receiver = False
def __str__(self):
return u'{0} => {1}'.format(self.source, self.destination)
def __call__(self, receiver, context, engine):
return utils.MappingRule(
self.source(receiver, context, engine),
self.destination(receiver, context, engine))
@six.python_2_unicode_compatible
class Statement(Function):
def __init__(self, expression, engine):
self.expression = expression
self.uses_receiver = False
self.engine = engine
super(Statement, self).__init__('#finalize', expression)
def __call__(self, receiver, context, engine):
if not context.collect_functions('#finalize'):
context = context.create_child_context()
context.register_function(lambda x: x, name='#finalize')
try:
return super(Statement, self).__call__(receiver, context, engine)
except exceptions.WrappedException as e:
six.reraise(type(e.wrapped), e.wrapped, sys.exc_info()[2])
def evaluate(self, data=utils.NO_VALUE, context=None):
if context is None or context is utils.NO_VALUE:
context = yaql.create_context()
if data is not utils.NO_VALUE:
if self.engine.options.get('yaql.convertInputData', True):
context['$'] = utils.convert_input_data(data)
else:
context['$'] = data
return self(utils.NO_VALUE, context, self.engine)
def __str__(self):
return str(self.expression)