Ejemplo n.º 1
0
def evaluate_constant(expr, engine, context):
    """Evaluate yaql expression into constant value if possible"""
    if isinstance(expr, expressions.Constant):
        return expr.value
    context = context.create_child_context()
    trap = utils.create_marker('trap')
    context['$'] = trap

    @specs.parameter('name', yaqltypes.StringConstant())
    @specs.name('#get_context_data')
    def get_context_data(name, context):
        res = context[name]
        if res is trap:
            raise yaql_exceptions.ResolutionError()
        return res

    context.register_function(get_context_data)

    try:
        return expressions.Statement(expr, engine).evaluate(context=context)
    except yaql_exceptions.YaqlException:
        return None
Ejemplo n.º 2
0
    def test_string_constant_function(self):
        @specs.parameter('arg', yaqltypes.StringConstant())
        def foo(arg):
            return arg

        context = self.context.create_child_context()
        context.register_function(foo)

        self.assertEqual('qw', self.eval('foo(qw)', context=context))
        self.assertEqual('q w', self.eval('foo("q w")', context=context))
        self.assertRaises(exceptions.NoMatchingFunctionException,
                          self.eval,
                          'foo($)',
                          context=context,
                          data='asd')
        self.assertRaises(exceptions.NoMatchingFunctionException,
                          self.eval,
                          'foo(123)',
                          context=context)
        self.assertRaises(exceptions.NoMatchingFunctionException,
                          self.eval,
                          'foo(null)',
                          context=context)
Ejemplo n.º 3
0
    def _create_context(self, root_context):
        @specs.parameter('name', yaqltypes.StringConstant())
        def get_context_data(name):
            def set_data(value):
                if not name or name == '$' or name == '$this':
                    raise ValueError('Cannot assign to {0}'.format(name))
                ctx = root_context
                while constants.CTX_VARIABLE_SCOPE not in ctx:
                    ctx = ctx.parent
                ctx[name] = value

            return LhsExpression.Property(lambda: root_context[name], set_data)

        @specs.parameter('this', LhsExpression.Property)
        @specs.parameter('key', yaqltypes.Keyword())
        def attribution(this, key):
            def setter(src_property, value):
                src = src_property.get()
                if isinstance(src, utils.MappingType):
                    src_property.set(
                        utils.FrozenDict(
                            itertools.chain(six.iteritems(src),
                                            ((key, value), ))))
                elif isinstance(src, dsl_types.MuranoObject):
                    src.set_property(key, value, root_context)
                elif isinstance(
                        src,
                    (dsl_types.MuranoTypeReference, dsl_types.MuranoType)):
                    if isinstance(src, dsl_types.MuranoTypeReference):
                        mc = src.type
                    else:
                        mc = src
                    mc.set_property(key, value, root_context)
                else:
                    raise ValueError('attribution may only be applied to '
                                     'objects and dictionaries')

            def getter(src):
                if isinstance(src, utils.MappingType):
                    return src.get(key, {})
                elif isinstance(src, dsl_types.MuranoObject):
                    self._current_obj = src
                    self._current_obj_name = key
                    try:
                        return src.get_property(key, root_context)
                    except exceptions.UninitializedPropertyAccessError:
                        return {}

                else:
                    raise ValueError('attribution may only be applied to '
                                     'objects and dictionaries')

            return LhsExpression.Property(lambda: getter(this.get()),
                                          lambda value: setter(this, value))

        @specs.parameter('this', LhsExpression.Property)
        @specs.parameter('index', yaqltypes.Lambda(with_context=True))
        def indexation(this, index):
            index = index(root_context)

            def getter(src):
                if utils.is_sequence(src):
                    return src[index]
                else:
                    raise ValueError('indexation may only be applied to lists')

            def setter(src_property, value):
                src = src_property.get()
                if utils.is_sequence(src):
                    src_property.set(src[:index] + (value, ) + src[index + 1:])
                elif isinstance(src, utils.MappingType):
                    attribution(src_property, index).set(value)

            if isinstance(index, int):
                return LhsExpression.Property(
                    lambda: getter(this.get()),
                    lambda value: setter(this, value))
            else:
                return attribution(this, index)

        def _wrap_type_reference(tr):
            return LhsExpression.Property(lambda: tr, self._invalid_target)

        @specs.parameter('prefix', yaqltypes.Keyword())
        @specs.parameter('name', yaqltypes.Keyword())
        @specs.name('#operator_:')
        def ns_resolve(prefix, name):
            return _wrap_type_reference(
                yaql_functions.ns_resolve(context, prefix, name))

        @specs.parameter('name', yaqltypes.Keyword())
        @specs.name('#unary_operator_:')
        def ns_resolve_unary(context, name):
            return _wrap_type_reference(
                yaql_functions.ns_resolve_unary(context, name))

        @specs.parameter('object_', dsl_types.MuranoObject)
        def type_(object_):
            return _wrap_type_reference(yaql_functions.type_(object_))

        @specs.name('type')
        @specs.parameter('cls', dsl.MuranoTypeParameter())
        def type_from_name(cls):
            return _wrap_type_reference(cls)

        context = yaql_integration.create_empty_context()
        context.register_function(get_context_data, '#get_context_data')
        context.register_function(attribution, '#operator_.')
        context.register_function(indexation, '#indexer')
        context.register_function(ns_resolve)
        context.register_function(ns_resolve_unary)
        context.register_function(type_)
        context.register_function(type_from_name)
        return context
Ejemplo n.º 4
0
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.
"""
The module describes main system functions for working with objects.
"""

import itertools

from yaql.language import contexts
from yaql.language import specs
from yaql.language import utils
from yaql.language import yaqltypes


@specs.parameter('name', yaqltypes.StringConstant())
@specs.name('#get_context_data')
def get_context_data(name, context):
    """:yaql:getContextData

    Returns the context value by its name. This function is system
    and can be overridden to change the way of getting context data.

    :signature: getContextData(name)
    :arg name: value's key name
    :argType name: string
    :returnType: any (value type)
    """
    return context[name]

Ejemplo n.º 5
0
    def _create_context(self, root_context):
        @specs.parameter('name', yaqltypes.StringConstant())
        def get_context_data(name):

            def set_data(value):
                if not name or name == '$' or name == '$this':
                    raise ValueError('Cannot assign to {0}'.format(name))
                ctx = root_context
                while constants.CTX_VARIABLE_SCOPE not in ctx:
                    ctx = ctx.parent
                ctx[name] = value

            return LhsExpression.Property(
                lambda: root_context[name], set_data)

        @specs.parameter('this', LhsExpression.Property)
        @specs.parameter('key', yaqltypes.Keyword())
        def attribution(this, key):
            def setter(src_property, value):
                src = src_property.get()
                if isinstance(src, utils.MappingType):
                    src_property.set(
                        utils.FrozenDict(
                            itertools.chain(
                                src.iteritems(),
                                ((key, value),))))
                elif isinstance(src, dsl_types.MuranoObject):
                    src.set_property(key, value, root_context)
                else:
                    raise ValueError(
                        'attribution may only be applied to '
                        'objects and dictionaries')

            def getter(src):
                if isinstance(src, utils.MappingType):
                    return src.get(key, {})
                elif isinstance(src, dsl_types.MuranoObject):
                    self._current_obj = src
                    self._current_obj_name = key
                    try:
                        return src.get_property(key, root_context)
                    except exceptions.UninitializedPropertyAccessError:
                        return {}

                else:
                    raise ValueError(
                        'attribution may only be applied to '
                        'objects and dictionaries')

            return LhsExpression.Property(
                lambda: getter(this.get()),
                lambda value: setter(this, value))

        @specs.parameter('this', LhsExpression.Property)
        @specs.parameter('index', yaqltypes.Lambda(with_context=True))
        def indexation(this, index):
            index = index(root_context)

            def getter(src):
                if utils.is_sequence(src):
                    return src[index]
                else:
                    raise ValueError('indexation may only be applied to lists')

            def setter(src_property, value):
                src = src_property.get()
                if utils.is_sequence(src):
                    src_property.set(src[:index] + (value,) + src[index + 1:])

            if isinstance(index, types.IntType):
                return LhsExpression.Property(
                    lambda: getter(this.get()),
                    lambda value: setter(this, value))
            else:
                return attribution(this, index)

        context = yaql_integration.create_empty_context()
        context.register_function(get_context_data, '#get_context_data')
        context.register_function(attribution, '#operator_.')
        context.register_function(indexation, '#indexer')
        return context