示例#1
0
 def _delete_value(self, root, lines, node):
     """Delete value and return start possition deleted value"""
     l1, c1, l2, c2 = node.span.start.line-1, node.span.start.column-1, \
         node.span.end.line-1, node.span.end.column-1
     l1, c1 = StructureChanger.skip_tar(lines, l1, c1, l2, c2)
     StructureChanger.delete_structure(lines, l1, c1, l2, c2)
     return l1, c1
示例#2
0
    def _add_key(self, root, lines, action):
        """Add key to abstract record"""
        try:
            node = root.get_node_at_path(action['parameters']['path'])
        except:
            return False
        l1, c1, l2, c2 = StructureChanger.node_pos(node)
        if node.implementation != DataNode.Implementation.mapping:
            raise TransformationFileFormatError(
                "Add path (" +
                self._get_paths_str(action, 'destination_path') +
                ") must be abstract record")

        key = action['parameters']['key']
        if "value" in action['parameters']:
            value = action['parameters']['value']
        else:
            value = None
        if "type" in action['parameters']:
            tag = action['parameters']['type']
        else:
            tag = None
        if node.parent is None:
            add = StructureChanger.add_key(key, 0, value, tag)
            lines.insert(l1, add)
        else:
            indentation = re.search(r'^(\s*)(\S.*)$', lines[l1])
            indentation = len(indentation.group(1)) + 2
            add = StructureChanger.add_key(key, indentation, value, tag)
            lines.insert(l1 + 1, add)
        return True
示例#3
0
    def _rename_type(self, root, lines, action):
        """Rename type transformation"""
        try:
            node = root.get_node_at_path(action['parameters']['path'])
        except:
            return False
        old = action['parameters']['old_name']
        new = action['parameters']['new_name']

        StructureChanger.change_tag(lines, node, old, new)
        return True
示例#4
0
 def _change_value(self, root, lines, action):
     """Change value to speciffied"""
     try:
         node = root.get_node_at_path(action['parameters']['path'])
     except:
         return False
     if node.implementation != DataNode.Implementation.scalar:
         self._add_notification(
             "Specified path '{0}',  is not scalar type node, action is ignored"
             .format(self._get_paths_str(action, 'path')),
             self._Severity.warning, action, node)
         return False
     old = action['parameters']['old_value']
     new = action['parameters']['new_value']
     l1, c1, l2, c2 = StructureChanger.value_pos(node)
     return StructureChanger.replace(lines, new, old, l1, c1, l2, c2)
示例#5
0
 def _replace_value(self, root, lines, action):
     """Rename type transformation"""
     try:
         node = root.get_node_at_path(action['parameters']['path'])
     except:
         return False
     if node.implementation != DataNode.Implementation.scalar:
         self._add_notification(
             "Specified path '{0}',  is not scalar type node, action is ignored"
             .format(self._get_paths_str(action, 'path')),
             self._Severity.warning, action, node)
         return False
     pattern = action['parameters']['pattern']
     replacement = action['parameters']['replacement']
     old = str(node.value)
     new = re.sub(pattern, replacement, old)
     if new != old:
         l1, c1, l2, c2 = StructureChanger.value_pos(node)
         return StructureChanger.replace(lines, new, old, l1, c1, l2, c2)
     return False
示例#6
0
    def _add_array(self, root, lines, action):
        """Move key transformation"""
        try:
            parent2 = root.get_node_at_path(
                action['parameters']['addition_path'])
        except:
            return False
        if parent2.implementation != DataNode.Implementation.sequence:
            raise TransformationFileFormatError(
                    "Specified addition path (" + self._get_paths_str(action, 'addition_path') + \
                    ") is not array type node." )
        if parent2.parent is None:
            raise TransformationFileFormatError(
                "Specified addition path can't be in root node")
        try:
            parent1 = root.get_node_at_path(
                action['parameters']['source_path'])
        except:
            return False
        if parent1.implementation != DataNode.Implementation.sequence:
            raise TransformationFileFormatError(
                    "Specified source path (" + self._get_paths_str(action, 'path') + \
                    ") is not array type node." )
        if parent2 == parent1:
            raise TransformationFileFormatError(
                "Source and addition paths must be different (" +
                self._get_paths_str(action, 'source_path') + ")")
        sl1, sc1, sl2, sc2 = StructureChanger.value_pos(parent1)
        sl2, sc2 = self._fix_end(lines, sl1, sc1, sl2, sc2)
        al1, ac1, al2, ac2 = StructureChanger.value_pos(parent2)
        al2, ac2 = self._fix_end(lines, al1, ac1, al2, ac2)
        if (al1 >= sl1 and sl2 >= al2) or (sl1 >= al1 and al2 >= sl2):
            raise TransformationFileFormatError(
                "Source and addition nodes can't contains each other (" +
                self._get_paths_str(action, 'source_path') + ")")

        indentation1 = StructureChanger.get_indentation(lines, sl1)
        al1, ac1, al2, ac2 = StructureChanger.add_comments(
            lines, al1, ac1, al2, ac2)
        add = StructureChanger.copy_structure(lines, al1, ac1, al2, ac2,
                                              indentation1, False)

        if sl2 < al1 or (sl2 == al1 and sl2 < ac1):
            # addition after source, first delete
            action['parameters']['path'] = action['parameters'][
                'addition_path']
            action['parameters']['deep'] = True
            self._delete_key(root, lines, action)
        self._add_comma(lines, sl1, sl2, sc2)
        StructureChanger.paste_structure(lines, sl2, add, True)
        if not (sl2 < al1 or (sl2 == al1 and sl2 < ac1)):
            action['parameters']['path'] = action['parameters'][
                'addition_path']
            action['parameters']['deep'] = True
            self._delete_key(root, lines, action)
        return True
示例#7
0
 def _delete_key(self, root, lines, action):
     """Delete key transformation"""
     try:
         node = root.get_node_at_path(action['parameters']['path'])
     except:
         return False
     if "deep" not in action[
             'parameters'] or not action['parameters']['deep']:
         if len(node.children_keys) > 0:
             return False
     l1, c1, l2, c2 = StructureChanger.node_pos(node)
     anchors = []
     for i in range(l1, l2 + 1):
         if l1 == l2:
             text = lines[l1][c1:c2]
         elif i == l1:
             text = lines[l1][c1:]
         elif i == l2:
             text = lines[l2][:c2]
         else:
             text = lines[i]
         anchor = re.search(r'\s+&\s*(\S+)\s+', text)
         if anchor is None:
             anchor = re.search(r'\s+&\s*(\S+)$', text)
         if anchor is not None:
             anchors.append(anchor.group(1))
     if len(anchors) > 0:
         self._rewrite_first_ref(root, lines, anchors)
     # try delete with comma after or prev
     nl2, nc2 = self._next_spread(lines, l2, c2)
     if nl2 == l2 and nc2 == c2:
         l1, c1 = self._prev_spred(lines, l1, c1)
     else:
         l2 = nl2
         c2 = nc2
     # try exclude comments
     l1, c1, l2, c2 = StructureChanger.leave_comments(lines, l1, c1, l2, c2)
     l1, c1, l2, c2 = StructureChanger.add_delete_item_chars(
         lines, l1, c1, l2, c2)
     StructureChanger.delete_structure(lines, l1, c1, l2, c2)
     return True
示例#8
0
 def _copy_tree_from_anchor(self,
                            lines,
                            anchor_node,
                            ref_node,
                            remove_anchor=False):
     """Copy tree structure from anchor node to node with reference"""
     l1, c1, l2, c2 = anchor_node.span.start.line-1, anchor_node.span.start.column-1, \
         anchor_node.span.end.line-1, anchor_node.span.end.column-1
     l1, c1 = StructureChanger.skip_tar(lines, l1, c1, l2, c2)
     hlpl1, hlpc1, l2, c2 = StructureChanger.add_comments(
         lines, l1, c1, l2, c2)
     dl1, dc1, dl2, dc2 = StructureChanger.node_pos(ref_node)
     intend = re.search(r'^(\s*)(\S.*)$', lines[dl1])
     intend = len(intend.group(1)) + 2
     add = StructureChanger.copy_structure(lines, l1, c1, l2, c2, intend)
     while dl1 <= dl2:
         ref = re.search(r'^(.*\*' + anchor_node.anchor.value + r')(.*)$',
                         lines[dl1])
         if ref is not None:
             anchor = "&" + anchor_node.anchor.value
             if remove_anchor:
                 anchor = ""
             lines[dl1] = re.sub(r'\*' + anchor_node.anchor.value + r"\s+",
                                 anchor + " ", lines[dl1])
             lines[dl1] = re.sub(r'\*' + anchor_node.anchor.value + r"$",
                                 anchor, lines[dl1])
             if not ref.group(2).isspace() and len(ref.group(2)) > 0:
                 lines.insert(dl1 + 1, ref.group(2))
                 lines[dl1] = ref.group(1)
             StructureChanger.paste_structure(lines, dl1, add, True, True)
             break
         dl1 += 1
示例#9
0
 def _scale_value(self, root, lines, action):
     """Multiply value by set scale"""
     try:
         node = root.get_node_at_path(action['parameters']['path'])
         scale = float(action['parameters']['scale'])
     except:
         return False
     if node.implementation != DataNode.Implementation.scalar:
         self._add_notification(
             "Specified path '{0}', is not scalar type node, action is ignored"
             .format(self._get_paths_str(action, 'path')),
             self._Severity.warning, action, node)
         return False
     try:
         value = float(node.value)
     except ValueError:
         self._add_notification(
             "Type of value in specified path '{0}', is not numeric, action is ignored"
             .format(self._get_paths_str(action, 'path')),
             self._Severity.warning, action, node)
         return False
     l1, c1, l2, c2 = StructureChanger.value_pos(node)
     return StructureChanger.replace(lines, str(scale * value),
                                     lines[l1][c1:c2], l1, c1, l2, c2)
示例#10
0
 def _move_key_forward(self, root, lines, action):
     """Move key forward"""
     try:
         parent = re.search(r'^(.*)/([^/]*)$', action['parameters']['path'])
         node = root.get_node_at_path(action['parameters']['path'])
         if parent is None:
             raise TransformationFileFormatError(
                 "Cannot find parent path for path (" +
                 self._get_paths_str(action, 'path') + ")")
         is_root = False
         if len(parent.group(1)) == 0:
             parent_node = root
             is_root = True
         else:
             parent_node = root.get_node_at_path(parent.group(1))
     except:
         return False
     l1, c1, l2, c2 = StructureChanger.node_pos(node)
     pl1, pc1, pl2, pc2 = parent_node.span.start.line-1, parent_node.span.start.column-1, \
         parent_node.span.end.line-1, parent_node.span.end.column-1
     if parent_node.implementation != DataNode.Implementation.mapping:
         raise TransformationFileFormatError(
             "Parent of path (" + self._get_paths_str(action, 'path') +
             ") must be abstract record")
     if is_root:
         indentation1 = 0
         pl1 = 0
         pc1 = 0
     else:
         indentation1 = StructureChanger.get_indentation(lines, pl1) + 2
     l1, c1, l2, c2 = StructureChanger.add_comments(lines, l1, c1, l2, c2)
     add = StructureChanger.copy_structure(lines, l1, c1, l2, c2,
                                           indentation1)
     pl1, pc1 = StructureChanger.skip_tar(lines, pl1, pc1, pl2, pc2)
     action['parameters']['deep'] = True
     self._delete_key(root, lines, action)
     StructureChanger.paste_structure(lines, pl1, add, pc1 != 0)
     return True
示例#11
0
    def _move_key(self, root, lines, action):
        """Move key transformation"""
        try:
            parent1 = root.get_node_at_path(
                action['parameters']['destination_path'])
            raise TransformationFileFormatError(
                "Destination path (" +
                self._get_paths_str(action, 'destination_path') +
                ") already exist")
        except:
            pass
        try:
            parent1 = re.search(r'^(.*)/([^/]*)$',
                                action['parameters']['source_path'])
            node1 = root.get_node_at_path(action['parameters']['source_path'])
        except:
            return False
        try:
            parent2 = re.search(r'^(.*)/([^/]*)$',
                                action['parameters']['destination_path'])
            new_node = parent2.group(2)
            node2 = root.get_node_at_path(parent2.group(1))
            node_struct = []
        except:
            if action['parameters']['create_path'] and parent2 is not None:
                node_struct, new_path = StructureChanger.copy_absent_path(
                    root, lines, parent2.group(1))
                if len(node_struct) == 0:
                    raise TransformationFileFormatError(
                        "Can't constract destination path (" +
                        self._get_paths_str(action, 'destination_path') + ")")
                try:
                    new_node = parent2.group(2)
                    parent2 = re.search(r'^(.*)/([^/]*)$',
                                        new_path + "/" + new_node)
                    node2 = root.get_node_at_path(parent2.group(1))
                except:
                    raise TransformationFileFormatError(
                        "Constracted path error(" +
                        self._get_paths_str(action, 'destination_path') + ")")
            else:
                raise TransformationFileFormatError(
                    "Parent of destination path (" +
                    self._get_paths_str(action, 'destination_path') +
                    ") must exist")
        sl1, sc1, sl2, sc2 = StructureChanger.node_pos(node1)
        dl1, dc1, dl2, dc2 = StructureChanger.node_pos(node2)
        if parent1.group(1) == parent2.group(1) and len(node_struct) == 0 and \
            not action['parameters']['keep-source']:
            # rename
            i = node1.key.span.start.line - 1
            lines[i] = re.sub(
                parent1.group(2) + r"\s*:",
                parent2.group(2) + ":", lines[i])
            return True
        if not action['parameters']['create_path']:
            # check only existing path
            if node2.implementation != DataNode.Implementation.mapping:
                raise TransformationFileFormatError(
                    "Parent of destination path (" +
                    self._get_paths_str(action, 'destination_path') +
                    ") must be abstract record")
        if node1.parent is None:
            indentation1 = 0
        else:
            indentation1 = StructureChanger.get_indentation(lines, dl1) + 2

        sl1, sc1, sl2, sc2 = StructureChanger.add_comments(
            lines, sl1, sc1, sl2, sc2)
        add = StructureChanger.copy_structure(lines, sl1, sc1, sl2, sc2,
                                              indentation1)
        # rename key
        i = node1.key.span.start.line - sl1 - 1
        add[i] = re.sub(parent1.group(2) + r"\s*:", new_node + ":", add[i])
        if action['parameters']['create_path'] and len(node_struct) > 0:
            add = StructureChanger.paste_absent_path(add, node_struct)
        if sl1 < dl1 and sl2 > dl1:
            raise TransformationFileFormatError(
                "Destination block (" +
                self._get_paths_str(action, 'destination_path') +
                ") and source block (" +
                self._get_paths_str(action, 'source_path') + " is overlapped")
        if sl1 < dl2 or action['parameters']['keep-source']:
            # source before dest, first copy
            indentation2 = re.search(r'^(\s*)(\S.*)$', lines[dl2])
            StructureChanger.paste_structure(lines, dl2, add,
                                             len(indentation2.group(1)) < dc2)
            action['parameters']['path'] = action['parameters']['source_path']
            action['parameters']['deep'] = True
            if not action['parameters']['keep-source']:
                self._delete_key(root, lines, action)
        else:
            # source after dest, first delete
            action['parameters']['path'] = action['parameters']['source_path']
            action['parameters']['deep'] = True
            self._delete_key(root, lines, action)
            indentation2 = re.search(r'^(\s*)(\S.*)$', lines[dl2])
            StructureChanger.paste_structure(lines, dl2, add,
                                             len(indentation2.group(1)) < dc2)
        return True
示例#12
0
 def transform(self, yaml, cfg):
     """transform yaml file"""
     self.err = []
     notification_handler = NotificationHandler()
     loader = Loader(notification_handler)
     root = loader.load(yaml)
     lines = yaml.splitlines(False)
     changes = False
     text = cfg.get_curr_format_text()
     root_input_type = get_root_input_type_from_json(text)
     for aaction in self._transformation['actions']:
         if changes:
             root, lines = self.refresh(root_input_type, yaml,
                                        notification_handler, loader)
             changes = False
         for action in self._replace_wildchars(root, aaction):
             if changes:
                 root, lines = self.refresh(root_input_type, yaml,
                                            notification_handler, loader)
             if action['action'] == "delete-key":
                 changes = self._delete_key(root, lines, action)
             elif action['action'] == "move-key":
                 changes = self._move_key(root, lines, action)
                 if changes and "set_type_path" in action['parameters']:
                     yaml = "\n".join(lines)
                     root, lines = self.refresh(root_input_type, yaml,
                                                notification_handler,
                                                loader)
                     changes = False
                     try:
                         node = root.get_node_at_path(
                             action['parameters']['set_type_path'])
                         if node.type is not None:
                             StructureChanger.change_tag(
                                 lines, node, node.type.value,
                                 action['parameters']['new_type'].strip())
                         else:
                             StructureChanger.add_tag(
                                 lines, node,
                                 action['parameters']['new_type'].strip())
                         changes = True
                     except:
                         pass
             elif action['action'] == "rename-type":
                 changes = self._rename_type(root, lines, action)
             elif action['action'] == "move-key-forward":
                 changes = self._move_key_forward(root, lines, action)
             elif action['action'] == "change-value":
                 changes = self._change_value(root, lines, action)
             elif action['action'] == "replace-value":
                 changes = self._replace_value(root, lines, action)
             elif action['action'] == "merge-arrays":
                 changes = self._add_array(root, lines, action)
                 if 'destination_path' in action['parameters']:
                     if changes:
                         yaml = "\n".join(lines)
                         root, lines = self.refresh(root_input_type, yaml,
                                                    notification_handler,
                                                    loader)
                     action['parameters']['keep-source'] = False
                     changes = self._move_key(root, lines, action)
             elif action['action'] == "add-key":
                 changes = self._add_key(root, lines, action)
             elif action['action'] == "scale-value":
                 changes = self._scale_value(root, lines, action)
             if changes:
                 yaml = "\n".join(lines)
     yaml = "\n".join(lines)
     return yaml