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
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
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
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
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]) #if indentation2 == None: if not indentation2: non_space_size = 0 else: non_space_size = len(indentation2.group(1)) StructureChanger.paste_structure(lines, dl2, add, non_space_size < 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 indentation2 = re.search(r'^(\s*)(\S.*)$', lines[dl2]) self._delete_key(root, lines, action) StructureChanger.paste_structure(lines, dl2, add, len(indentation2.group(1)) < dc2) return True