コード例 #1
0
ファイル: loader.py プロジェクト: dengchangtao/flow123d
    def _merge_into_node(self, node):
        """Merges a single alias node into this record node."""
        # allow only alias nodes to be merged
        if not isinstance(self._event, pyyaml.AliasEvent):
            temp = self._create_node(node)  # skip the node to avoid parsing error
            notification = Notification.from_name('NoReferenceToMerge')
            notification.span = temp.span
            self.notification_handler.report(notification)
            return

        anchor = self._extract_anchor()
        if anchor.value not in self.anchors:
            notification = Notification.from_name('UndefinedAnchor', anchor.value)
            notification.span = anchor.span
            self.notification_handler.report(notification)
            return

        anchor_node = self.anchors[anchor.value]
        if anchor_node.implementation != DataNode.Implementation.mapping:
            notification = Notification.from_name('InvalidReferenceForMerge', anchor.value)
            notification.span = anchor.span
            self.notification_handler.report(notification)
            return

        for child in anchor_node.children:
            if child.key.value not in node.children_keys:
                node.set_child(copy.deepcopy(child))
        return
コード例 #2
0
    def _get_transformation_array_size(cls, node, input_type):
        """Return transformation array size."""
        # find a children node that has an array instead of record or scalar
        for child in node.children:
            # the key is not specified in input type
            if 'keys' not in input_type or child.key.value not in input_type['keys']:
                continue

            child_type = input_type['keys'][child.key.value]['type']

            if child.implementation == DataNode.Implementation.sequence:
                if child_type['base_type'] == 'Record':
                    notification = Notification.from_name("InvalidTransposition")
                    notification.span = child.span
                    raise notification
                elif child_type['base_type'] != 'Array':
                    if cls.array_size is None:
                        cls.array_size = len(child.children)
                        cls.paths_to_convert.append('/'.join(cls.current_path + [child.key.value]))
                    elif cls.array_size != len(child.children):
                        notification = Notification.from_name(
                            "DifferentArrayLengthForTransposition")
                        notification.span = child.span
                        raise notification
                    else:
                        cls.paths_to_convert.append('/'.join(cls.current_path + [child.key.value]))

            # verify array size recursively
            cls.current_path.append(child.key.value)
            cls._get_transformation_array_size(child, child_type)
            cls.current_path.pop()

        return cls.array_size
コード例 #3
0
ファイル: validator.py プロジェクト: dengchangtao/flow123d
    def _validate_node(self, node, input_type):
        """
        Determines if node contains correct value.

        Method verifies node recursively. All descendant nodes are checked.
        """
        if node is None:
            raise Notification.from_name('ValidationError', 'Invalid node (None)')

        if input_type['base_type'] != 'AbstractRecord' and hasattr(node, 'type') \
                and node.type is not None and 'implemented_abstract_record' not in input_type:
            notification = Notification.from_name('UselessTag', node.type.value)
            notification.span = node.type.span
            self.notification_handler.report(notification)

        node.input_type = input_type
        if is_scalar(input_type):
            self._validate_scalar(node, input_type)
        elif input_type['base_type'] == 'Record':
            self._validate_record(node, input_type)
        elif input_type['base_type'] == 'AbstractRecord':
            self._validate_abstract(node, input_type)
        elif input_type['base_type'] == 'Array':
            self._validate_array(node, input_type)
        else:
            notification = Notification.from_name('InputTypeNotSupported',
                                                  input_type['base_type'])
            self._report_notification(notification)
コード例 #4
0
    def convert(node, input_type):
        """Convert value of Scalar node to expected type.

        node: :py:class:`DataNode` data structure
        input_type: definition of input_type
        """
        conversions = {
            'Bool': ScalarConverter._convert_to_bool,
            'Integer': ScalarConverter._convert_to_int,
            'Double': ScalarConverter._convert_to_float,
            'String': ScalarConverter._convert_to_string,
            'FileName': ScalarConverter._convert_to_string,
            'Selection': ScalarConverter._convert_to_string,
        }

        base_type = input_type['base_type']
        if base_type in conversions and node.value is not None:
            try:
                value = conversions[base_type](node.value)
            except ValueError:
                notification = Notification.from_name('ValueConversionError', node.value, base_type)
                notification.span = node.span
                notification_handler.report(notification)
                return
            node.value = value
コード例 #5
0
ファイル: validator.py プロジェクト: dengchangtao/flow123d
 def _validate_record(self, node, input_type):
     """Validates a Record node."""
     if not node.implementation == DataNode.Implementation.mapping:
         notification = Notification.from_name('ValidationTypeError', 'Record')
         notification.span = get_node_key(node).notification_span
         self._report_notification(notification)
         return
     keys = node.children_keys
     node.options = input_type['keys'].keys()
     keys.extend(input_type['keys'].keys())
     for key in set(keys):
         if node.origin == DataNode.Origin.error:
             continue
         child = node.get_child(key)
         try:
             checks.check_record_key(node.children_keys, key, input_type)
         except Notification as notification:
             if notification.name == 'UnknownRecordKey':
                 notification.span = child.notification_span
             else:
                 notification.span = get_node_key(node).notification_span
             self._report_notification(notification)
         else:
             if child is not None:
                 child_input_type = input_type['keys'][key]['type']
                 self._validate_node(child, child_input_type)
コード例 #6
0
ファイル: loader.py プロジェクト: dengchangtao/flow123d
 def _register_anchor(self, anchor, node):
     """Registers an anchor to a node."""
     node.anchor = anchor
     if anchor.value in self.anchors:
         notification = Notification.from_name('OverridingAnchor', anchor.value)
         notification.span = anchor.span
         self.notification_handler.report(notification)
     self.anchors[anchor.value] = node
コード例 #7
0
ファイル: validator.py プロジェクト: jbrezmorf/flow123d
    def _validate_node(self, node, input_type):
        """
        Determines if node contains correct value.

        Method verifies node recursively. All descendant nodes are checked.
        """
        if node is None:
            raise Notification.from_name('ValidationError', 'Invalid node (None)')

        # parameters
        # TODO: enable parameters in unknown IST?
        if hasattr(node, 'value'):
            match = is_param(node.value)
            if match:
                # extract parameters
                new_param = Parameter(match.group(1))
                exists = False
                for param in self.params:
                    if param.name == new_param.name:
                        exists = True
                        break
                if not exists:
                    self.params.append(new_param)
                node.input_type = input_type
                # assume parameters are correct, do not validate further
                return

        if input_type['base_type'] != 'Abstract' and hasattr(node, 'type') \
                and node.type is not None and 'implemented_abstract_record' not in input_type:
            notification = Notification.from_name('UselessTag', node.type.value)
            notification.span = node.type.span
            self.notification_handler.report(notification)

        node.input_type = input_type
        if is_scalar(input_type):
            self._validate_scalar(node, input_type)
        elif input_type['base_type'] == 'Record':
            self._validate_record(node, input_type)
        elif input_type['base_type'] == 'Abstract':
            self._validate_abstract(node, input_type)
        elif input_type['base_type'] == 'Array':
            self._validate_array(node, input_type)
        else:
            notification = Notification.from_name('InputTypeNotSupported',
                                                  input_type['base_type'])
            self._report_notification(notification)
コード例 #8
0
    def make_transposition(cls, node, input_type):
        """Transpose a record or scalar into an array."""
        assert input_type['base_type'] == 'Array', "Only Array can be a result of transposition"
        cls.init()

        # if node is scalar, convert it to array
        if node.implementation == DataNode.Implementation.scalar:
            return cls._expand_value_to_array(node)

        # verify that subtype is record
        subtype = input_type['subtype']
        if subtype['base_type'] != 'Record':
            notification = Notification.from_name('UnsupportedTransposition',
                                                  input_type['base_type'])
            notification.span = node.span
            notification_handler.report(notification)
            return node
        assert node.implementation == DataNode.Implementation.mapping,\
            "Can not perform transposition on array"

        # get array size
        try:
            cls._get_transformation_array_size(node, subtype)
        except Notification as notification:
            notification_handler.report(notification)
            return node
        if cls.array_size is None:
            cls.array_size = 1

        # create array
        array_node = SequenceDataNode(node.key, node.parent)
        array_node.span = node.span
        array_node.input_type = node.input_type
        array_node.origin = DataNode.Origin.ac_array
        template_node = deepcopy(node)
        template_node.parent = array_node
        template_node.input_type = subtype
        template_node.origin = DataNode.Origin.ac_transposition

        # create and transpose items of the array
        for i in range(cls.array_size):
            child_node = deepcopy(template_node)
            child_node.key = TextValue(str(i))
            # convert array to value
            for path in cls.paths_to_convert:
                node_to_convert = child_node.get_node_at_path(path)
                converted_node = node_to_convert.children[i]
                converted_node.parent = node_to_convert.parent
                converted_node.key = node_to_convert.key
                node_to_convert.parent.set_child(converted_node)
            array_node.children.append(child_node)

        return array_node
コード例 #9
0
ファイル: validator.py プロジェクト: dengchangtao/flow123d
 def _validate_array(self, node, input_type):
     """Validates an Array node."""
     if not node.implementation == DataNode.Implementation.sequence:
         notification = Notification.from_name('ValidationTypeError', 'Array')
         notification.span = get_node_key(node).notification_span
         self._report_notification(notification)
         return
     try:
         checks.check_array(node.children, input_type)
     except Notification as notification:
         notification.span = get_node_key(node).notification_span
         self._report_notification(notification)
     for child in node.children:
         self._validate_node(child, input_type['subtype'])
コード例 #10
0
ファイル: loader.py プロジェクト: dengchangtao/flow123d
 def _create_record_key(self):
     """Creates `TextValue` of record key."""
     # check if key is scalar
     if not isinstance(self._event, pyyaml.ScalarEvent):
         start_pos = Position.from_mark(self._event.start_mark)
         self._create_fatal_error_node(start_pos)
         notification = Notification.from_name('ComplexRecordKey')
         notification.span = self._fatal_error_node.span
         self.notification_handler.report(notification)
         self._event = None
         self._iterate_events = False
         return None
     key = TextValue()
     key.value = self._event.value
     key.span = Span.from_event(self._event)
     return key
コード例 #11
0
ファイル: loader.py プロジェクト: dengchangtao/flow123d
    def _create_alias_node(self, anchor):
        """Creates an alias node."""
        if anchor.value not in self.anchors:
            notification = Notification.from_name('UndefinedAnchor', anchor.value)
            notification.span = anchor.span
            self.notification_handler.report(notification)
            return None
        ref = self.anchors[anchor.value]
        node = copy.deepcopy(ref)
        node.anchor = anchor
        node.ref = ref

        # set correct node.span
        node.span = copy.deepcopy(node.anchor.span)
        start = node.span.start
        node.span.start = Position(start.line, start.column - 1)
        return node
コード例 #12
0
ファイル: loader.py プロジェクト: dengchangtao/flow123d
 def _create_scalar_node(self):
     """Creates a ScalarDataNode."""
     node = ScalarDataNode()
     tag = self._event.tag
     if tag is None or not tag.startswith('tag:yaml.org,2002:'):
         tag = resolve_scalar_tag(self._event.value)
     node.span = Span.from_event(self._event)
     try:
         node.value = construct_scalar(self._event.value, tag)
     except Exception as error:
         notification = Notification.from_name('ConstructScalarError', error.args[0])
         notification.span = node.span
         self.notification_handler.report(notification)
         return node
     if node.value is None:
         # alter position of empty node (so it can be selected)
         node.span.end.column += 1
     return node
コード例 #13
0
ファイル: loader.py プロジェクト: dengchangtao/flow123d
 def _next_parse_event(self):
     """
     Attempts to get next parsing event and handles errors. When there
     are no more valid parsing events, event is set to None.
     """
     if self._iterate_events:
         try:
             # get next parsing event
             self._event = next(self._event_generator)
         except pyyaml.MarkedYAMLError as error:
             # handle parsing error
             self._event = None
             self._iterate_events = False
             start_pos = Position.from_yaml_error(error)
             self._create_fatal_error_node(start_pos)
             notification = Notification.from_name('SyntaxFatalError')
             notification.span = self._fatal_error_node.span
             self.notification_handler.report(notification)
         except StopIteration:
             # handle end of parsing events
             self._event = None
             self._iterate_events = False