コード例 #1
0
ファイル: assign.py プロジェクト: inmanta/inmanta-core
    def resume(
        self, requires: typing.Dict[object, object], resolver: Resolver, queue: QueueScheduler, target: ResultVariable
    ) -> None:
        root_object = self.rootobject.execute(requires, resolver, queue)

        if not isinstance(root_object, Instance):
            raise TypingException(self, "short index lookup is only possible one objects, %s is not an object" % root_object)

        from_entity = root_object.get_type()

        relation = from_entity.get_attribute(self.relation)
        if not isinstance(relation, RelationAttribute):
            raise TypingException(self, "short index lookup is only possible on relations, %s is an attribute" % relation)

        if relation.end is None:
            raise TypingException(
                self, "short index lookup is only possible on bi-drectional relations, %s is unidirectional" % relation
            )

        self.type = relation.type

        self.type.lookup_index(
            list(
                chain(
                    [(relation.end.name, root_object)],
                    ((k, v.execute(requires, resolver, queue)) for (k, v) in self.querypart),
                    ((k, v) for kwargs in self.wrapped_querypart for (k, v) in kwargs.execute(requires, resolver, queue)),
                )
            ),
            self,
            target,
        )
コード例 #2
0
ファイル: assign.py プロジェクト: wdesmedt/inmanta
    def resume(self, requires: typing.Dict[object,
                                           ResultVariable], resolver: Resolver,
               queue: QueueScheduler, target: ResultVariable) -> None:
        root_object = self.rootobject.execute(requires, resolver, queue)

        if not isinstance(root_object, Instance):
            raise TypingException(
                self,
                "short index lookup is only possible one objects, %s is not an object"
                % root_object)

        from_entity = root_object.get_type()

        relation = from_entity.get_attribute(self.relation)
        if not isinstance(relation, RelationAttribute):
            raise TypingException(
                self,
                "short index lookup is only possible on relations, %s is an attribute"
                % relation)

        self.type = relation.get_type()

        self.type.lookup_index([(relation.end.name, root_object)] +
                               [(k, v.execute(requires, resolver, queue))
                                for (k, v) in self.querypart], self, target)
コード例 #3
0
ファイル: define.py プロジェクト: wdesmedt/inmanta
    def evaluate(self):
        """
            Add this relation to the participating ends
        """
        try:
            left = self.namespace.get_type(self.left[0])
        except TypeNotFoundException as e:
            e.set_location(self.location)
            raise e

        if isinstance(left, Default):
            raise TypingException(
                self,
                "Can not define relation on a default constructor %s, use base type instead: %s " % (
                    left.name, left.get_entity().get_full_name())
            )

        if left.get_attribute_from_related(self.right[1]) is not None:
            raise DuplicateException(self, left.get_attribute_from_related(self.right[1]),
                                     ("Attribute name %s is already defined in %s, unable to define relationship")
                                     % (self.right[1], left.name))

        try:
            right = self.namespace.get_type(self.right[0])
        except TypeNotFoundException as e:
            e.set_location(self.location)
            raise e

        if isinstance(right, Default):
            raise TypingException(
                self,
                "Can not define relation on a default constructor %s, use base type instead: %s " % (
                    right.name, right.get_entity().get_full_name())
            )

        if right.get_attribute_from_related(self.left[1]) is not None:
            raise DuplicateException(self, right.get_attribute_from_related(self.left[1]),
                                     ("Attribute name %s is already defined in %s, unable to define relationship")
                                     % (self.left[1], right.name))

        if self.left[1] is not None:
            left_end = RelationAttribute(right, left, self.left[1])
            left_end.set_multiplicity(self.left[2])
            left_end.comment = self.comment
            self.copy_location(left_end)
        else:
            left_end = None

        if self.right[1] is not None:
            right_end = RelationAttribute(left, right, self.right[1])
            right_end.set_multiplicity(self.right[2])
            right_end.comment = self.comment
            self.copy_location(right_end)
        else:
            right_end = None

        if left_end is not None and right_end is not None:
            left_end.end = right_end
            right_end.end = left_end
コード例 #4
0
    def evaluate(self) -> None:
        """
            Evaluate this statement.
        """
        try:
            entity_type = self.type
            entity_type.comment = self.comment

            add_attributes = {}
            for attribute in self.attributes:
                attr_type = self.namespace.get_type(attribute.type)
                if not isinstance(attr_type, (Type, type)):
                    raise TypingException(self, "Attributes can only be a type. Entities need to be defined as relations.")

                attr_obj = Attribute(entity_type, attr_type, attribute.name, attribute.multi, attribute.nullable)
                attribute.copy_location(attr_obj)

                add_attributes[attribute.name] = attr_obj

                if attribute.default is not None:
                    entity_type.add_default_value(attribute.name, attribute.default)
                elif attribute.remove_default:
                    entity_type.add_default_value(attribute.name, None)

            if len(set(self.parents)) != len(self.parents):
                raise TypingException(self, "same parent defined twice")
            for parent in self.parents:
                parent_type = self.namespace.get_type(str(parent))
                if parent_type is self.type:
                    raise TypingException(self, "Entity can not be its own parent (%s) " % parent)
                if not isinstance(parent_type, Entity):
                    raise TypingException(self, "Parents of an entity need to be entities. "
                                          "Default constructors are not supported. %s is not an entity" % parent)

                entity_type.parent_entities.append(parent_type)
                parent_type.child_entities.append(entity_type)

            for parent_type in entity_type.get_all_parent_entities():
                for attr_name, other_attr in parent_type.attributes.items():
                    if attr_name not in add_attributes:
                        add_attributes[attr_name] = other_attr
                    else:
                        # allow compatible attributes
                        my_attr = add_attributes[attr_name]

                        if my_attr.type == other_attr.type:
                            add_attributes[attr_name] = other_attr
                        else:
                            raise DuplicateException(
                                my_attr, other_attr, "Incompatible attributes")
            # verify all attribute compatibility
        except TypeNotFoundException as e:
            e.set_statement(self)
            raise e
コード例 #5
0
ファイル: assign.py プロジェクト: inmanta/inmanta-core
    def execute(self, requires: typing.Dict[object, object], resolver: Resolver, queue: QueueScheduler) -> object:
        mapv = self.themap.execute(requires, resolver, queue)
        if not isinstance(mapv, dict):
            raise TypingException(self, "dict lookup is only possible on dicts, %s is not an object" % mapv)

        keyv = self.key.execute(requires, resolver, queue)
        if not isinstance(keyv, str):
            raise TypingException(self, "dict keys must be string, %s is not a string" % keyv)

        if keyv not in mapv:
            raise KeyException(self, "key %s not found in dict, options are [%s]" % (keyv, ",".join(mapv.keys())))

        return mapv[keyv]
コード例 #6
0
    def evaluate(self) -> None:
        """
        Evaluate this statement.
        """
        try:
            entity_type = self.namespace.get_type(self.entity)

            if not isinstance(entity_type, EntityLike):
                raise TypingException(
                    self,
                    "Implementation can only be define for an Entity, but %s is a %s"
                    % (self.entity, entity_type))

            entity_type = entity_type.get_entity()

            # If one implements statement has parent declared, set to true
            entity_type.implements_inherits |= self.inherit

            implement = Implement()
            implement.comment = self.comment
            implement.constraint = self.select
            implement.location = self.entity_location

            i = 0
            for _impl in self.implementations:
                i += 1

                # check if the implementation has the correct type
                impl_obj = self.namespace.get_type(_impl)
                assert isinstance(
                    impl_obj,
                    Implementation), "%s is not an implementation" % (_impl)

                if impl_obj.entity is not None and not (
                        entity_type is impl_obj.entity
                        or entity_type.is_parent(impl_obj.entity)):
                    raise TypingException(
                        self,
                        "Type mismatch: cannot use %s as implementation for "
                        " %s because its implementing type is %s" %
                        (impl_obj.name, entity_type, impl_obj.entity),
                    )

                # add it
                implement.implementations.append(impl_obj)

            entity_type.add_implement(implement)
        except TypeNotFoundException as e:
            e.set_statement(self)
            raise e
コード例 #7
0
    def evaluate(self) -> None:
        """
        Evaluate this statement.
        """
        # the base class
        type_class = self.namespace.get_type(self.ctor.class_type)

        if not isinstance(type_class, EntityLike):
            raise TypingException(
                self,
                "Default can only be define for an Entity, but %s is a %s" %
                (self.ctor.class_type, self.ctor.class_type))
        inmanta_warnings.warn(
            CompilerDeprecationWarning(
                self,
                "Default constructors are deprecated. Use inheritance instead."
            ))

        self.type.comment = self.comment

        default = self.type
        default.set_entity(type_class)

        for name, value in self.ctor.get_attributes().items():
            default.add_default(name, value)
コード例 #8
0
ファイル: expression.py プロジェクト: inmanta/inmanta-core
 def _bin_op(self, arg1: object, arg2: object) -> object:
     """
     @see Operator#_op
     """
     if not isinstance(arg1, (int, float)) or not isinstance(arg2, (int, float)):
         raise TypingException(self, "Can only compare numbers.")
     return arg1 >= arg2
コード例 #9
0
ファイル: generator.py プロジェクト: inmanta/inmanta-core
 def execute(self, requires: Dict[object, object], resolver: Resolver,
             queue: QueueScheduler) -> List[Tuple[str, object]]:
     dct: object = self.dictionary.execute(requires, resolver, queue)
     if not isinstance(dct, Dict):
         raise TypingException(
             self, "The ** operator can only be applied to dictionaries")
     return list(dct.items())
コード例 #10
0
ファイル: attribute.py プロジェクト: n-pochet/inmanta
 def final(self, excns: List[Exception]) -> None:
     for rv in self.source_annotations:
         try:
             if isinstance(rv.get_value(), Unknown):
                 excns.append(
                     TypingException(
                         self, "Relation annotation can not be Unknown"))
         except RuntimeException as e:
             excns.append(e)
     for rv in self.target_annotations:
         try:
             if isinstance(rv.get_value(), Unknown):
                 excns.append(
                     TypingException(
                         self, "Relation annotation can not be Unknown"))
         except RuntimeException as e:
             excns.append(e)
コード例 #11
0
ファイル: expression.py プロジェクト: inmanta/inmanta-core
    def _bin_op(self, arg1: object, arg2: object) -> object:
        """
        @see Operator#_op
        """
        assert arg2 == self.regex
        if not isinstance(arg1, str):
            raise TypingException(self, "Regex can only be match with strings. %s is of type %s" % (arg1, type(arg1)))

        return self.regex.match(arg1) is not None
コード例 #12
0
    def _bin_op(self, arg1, arg2):
        """
        @see Operator#_op
        """
        if not isinstance(arg1, str):
            raise TypingException(
                self,
                "Regex can only be match with strings. %s is of type %s" %
                arg1)

        return arg2.match(arg1) is not None
コード例 #13
0
ファイル: generator.py プロジェクト: e7ChatsApp/inmanta-core
    def normalize(self) -> None:
        mytype: "EntityLike" = self.namespace.get_type(self.class_type)
        self.type = mytype

        for (k, v) in self.__attributes.items():
            v.normalize()

        for wrapped_kwargs in self.wrapped_kwargs:
            wrapped_kwargs.normalize()

        inindex = set()

        all_attributes = dict(self.type.get_default_values())
        all_attributes.update(self.__attributes)

        # now check that all variables that have indexes on them, are already
        # defined and add the instance to the index
        for index in self.type.get_entity().get_indices():
            for attr in index:
                if attr not in all_attributes:
                    self.required_kwargs.append(attr)
                    continue
                inindex.add(attr)
        if self.required_kwargs and not self.wrapped_kwargs:
            raise TypingException(
                self,
                "attributes %s are part of an index and should be set in the constructor."
                % ",".join(self.required_kwargs),
            )

        for (k, v) in all_attributes.items():
            attribute = self.type.get_entity().get_attribute(k)
            if attribute is None:
                raise TypingException(
                    self, "no attribute %s on type %s" %
                    (k, self.type.get_full_name()))
            if k not in inindex:
                self._indirect_attributes[k] = v
            else:
                self._direct_attributes[k] = v
コード例 #14
0
ファイル: expression.py プロジェクト: inmanta/inmanta-core
    def _bin_op(self, arg1: object, arg2: object) -> object:
        """
        @see Operator#_op
        """
        if isinstance(arg2, dict):
            return arg1 in arg2
        elif isinstance(arg2, list):
            for arg in arg2:
                if arg == arg1:
                    return True
        else:
            raise TypingException(self, "Operand two of 'in' can only be a list or dict (%s)" % arg2)

        return False
コード例 #15
0
ファイル: assign.py プロジェクト: inmanta/inmanta-core
    def resume(
        self, requires: typing.Dict[object, object], resolver: Resolver, queue: QueueScheduler, target: ResultVariable
    ) -> None:
        instance = self.instance.execute(requires, resolver, queue)
        if not isinstance(instance, Instance):
            raise TypingException(
                self, "The object at %s is not an Entity but a %s with value %s" % (self.instance, type(instance), instance)
            )
        var = instance.get_attribute(self.attribute_name)
        if self.list_only and not var.is_multi():
            raise TypingException(self, "Can not use += on relations with multiplicity 1")

        if var.is_multi():
            # gradual only for multi
            # to preserve order on lists used in attributes
            # while allowing gradual execution on relations
            reqs = self.value.requires_emit_gradual(
                resolver, queue, GradualSetAttributeHelper(self, instance, self.attribute_name, var)
            )
        else:
            reqs = self.value.requires_emit(resolver, queue)

        SetAttributeHelper(queue, resolver, var, reqs, self.value, self, instance, self.attribute_name)
コード例 #16
0
    def normalize(self) -> None:
        self.type = self.namespace.get_type(self.class_type)
        for (k, v) in self.__attributes.items():
            v.normalize()

        inindex = set()

        # now check that all variables that have indexes on them, are already
        # defined and add the instance to the index
        for index in self.type.get_entity().get_indices():
            for attr in index:
                if attr not in self.attributes:
                    raise TypingException(self, "%s is part of an index and should be set in the constructor." % attr)
                inindex.add(attr)

        for (k, v) in self.__attributes.items():
            attribute = self.type.get_entity().get_attribute(k)
            if attribute is None:
                raise TypingException(self, "no attribute %s on type %s" % (k, self.type.get_full_name()))
            if isinstance(attribute, RelationAttribute) and k not in inindex:
                self._indirect_attributes[k] = v
            else:
                self._direct_attributes[k] = v
コード例 #17
0
ファイル: define.py プロジェクト: inmanta/inmanta-core
 def evaluate(self) -> None:
     """
     Evaluate this statement in the given scope
     """
     try:
         cls = self.namespace.get_type(self.entity)
         if not isinstance(cls, Entity):
             raise TypingException(
                 self, "Implementation can only be define for an Entity, but %s is a %s" % (self.entity, cls)
             )
         self.type.set_type(cls)
         self.copy_location(self.type)
     except TypeNotFoundException as e:
         e.set_statement(self)
         raise e
コード例 #18
0
ファイル: define.py プロジェクト: inmanta/inmanta-core
    def set_expression(self, expression: ExpressionStatement) -> None:
        """
        Set the expression that constrains the basetype. This expression
        should reference the value that will be assign to a variable of this
        type. This variable has the same name as the type.
        """
        contains_var = False

        if hasattr(expression, "arguments"):
            # some sort of function call
            expression = Equals(expression, Literal(True))

        for var in expression.requires():
            if var == self.name or var == "self":
                contains_var = True

        if not contains_var:
            raise TypingException(self, "typedef expressions should reference the self variable")

        self.__expression = expression
コード例 #19
0
ファイル: generator.py プロジェクト: inmanta/inmanta-core
    def execute(self, requires: Dict[object, object], resolver: Resolver,
                queue: QueueScheduler) -> object:
        """
        Evaluate this statement.
        """
        var = self.base.execute(requires, resolver, queue)

        if isinstance(var, Unknown):
            return None

        if not isinstance(var, list):
            raise TypingException(
                self, "A for loop can only be applied to lists and relations")

        helper = requires[self]

        for loop_var in var:
            # generate a subscope/namespace for each loop
            helper.receive_result(loop_var, self.location)

        return None
コード例 #20
0
ファイル: define.py プロジェクト: inmanta/inmanta-core
    def evaluate(self) -> None:
        """
        Add this relation to the participating ends
        """
        try:
            left = self.namespace.get_type(self.left[0])
        except TypeNotFoundException as e:
            e.set_location(self.location)
            raise e

        if isinstance(left, Default):
            raise TypingException(
                self,
                "Can not define relation on a default constructor %s, use base type instead: %s "
                % (left.name, left.get_entity().get_full_name()),
            )

        assert isinstance(left, Entity), "%s is not an entity" % left

        # Duplicate checking is in entity.normalize
        # Because here we don't know if all entities have been defined

        try:
            right = self.namespace.get_type(self.right[0])
        except TypeNotFoundException as e:
            e.set_location(self.location)
            raise e

        if isinstance(right, Default):
            raise TypingException(
                self,
                "Can not define relation on a default constructor %s, use base type instead: %s "
                % (right.name, right.get_entity().get_full_name()),
            )

        assert isinstance(right, Entity), "%s is not an entity" % right
        # Duplicate checking is in entity.normalize
        # Because here we don't know if all entities have been defined

        left_end: Optional[RelationAttribute]
        if self.left[1] is not None:
            left_end = RelationAttribute(right, left, str(self.left[1]), self.left[1].get_location())
            left_end.target_annotations = self.annotations
            left_end.set_multiplicity(self.left[2])
            left_end.comment = self.comment
        else:
            left_end = None

        right_end: Optional[RelationAttribute]
        if self.right[1] is not None:
            if right == left and str(self.left[1]) == str(self.right[1]):
                # relation is its own inverse
                right_end = left_end
            else:
                right_end = RelationAttribute(left, right, str(self.right[1]), self.right[1].get_location())
                right_end.source_annotations = self.annotations
                right_end.set_multiplicity(self.right[2])
                right_end.comment = self.comment
        else:
            right_end = None

        if left_end is not None and right_end is not None:
            left_end.end = right_end
            right_end.end = left_end
コード例 #21
0
    def evaluate(self) -> None:
        """
        Add this relation to the participating ends
        """
        try:
            left = self.namespace.get_type(self.left[0])
        except TypeNotFoundException as e:
            e.set_location(self.location)
            raise e

        if isinstance(left, Default):
            raise TypingException(
                self,
                "Can not define relation on a default constructor %s, use base type instead: %s "
                % (left.name, left.get_entity().get_full_name()),
            )

        assert isinstance(left, Entity), "%s is not an entity" % left

        if left.get_attribute_from_related(str(self.right[1])) is not None:
            raise DuplicateException(
                self,
                left.get_attribute_from_related(str(self.right[1])),
                ("Attribute name %s is already defined in %s, unable to define relationship"
                 ) % (str(self.right[1]), left.name),
            )

        try:
            right = self.namespace.get_type(self.right[0])
        except TypeNotFoundException as e:
            e.set_location(self.location)
            raise e

        if isinstance(right, Default):
            raise TypingException(
                self,
                "Can not define relation on a default constructor %s, use base type instead: %s "
                % (right.name, right.get_entity().get_full_name()),
            )

        assert isinstance(right, Entity), "%s is not an entity" % right

        if right.get_attribute_from_related(str(self.left[1])) is not None:
            raise DuplicateException(
                self,
                right.get_attribute_from_related(str(self.left[1])),
                ("Attribute name %s is already defined in %s, unable to define relationship"
                 ) % (str(self.left[1]), right.name),
            )

        left_end: Optional[RelationAttribute]
        if self.left[1] is not None:
            left_end = RelationAttribute(right, left, str(self.left[1]),
                                         self.left[1].get_location())
            left_end.target_annotations = self.annotations
            left_end.set_multiplicity(self.left[2])
            left_end.comment = self.comment
        else:
            left_end = None

        right_end: Optional[RelationAttribute]
        if self.right[1] is not None:
            if right == left and str(self.left[1]) == str(self.right[1]):
                # relation is its own inverse
                right_end = left_end
            else:
                right_end = RelationAttribute(left, right, str(self.right[1]),
                                              self.right[1].get_location())
                right_end.source_annotations = self.annotations
                right_end.set_multiplicity(self.right[2])
                right_end.comment = self.comment
        else:
            right_end = None

        if left_end is not None and right_end is not None:
            left_end.end = right_end
            right_end.end = left_end
コード例 #22
0
ファイル: generator.py プロジェクト: inmanta/inmanta-core
    def execute(self, requires: Dict[object, object], resolver: Resolver,
                queue: QueueScheduler):
        """
        Evaluate this statement.
        """
        LOGGER.log(LOG_LEVEL_TRACE, "executing constructor for %s at %s",
                   self.class_type, self.location)

        # the type to construct
        type_class = self.type.get_entity()

        # kwargs
        kwarg_attrs: Dict[str, object] = {}
        for kwargs in self.wrapped_kwargs:
            for (k, v) in kwargs.execute(requires, resolver, queue):
                if k in self.attributes or k in kwarg_attrs:
                    raise RuntimeException(
                        self,
                        "The attribute %s is set twice in the constructor call of %s."
                        % (k, self.class_type))
                attribute = self.type.get_entity().get_attribute(k)
                if attribute is None:
                    raise TypingException(
                        self, "no attribute %s on type %s" %
                        (k, self.type.get_full_name()))
                kwarg_attrs[k] = v

        missing_attrs: List[str] = [
            attr for attr in self.required_kwargs if attr not in kwarg_attrs
        ]
        if missing_attrs:
            raise IndexAttributeMissingInConstructorException(
                self, type_class, missing_attrs)

        # Schedule all direct attributes for direct execution. The kwarg keys and the direct_attributes keys are disjoint
        # because a RuntimeException is raised above when they are not.
        direct_attributes: Dict[str, object] = {
            k: v.execute(requires, resolver, queue)
            for (k, v) in self._direct_attributes.items()
        }
        direct_attributes.update(kwarg_attrs)

        # Override defaults with kwargs. The kwarg keys and the indirect_attributes keys are disjoint because a RuntimeException
        # is raised above when they are not.
        indirect_attributes: Dict[str, ExpressionStatement] = {
            k: v
            for k, v in self._indirect_attributes.items()
            if k not in kwarg_attrs
        }

        # check if the instance already exists in the index (if there is one)
        instances: List[Instance] = []
        for index in type_class.get_indices():
            params = []
            for attr in index:
                params.append((attr, direct_attributes[attr]))

            obj: Optional[Instance] = type_class.lookup_index(params, self)

            if obj is not None:
                if obj.get_type().get_entity() != type_class:
                    raise DuplicateException(
                        self, obj, "Type found in index is not an exact match")
                instances.append(obj)

        graph: Optional[DataflowGraph] = resolver.dataflow_graph
        if len(instances) > 0:
            if graph is not None:
                graph.add_index_match(
                    chain(
                        [self.get_dataflow_node(graph)],
                        (i.instance_node
                         for i in instances if i.instance_node is not None),
                    ))
            # ensure that instances are all the same objects
            first = instances[0]
            for i in instances[1:]:
                if i != first:
                    raise Exception("Inconsistent indexes detected!")

            object_instance = first
            self.copy_location(object_instance)
            for k, v in direct_attributes.items():
                object_instance.set_attribute(k, v, self.location)
        else:
            # create the instance
            object_instance = type_class.get_instance(
                direct_attributes, resolver, queue, self.location,
                self.get_dataflow_node(graph) if graph is not None else None)

        # deferred execution for indirect attributes
        for attributename, valueexpression in indirect_attributes.items():
            var = object_instance.get_attribute(attributename)
            if var.is_multi():
                # gradual only for multi
                # to preserve order on lists used in attributes
                # while allowing gradual execution on relations
                reqs = valueexpression.requires_emit_gradual(
                    resolver, queue,
                    GradualSetAttributeHelper(self, object_instance,
                                              attributename, var))
            else:
                reqs = valueexpression.requires_emit(resolver, queue)
            SetAttributeHelper(queue, resolver, var, reqs, valueexpression,
                               self, object_instance, attributename)

        # generate an implementation
        for stmt in type_class.get_sub_constructor():
            stmt.emit(object_instance, queue)

        object_instance.trackers.append(queue.get_tracker())

        return object_instance