def _rename_reads(sc, t, old_name, new_name): """Updates all locations in the module where the given name is read. Arguments: sc: (scope.Scope) Scope to work in. This should be the scope of `t`. t: (ast.AST) The AST to perform updates in. old_name: (string) Dotted name to update. new_name: (string) Dotted name to replace it with. Returns: True if any changes were made, False otherwise. """ name_parts = old_name.split('.') try: name = sc.names[name_parts[0]] for part in name_parts[1:]: name = name.attrs[part] except KeyError: return False has_changed = False for ref_node in name.reads: if isinstance(ref_node, (ast.Name, ast.Attribute)): ast_utils.replace_child(sc.parent(ref_node), ref_node, ast.parse(new_name).body[0].value) has_changed = True elif isinstance(ref_node, ast.Str) and ref_node.s.startswith(old_name): ref_node.s = ref_node.s.replace(old_name, new_name, 1) return has_changed
def testReplaceChildInvalid(self): src = 'def foo():\n return 1\nx = 1\n' replace_with = pasta.parse('bar()', py_ver).body[0] t = pasta.parse(src, py_ver) parent = t.body[0] node_to_replace = t.body[1] with self.assertRaises(errors.InvalidAstError): ast_utils.replace_child(parent, node_to_replace, replace_with)
def testReplaceChildInBody(self): src = 'def foo():\n a = 0\n a += 1 # replace this\n return a\n' replace_with = pasta.parse('foo(a + 1) # trailing comment\n').body[0] expected = 'def foo():\n a = 0\n foo(a + 1) # replace this\n return a\n' t = pasta.parse(src) parent = t.body[0] node_to_replace = parent.body[1] ast_utils.replace_child(parent, node_to_replace, replace_with) self.assertEqual(expected, pasta.dump(t))
def inline_name(t, name, py_ver=sys.version_info[:2]): """Inline a constant name into a module.""" sc = scope.analyze(t) name_node = sc.names[name] # The name must be a Name node (not a FunctionDef, etc.) if not isinstance(name_node.definition, (ast27.Name, ast3.Name)): raise InlineError('%r is not a constant; it has type %r' % (name, type(name_node.definition))) assign_node = sc.parent(name_node.definition) if not isinstance(assign_node, (ast27.Assign, ast3.Assign)): raise InlineError('%r is not declared in an assignment' % name) value = assign_node.value if not isinstance(sc.parent(assign_node), (ast27.Module, ast3.Module)): raise InlineError('%r is not a top-level name' % name) # If the name is written anywhere else in this module, it is not constant for ref in name_node.reads: if isinstance(getattr(ref, 'ctx', None), (ast27.Store, ast3.Store)): raise InlineError('%r is not a constant' % name) # Replace all reads of the name with a copy of its value for ref in name_node.reads: ast_utils.replace_child(sc.parent(ref), ref, copy.deepcopy(value)) # Remove the assignment to this name if len(assign_node.targets) == 1: ast_utils.remove_child(sc.parent(assign_node), assign_node, py_ver=py_ver) else: tgt_list = [ tgt for tgt in assign_node.targets if not (isinstance(tgt, ast.Name) and tgt.id == name) ] assign_node.targets = tgt_list