Beispiel #1
0
    def test_nullable_collections(self):
        @specs.parameter('arg', yaqltypes.Sequence())
        def foo1(arg):
            return arg is None

        @specs.parameter('arg', yaqltypes.Sequence(nullable=True))
        def foo2(arg):
            return arg is None

        @specs.parameter('arg', yaqltypes.Iterable())
        def bar1(arg):
            return arg is None

        @specs.parameter('arg', yaqltypes.Iterable(nullable=True))
        def bar2(arg):
            return arg is None

        @specs.parameter('arg', yaqltypes.Iterator())
        def baz1(arg):
            return arg is None

        @specs.parameter('arg', yaqltypes.Iterator(nullable=True))
        def baz2(arg):
            return arg is None

        for func in (foo1, foo2, bar1, bar2, baz1, baz2):
            self.context.register_function(func)

        self.assertFalse(self.eval('foo1([1, 2])'))
        self.assertRaises(exceptions.NoMatchingFunctionException, self.eval,
                          'foo1(null)')
        self.assertFalse(self.eval('foo2([1, 2])'))
        self.assertTrue(self.eval('foo2(null)'))

        self.assertFalse(self.eval('bar1([1, 2])'))
        self.assertRaises(exceptions.NoMatchingFunctionException, self.eval,
                          'bar1(null)')
        self.assertFalse(self.eval('bar2([1, 2])'))
        self.assertTrue(self.eval('bar2(null)'))

        self.assertFalse(self.eval('baz1($)', data=iter([1, 2])))
        self.assertRaises(exceptions.NoMatchingFunctionException, self.eval,
                          'baz1(null)')
        self.assertFalse(self.eval('baz2($)', data=iter([1, 2])))
        self.assertTrue(self.eval('baz2(null)'))
Beispiel #2
0
def class_factory(context):
    """Factory for class() contract function that generates schema instead"""
    @specs.parameter('schema', Schema)
    @specs.parameter('name',
                     dsl.MuranoTypeParameter(nullable=False, context=context))
    @specs.parameter('default_name',
                     dsl.MuranoTypeParameter(nullable=True, context=context))
    @specs.parameter('version_spec', yaqltypes.String(True))
    @specs.method
    def class_(schema, name, default_name=None, version_spec=None):
        types = 'muranoObject'
        if '_notNull' not in schema.data:
            types = [types] + ['null']

        return Schema({'type': types, 'muranoType': name.type.name})

    @specs.parameter('schema', Schema)
    @specs.parameter('type_',
                     dsl.MuranoTypeParameter(nullable=False, context=context))
    @specs.parameter('default_type',
                     dsl.MuranoTypeParameter(nullable=True, context=context))
    @specs.parameter('version_spec', yaqltypes.String(True))
    @specs.parameter('exclude_properties', yaqltypes.Sequence(nullable=True))
    @specs.method
    def template(schema,
                 type_,
                 exclude_properties=None,
                 default_type=None,
                 version_spec=None):
        result = class_(schema, type_, default_type, version_spec)
        result.data['owned'] = True
        if exclude_properties:
            result.data['excludedProperties'] = exclude_properties
        return result

    return class_, template
Beispiel #3
0
@specs.parameter('d', utils.MappingType, alias='dict')
@specs.name('values')
@specs.method
def dict_values(d):
    return six.itervalues(d)


@specs.parameter('d', utils.MappingType, alias='dict')
@specs.name('items')
@specs.method
def dict_items(d):
    return six.iteritems(d)


@specs.parameter('lst', yaqltypes.Sequence(), alias='list')
@specs.parameter('index', int, nullable=False)
@specs.name('#indexer')
def list_indexer(lst, index):
    return lst[index]


@specs.parameter('value', nullable=True)
@specs.parameter('collection', yaqltypes.Iterable())
@specs.name('#operator_in')
def in_(value, collection):
    return value in collection


@specs.parameter('value', nullable=True)
@specs.parameter('collection', yaqltypes.Iterable())
Beispiel #4
0
    :arg right: object property name
    :argType right: keyword
    :returnType: any

    .. code::

        yaql> now().year
        2016
    """
    func_name = '#property#{0}'.format(name)
    return func(func_name, obj)


@specs.name('call')
@specs.parameter('name', yaqltypes.String())
@specs.parameter('args', yaqltypes.Sequence())
@specs.parameter('kwargs', utils.MappingType)
def call_func(context, engine, name, args, kwargs, receiver=utils.NO_VALUE):
    """:yaql:call

    Evaluates function name with specified args and kwargs and returns the
    result.

    :signature: call(name, args, kwargs)
    :arg name: name of callable
    :argType name: string
    :arg args: sequence of items to be used for calling
    :argType args: sequence
    :arg kwargs: dictionary with kwargs to be used for calling
    :argType kwargs: mapping
    :returnType: any (callable return type)
Beispiel #5
0
class Template(contracts.ContractMethod):
    name = 'template'

    @specs.parameter('type_', dsl.MuranoTypeParameter(nullable=False,
                                                      lazy=True))
    @specs.parameter('default_type',
                     dsl.MuranoTypeParameter(nullable=True, lazy=True))
    @specs.parameter('version_spec', yaqltypes.String(True))
    @specs.parameter('exclude_properties', yaqltypes.Sequence(nullable=True))
    def __init__(self,
                 engine,
                 type_,
                 default_type=None,
                 version_spec=None,
                 exclude_properties=None):
        self.type = type_(self.context).type
        self.default_type = default_type(self.context) or self.type
        self.version_spec = version_spec
        self.exclude_properties = exclude_properties
        self.engine = engine

    def validate(self):
        if self.value is None or helpers.is_instance_of(
                self.value, self.type.name, self.version_spec
                or helpers.get_names_scope(self.root_context)):
            return self.value
        if not isinstance(
                self.value,
            (dsl_types.MuranoObject, dsl_types.MuranoObjectInterface)):
            raise exceptions.ContractViolationException(
                'Value is not an object')
        raise exceptions.ContractViolationException(
            'Object of type {0} is not compatible with '
            'requested type {1}'.format(self.value.type, self.type))

    def check_type(self):
        if isinstance(self.value, utils.MappingType):
            return self.value
        return self.validate()

    def transform(self):
        object_store = helpers.get_object_store()
        if self.value is None:
            return None
        if isinstance(self.value, dsl_types.MuranoObject):
            obj = self.value
        elif isinstance(self.value, dsl_types.MuranoObjectInterface):
            obj = self.value.object
        elif isinstance(self.value, utils.MappingType):
            passkey = utils.create_marker('<Contract Passkey>')
            if self.exclude_properties:
                parsed = helpers.parse_object_definition(
                    self.value, self.calling_type, self.context)
                props = dsl.to_mutable(parsed['properties'], self.engine)
                for p in self.exclude_properties:
                    helpers.patch_dict(props, p, passkey)
                parsed['properties'] = props
                value = helpers.assemble_object_definition(parsed)
            else:
                value = self.value
            with helpers.thread_local_attribute(constants.TL_CONTRACT_PASSKEY,
                                                passkey):
                with helpers.thread_local_attribute(
                        constants.TL_OBJECTS_DRY_RUN, True):
                    obj = object_store.load(value,
                                            self.owner,
                                            context=self.context,
                                            default_type=self.default_type,
                                            scope_type=self.calling_type)
                    obj.__passkey__ = passkey
        else:
            raise exceptions.ContractViolationException(
                'Value {0} cannot be represented as class {1}'.format(
                    helpers.format_scalar(self.value), self.type))
        self.value = obj
        return self.validate()

    def finalize(self):
        if self.value is None:
            return None
        object_store = helpers.get_object_store()
        if object_store.initializing:
            return {}
        passkey = getattr(self.value, '__passkey__', None)
        with helpers.thread_local_attribute(constants.TL_CONTRACT_PASSKEY,
                                            passkey):
            result = serializer.serialize(self.value.real_this,
                                          object_store.executor,
                                          dsl_types.DumpTypes.Mixed)
            if self.exclude_properties:
                for p in self.exclude_properties:
                    helpers.patch_dict(result, p, utils.NO_VALUE)
            return result

    def generate_schema(self):
        result = Class.generate_class_schema(self.value, self.type)
        result['owned'] = True
        if self.exclude_properties:
            result['excludedProperties'] = self.exclude_properties
        return result
Beispiel #6
0
    def prepare_transform_context(root_context, this, owner, default,
                                  calling_type):
        @specs.parameter('value', nullable=True)
        @specs.method
        def int_(value):
            if value is dsl.NO_VALUE:
                value = default
            if value is None:
                return None
            try:
                return int(value)
            except Exception:
                raise exceptions.ContractViolationException(
                    'Value {0} violates int() contract'.format(
                        format_scalar(value)))

        @specs.parameter('value', nullable=True)
        @specs.method
        def string(value):
            if value is dsl.NO_VALUE:
                value = default
            if value is None:
                return None
            try:
                return six.text_type(value)
            except Exception:
                raise exceptions.ContractViolationException(
                    'Value {0} violates string() contract'.format(
                        format_scalar(value)))

        @specs.parameter('value', nullable=True)
        @specs.method
        def bool_(value):
            if value is dsl.NO_VALUE:
                value = default
            if value is None:
                return None
            return True if value else False

        @specs.parameter('value', nullable=True)
        @specs.method
        def not_null(value):
            if isinstance(value, TypeScheme.ObjRef):
                return value

            if value is None:
                raise exceptions.ContractViolationException(
                    'null value violates notNull() contract')
            return value

        @specs.parameter('value', nullable=True)
        @specs.method
        def error(value):
            raise exceptions.ContractViolationException('error() contract')

        @specs.parameter('value', nullable=True)
        @specs.parameter('predicate', yaqltypes.Lambda(with_context=True))
        @specs.parameter('msg', yaqltypes.String(nullable=True))
        @specs.method
        def check(value, predicate, msg=None):
            if isinstance(value, TypeScheme.ObjRef) or predicate(
                    root_context.create_child_context(), value):
                return value
            else:
                if not msg:
                    msg = "Value {0} doesn't match predicate".format(
                        format_scalar(value))
                raise exceptions.ContractViolationException(msg)

        @specs.parameter('obj', TypeScheme.ObjRef, nullable=True)
        @specs.name('owned')
        @specs.method
        def owned_ref(obj):
            if obj is None:
                return None
            if isinstance(obj, TypeScheme.ObjRef):
                return obj

        @specs.parameter('obj', dsl_types.MuranoObject)
        @specs.method
        def owned(obj):
            p = obj.owner
            while p is not None:
                if p is this:
                    return obj
                p = p.owner

            raise exceptions.ContractViolationException(
                'Object {0} violates owned() contract'.format(obj))

        @specs.parameter('obj', TypeScheme.ObjRef, nullable=True)
        @specs.name('not_owned')
        @specs.method
        def not_owned_ref(obj):
            if isinstance(obj, TypeScheme.ObjRef):
                return obj

            if obj is None:
                return None

        @specs.parameter('obj', dsl_types.MuranoObject)
        @specs.method
        def not_owned(obj):
            try:
                owned(obj)
            except exceptions.ContractViolationException:
                return obj
            else:
                raise exceptions.ContractViolationException(
                    'Object {0} violates notOwned() contract'.format(obj))

        @specs.parameter('name',
                         dsl.MuranoTypeParameter(nullable=False,
                                                 context=root_context))
        @specs.parameter('default_name',
                         dsl.MuranoTypeParameter(nullable=True,
                                                 context=root_context))
        @specs.parameter('value', nullable=True)
        @specs.parameter('version_spec', yaqltypes.String(True))
        @specs.method
        def class_(value, name, default_name=None, version_spec=None):
            object_store = helpers.get_object_store()
            if not default_name:
                default_name = name
            murano_class = name.type
            if isinstance(value, TypeScheme.ObjRef):
                value = value.object_id
            if value is None:
                return None
            if isinstance(value, dsl_types.MuranoObject):
                obj = value
            elif isinstance(value, dsl_types.MuranoObjectInterface):
                obj = value.object
            elif isinstance(value, utils.MappingType):
                obj = object_store.load(value,
                                        owner,
                                        context=root_context,
                                        default_type=default_name,
                                        scope_type=calling_type)
            elif isinstance(value, six.string_types):
                obj = object_store.get(value)
                if obj is None:
                    if not object_store.initializing:
                        raise exceptions.NoObjectFoundError(value)
                    else:
                        return TypeScheme.ObjRef(value)
            else:
                raise exceptions.ContractViolationException(
                    'Value {0} cannot be represented as class {1}'.format(
                        format_scalar(value), name))
            if not helpers.is_instance_of(
                    obj, murano_class.name, version_spec
                    or helpers.get_type(root_context)):
                raise exceptions.ContractViolationException(
                    'Object of type {0} is not compatible with '
                    'requested type {1}'.format(obj.type.name, murano_class))
            return obj

        @specs.parameter('type_',
                         dsl.MuranoTypeParameter(nullable=False,
                                                 context=root_context))
        @specs.parameter('default_type',
                         dsl.MuranoTypeParameter(nullable=True,
                                                 context=root_context))
        @specs.parameter('value', nullable=True)
        @specs.parameter('version_spec', yaqltypes.String(True))
        @specs.parameter('exclude_properties',
                         yaqltypes.Sequence(nullable=True))
        @specs.method
        def template(engine,
                     value,
                     type_,
                     exclude_properties=None,
                     default_type=None,
                     version_spec=None):
            object_store = helpers.get_object_store()
            passkey = None
            if not default_type:
                default_type = type_
            murano_class = type_.type
            if value is None:
                return None
            if isinstance(value, dsl_types.MuranoObject):
                obj = value
            elif isinstance(value, dsl_types.MuranoObjectInterface):
                obj = value.object
            elif isinstance(value, utils.MappingType):
                passkey = utils.create_marker('<Contract Passkey>')
                if exclude_properties:
                    parsed = helpers.parse_object_definition(
                        value, calling_type, context)
                    props = dsl.to_mutable(parsed['properties'], engine)
                    for p in exclude_properties:
                        helpers.patch_dict(props, p, passkey)
                    parsed['properties'] = props
                    value = helpers.assemble_object_definition(parsed)
                with helpers.thread_local_attribute(
                        constants.TL_CONTRACT_PASSKEY, passkey):
                    with helpers.thread_local_attribute(
                            constants.TL_OBJECTS_DRY_RUN, True):
                        obj = object_store.load(value,
                                                owner,
                                                context=context,
                                                default_type=default_type,
                                                scope_type=calling_type)
            else:
                raise exceptions.ContractViolationException(
                    'Value {0} cannot be represented as class {1}'.format(
                        format_scalar(value), type_))
            if not helpers.is_instance_of(
                    obj, murano_class.name, version_spec
                    or helpers.get_type(root_context)):
                raise exceptions.ContractViolationException(
                    'Object of type {0} is not compatible with '
                    'requested type {1}'.format(obj.type.name, type_))

            with helpers.thread_local_attribute(constants.TL_CONTRACT_PASSKEY,
                                                passkey):
                result = serializer.serialize(obj.real_this,
                                              object_store.executor,
                                              dsl_types.DumpTypes.Mixed)
                if exclude_properties:
                    for p in exclude_properties:
                        helpers.patch_dict(result, p, utils.NO_VALUE)
                return result

        context = root_context.create_child_context()
        context.register_function(int_)
        context.register_function(string)
        context.register_function(bool_)
        context.register_function(check)
        context.register_function(not_null)
        context.register_function(error)
        context.register_function(class_)
        context.register_function(template)
        context.register_function(owned_ref)
        context.register_function(owned)
        context.register_function(not_owned_ref)
        context.register_function(not_owned)
        return context
Beispiel #7
0
    def prepare_validate_context(root_context):
        @specs.parameter('value', nullable=True)
        @specs.method
        def int_(value):
            if value is None or isinstance(
                    value, int) and not isinstance(value, bool):
                return value
            raise exceptions.ContractViolationException()

        @specs.parameter('value', nullable=True)
        @specs.method
        def string(value):
            if value is None or isinstance(value, six.string_types):
                return value
            raise exceptions.ContractViolationException()

        @specs.parameter('value', nullable=True)
        @specs.method
        def bool_(value):
            if value is None or isinstance(value, bool):
                return value
            raise exceptions.ContractViolationException()

        @specs.parameter('value', nullable=True)
        @specs.method
        def not_null(value):
            if value is None:
                raise exceptions.ContractViolationException()
            return value

        @specs.parameter('value', nullable=True)
        @specs.parameter('predicate', yaqltypes.Lambda(with_context=True))
        @specs.method
        def check(value, predicate):
            if predicate(root_context.create_child_context(), value):
                return value
            raise exceptions.ContractViolationException()

        @specs.parameter('type',
                         dsl.MuranoTypeParameter(nullable=False,
                                                 context=root_context))
        @specs.parameter('value', nullable=True)
        @specs.parameter('version_spec', yaqltypes.String(True))
        @specs.method
        def class_(value, type, version_spec=None):
            if value is None or helpers.is_instance_of(
                    value, type.type.name, version_spec
                    or helpers.get_names_scope(root_context)):
                return value
            raise exceptions.ContractViolationException()

        @specs.parameter('type_',
                         dsl.MuranoTypeParameter(nullable=False,
                                                 context=root_context))
        @specs.parameter('default_type',
                         dsl.MuranoTypeParameter(nullable=True,
                                                 context=root_context))
        @specs.parameter('value', nullable=True)
        @specs.parameter('version_spec', yaqltypes.String(True))
        @specs.parameter('exclude_properties',
                         yaqltypes.Sequence(nullable=True))
        @specs.method
        def template(value,
                     type_,
                     exclude_properties=None,
                     default_type=None,
                     version_spec=None):

            if value is None or isinstance(value, utils.MappingType):
                return value

            if helpers.is_instance_of(
                    value, type_.type.name, version_spec
                    or helpers.get_names_scope(root_context)):
                return value
            raise exceptions.ContractViolationException()

        context = root_context.create_child_context()
        context.register_function(int_)
        context.register_function(string)
        context.register_function(bool_)
        context.register_function(check)
        context.register_function(not_null)
        context.register_function(class_)
        context.register_function(template)
        return context