def rename_transform(node: LN, capture: Capture, filename: Filename) -> None: log.debug(f"{filename} [{list(capture)}]: {node}") # If two keys reference the same underlying object, do not modify it twice visited: List[LN] = [] for _key, value in capture.items(): log.debug(f"{_key}: {value}") if value in visited: continue visited.append(value) if isinstance(value, Leaf) and value.type == TOKEN.NAME: if value.value == old_name and value.parent is not None: value.replace(Name(new_name, prefix=value.prefix)) break elif isinstance(value, Node): if type_repr(value.type) == "dotted_name": dp_old = dotted_parts(old_name) dp_new = dotted_parts(new_name) parts = zip(dp_old, dp_new, value.children) for old, new, leaf in parts: if old != leaf.value: break if old != new: leaf.replace(Name(new, prefix=leaf.prefix)) if len(dp_new) < len(dp_old): # if new path is shorter, remove excess children del value.children[len(dp_new) : len(dp_old)] elif len(dp_new) > len(dp_old): # if new path is longer, add new children children = [ Name(new) for new in dp_new[len(dp_old) : len(dp_new)] ] value.children[len(dp_old) : len(dp_old)] = children elif type_repr(value.type) == "power": # We don't actually need the '.' so just skip it dp_old = old_name.split(".") dp_new = new_name.split(".") for old, new, leaf in zip(dp_old, dp_new, value.children): if isinstance(leaf, Node): name_leaf = leaf.children[1] else: name_leaf = leaf if old != name_leaf.value: break name_leaf.replace(Name(new, prefix=name_leaf.prefix)) if len(dp_new) < len(dp_old): # if new path is shorter, remove excess children del value.children[len(dp_new) : len(dp_old)] elif len(dp_new) > len(dp_old): # if new path is longer, add new trailers in the middle for i in range(len(dp_old), len(dp_new)): value.insert_child( i, Node(SYMBOL.trailer, [Dot(), Name(dp_new[i])]) )
def test_min_type(self): snippet = "True {} True\n".format(op) real_result = eval(snippet, {}, {}) t = tree(snippet) expr = t.children[0].children[0] t_op = expr.children[1].type expr_type = pytree.type_repr(expr.type) key_type = TOKEN.tok_name[t_op] self.assertEqual(map_type(real_result), OP_MIN_TYPE.get(t_op), key_type)
def rename_transform(node: LN, capture: Capture, filename: Filename) -> None: log.debug(f"{filename} [{list(capture)}]: {node}") for _key, value in capture.items(): log.debug(f"{_key}: {value}") if isinstance(value, Leaf) and value.type == TOKEN.NAME: if value.value == old_name and value.parent is not None: value.replace(Name(new_name, prefix=value.prefix)) break elif isinstance(value, Node): if type_repr(value.type) == "dotted_name": parts = zip( dotted_parts(old_name), dotted_parts(new_name), value.children, ) for old, new, leaf in parts: if old != leaf.value: break if old != new: leaf.replace(Name(new, prefix=leaf.prefix)) elif type_repr(value.type) == "power": pows = zip(dotted_parts(old_name), dotted_parts(new_name)) it = iter(value.children) leaf = next(it) for old, new in pows: if old == ".": leaf = leaf.children[1] continue if old != leaf.value: break if old == leaf.value and old != new: leaf.replace(Name(new, prefix=leaf.prefix)) leaf = next(it)
def print_tree( node: LN, results: Capture = None, filename: Filename = None, indent: int = 0, recurse: int = -1, ): filename = filename or Filename("") tab = INDENT_STR * indent if filename and indent == 0: click.secho(filename, fg="red", bold=True) if isinstance(node, Leaf): click.echo( click.style(tab, fg="black", bold=True) + click.style( "[{}] {} {}".format(tok_name[node.type], repr(node.prefix), repr(node.value)), fg="yellow", )) else: click.echo( click.style(tab, fg="black", bold=True) + click.style( "[{}] {}".format(type_repr(node.type), repr(node.prefix)), fg="blue")) if node.children: if recurse: for child in node.children: # N.b. do not pass results here since we print them once # at the end. print_tree(child, indent=indent + 1, recurse=recurse - 1) else: click.echo(INDENT_STR * (indent + 1) + "...") if results is None: return for key in results: if key == "node": continue value = results[key] if isinstance(value, (Leaf, Node)): click.secho("results[{}] =".format(repr(key)), fg="red") print_tree(value, indent=1, recurse=1) else: # TODO: Improve display of multi-match here, see # test_print_tree_captures test. click.secho("results[{}] = {}".format(repr(key), value), fg="red")
def print_node(node: LN, max_depth: int = 1000, indent: str = "", last: bool = True, capture={}): """Debugging function to print node tree. Arguments: node: The node to print max_depth: The maximum recursion depth to walk children """ if last: first_i = "└─" second_i = " " else: first_i = "├─" second_i = "│ " prefix = indent + first_i name = "" if node in capture.values(): name = ("\033[32m" + next(k for k, v in capture.items() if v == node) + "\033[0m= ") if type(node) is Node: print(prefix + name + "Node[{}] prefix={} suffix={}".format( type_repr(node.type), repr(node.prefix), repr(node.get_suffix()))) elif type(node) is Leaf: print(indent + first_i + name + "Leaf({}, {}, col={}{})".format( token.tok_name[node.type], repr(node.value), node.column, ", prefix={}".format(repr(node.prefix)) if node.prefix else "", )) else: raise RuntimeError("Unknown node type") indent = indent + second_i children = list(node.children) if max_depth == 0 and children: print(indent + f"└─...{len(children)} children") else: for i, child in enumerate(node.children): print_node( child, indent=indent, last=(i + 1) == len(children), max_depth=max_depth - 1, capture=capture, )
def print_selector_pattern(node, results=None, filename=None): key = "" if results: for k, v in results.items(): if node == v: key = k + "=" elif isinstance(v, list) and node in v: # v is a list? key = k + "=" if isinstance(node, Leaf): click.echo("{}{} ".format(key, repr(node.value)), nl=False) else: click.echo("{}{} ".format(key, type_repr(node.type)), nl=False) if node.children: click.echo("< ", nl=False) for child in node.children: print_selector_pattern(child, results, filename) click.echo("> ", nl=False)
def print_node(node, indent="", last=True): """Debugging function to print node tree""" if last: first_i = "└─" second_i = " " else: first_i = "├─" second_i = "│ " prefix = indent + first_i if type(node) is Node: print(prefix + "Node[{}] prefix={} suffix={}".format( type_repr(node.type), repr(node.prefix), repr(node.get_suffix()))) else: print(indent + first_i + repr(node)) indent = indent + second_i children = list(node.children) for i, child in enumerate(node.children): print_node(child, indent, last=(i + 1) == len(children))