Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Unified Diff: tools/telemetry/third_party/rope/rope/refactor/move.py

Issue 1132103009: Example of refactoring using rope library. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/third_party/rope/rope/refactor/move.py
diff --git a/tools/telemetry/third_party/rope/rope/refactor/move.py b/tools/telemetry/third_party/rope/rope/refactor/move.py
new file mode 100644
index 0000000000000000000000000000000000000000..60df493e27fe2aab2e062e15dec894bce3bd440e
--- /dev/null
+++ b/tools/telemetry/third_party/rope/rope/refactor/move.py
@@ -0,0 +1,718 @@
+"""A module containing classes for move refactoring
+
+`create_move()` is a factory for creating move refactoring objects
+based on inputs.
+
+"""
+from rope.base import (pyobjects, codeanalyze, exceptions, pynames,
+ taskhandle, evaluate, worder, libutils)
+from rope.base.change import ChangeSet, ChangeContents, MoveResource
+from rope.refactor import importutils, rename, occurrences, sourceutils, \
+ functionutils
+
+
+def create_move(project, resource, offset=None):
+ """A factory for creating Move objects
+
+ Based on `resource` and `offset`, return one of `MoveModule`,
+ `MoveGlobal` or `MoveMethod` for performing move refactoring.
+
+ """
+ if offset is None:
+ return MoveModule(project, resource)
+ this_pymodule = project.get_pymodule(resource)
+ pyname = evaluate.eval_location(this_pymodule, offset)
+ if pyname is None:
+ raise exceptions.RefactoringError(
+ 'Move only works on classes, functions, modules and methods.')
+ pyobject = pyname.get_object()
+ if isinstance(pyobject, pyobjects.PyModule) or \
+ isinstance(pyobject, pyobjects.PyPackage):
+ return MoveModule(project, pyobject.get_resource())
+ if isinstance(pyobject, pyobjects.PyFunction) and \
+ isinstance(pyobject.parent, pyobjects.PyClass):
+ return MoveMethod(project, resource, offset)
+ if isinstance(pyobject, pyobjects.PyDefinedObject) and \
+ isinstance(pyobject.parent, pyobjects.PyModule):
+ return MoveGlobal(project, resource, offset)
+ raise exceptions.RefactoringError(
+ 'Move only works on global classes/functions, modules and methods.')
+
+
+class MoveMethod(object):
+ """For moving methods
+
+ It makes a new method in the destination class and changes
+ the body of the old method to call the new method. You can
+ inline the old method to change all of its occurrences.
+
+ """
+
+ def __init__(self, project, resource, offset):
+ self.project = project
+ this_pymodule = self.project.get_pymodule(resource)
+ pyname = evaluate.eval_location(this_pymodule, offset)
+ self.method_name = worder.get_name_at(resource, offset)
+ self.pyfunction = pyname.get_object()
+ if self.pyfunction.get_kind() != 'method':
+ raise exceptions.RefactoringError('Only normal methods'
+ ' can be moved.')
+
+ def get_changes(self, dest_attr, new_name=None, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Return the changes needed for this refactoring
+
+ Parameters:
+
+ - `dest_attr`: the name of the destination attribute
+ - `new_name`: the name of the new method; if `None` uses
+ the old name
+ - `resources` can be a list of `rope.base.resources.File`\s to
+ apply this refactoring on. If `None`, the restructuring
+ will be applied to all python files.
+
+ """
+ changes = ChangeSet('Moving method <%s>' % self.method_name)
+ if resources is None:
+ resources = self.project.get_python_files()
+ if new_name is None:
+ new_name = self.get_method_name()
+ resource1, start1, end1, new_content1 = \
+ self._get_changes_made_by_old_class(dest_attr, new_name)
+ collector1 = codeanalyze.ChangeCollector(resource1.read())
+ collector1.add_change(start1, end1, new_content1)
+
+ resource2, start2, end2, new_content2 = \
+ self._get_changes_made_by_new_class(dest_attr, new_name)
+ if resource1 == resource2:
+ collector1.add_change(start2, end2, new_content2)
+ else:
+ collector2 = codeanalyze.ChangeCollector(resource2.read())
+ collector2.add_change(start2, end2, new_content2)
+ result = collector2.get_changed()
+ import_tools = importutils.ImportTools(self.project)
+ new_imports = self._get_used_imports(import_tools)
+ if new_imports:
+ goal_pymodule = libutils.get_string_module(
+ self.project, result, resource2)
+ result = _add_imports_to_module(
+ import_tools, goal_pymodule, new_imports)
+ if resource2 in resources:
+ changes.add_change(ChangeContents(resource2, result))
+
+ if resource1 in resources:
+ changes.add_change(ChangeContents(resource1,
+ collector1.get_changed()))
+ return changes
+
+ def get_method_name(self):
+ return self.method_name
+
+ def _get_used_imports(self, import_tools):
+ return importutils.get_imports(self.project, self.pyfunction)
+
+ def _get_changes_made_by_old_class(self, dest_attr, new_name):
+ pymodule = self.pyfunction.get_module()
+ indents = self._get_scope_indents(self.pyfunction)
+ body = 'return self.%s.%s(%s)\n' % (
+ dest_attr, new_name, self._get_passed_arguments_string())
+ region = sourceutils.get_body_region(self.pyfunction)
+ return (pymodule.get_resource(), region[0], region[1],
+ sourceutils.fix_indentation(body, indents))
+
+ def _get_scope_indents(self, pyobject):
+ pymodule = pyobject.get_module()
+ return sourceutils.get_indents(
+ pymodule.lines, pyobject.get_scope().get_start()) + \
+ sourceutils.get_indent(self.project)
+
+ def _get_changes_made_by_new_class(self, dest_attr, new_name):
+ old_pyclass = self.pyfunction.parent
+ if dest_attr not in old_pyclass:
+ raise exceptions.RefactoringError(
+ 'Destination attribute <%s> not found' % dest_attr)
+ pyclass = old_pyclass[dest_attr].get_object().get_type()
+ if not isinstance(pyclass, pyobjects.PyClass):
+ raise exceptions.RefactoringError(
+ 'Unknown class type for attribute <%s>' % dest_attr)
+ pymodule = pyclass.get_module()
+ resource = pyclass.get_module().get_resource()
+ start, end = sourceutils.get_body_region(pyclass)
+ pre_blanks = '\n'
+ if pymodule.source_code[start:end].strip() != 'pass':
+ pre_blanks = '\n\n'
+ start = end
+ indents = self._get_scope_indents(pyclass)
+ body = pre_blanks + sourceutils.fix_indentation(
+ self.get_new_method(new_name), indents)
+ return resource, start, end, body
+
+ def get_new_method(self, name):
+ return '%s\n%s' % (
+ self._get_new_header(name),
+ sourceutils.fix_indentation(self._get_body(),
+ sourceutils.get_indent(self.project)))
+
+ def _get_unchanged_body(self):
+ return sourceutils.get_body(self.pyfunction)
+
+ def _get_body(self, host='host'):
+ self_name = self._get_self_name()
+ body = self_name + ' = None\n' + self._get_unchanged_body()
+ pymodule = libutils.get_string_module(self.project, body)
+ finder = occurrences.create_finder(
+ self.project, self_name, pymodule[self_name])
+ result = rename.rename_in_module(finder, host, pymodule=pymodule)
+ if result is None:
+ result = body
+ return result[result.index('\n') + 1:]
+
+ def _get_self_name(self):
+ return self.pyfunction.get_param_names()[0]
+
+ def _get_new_header(self, name):
+ header = 'def %s(self' % name
+ if self._is_host_used():
+ header += ', host'
+ definition_info = functionutils.DefinitionInfo.read(self.pyfunction)
+ others = definition_info.arguments_to_string(1)
+ if others:
+ header += ', ' + others
+ return header + '):'
+
+ def _get_passed_arguments_string(self):
+ result = ''
+ if self._is_host_used():
+ result = 'self'
+ definition_info = functionutils.DefinitionInfo.read(self.pyfunction)
+ others = definition_info.arguments_to_string(1)
+ if others:
+ if result:
+ result += ', '
+ result += others
+ return result
+
+ def _is_host_used(self):
+ return self._get_body('__old_self') != self._get_unchanged_body()
+
+
+class MoveGlobal(object):
+ """For moving global function and classes"""
+
+ def __init__(self, project, resource, offset):
+ self.project = project
+ this_pymodule = self.project.get_pymodule(resource)
+ self.old_pyname = evaluate.eval_location(this_pymodule, offset)
+ self.old_name = self.old_pyname.get_object().get_name()
+ pymodule = self.old_pyname.get_object().get_module()
+ self.source = pymodule.get_resource()
+ self.tools = _MoveTools(self.project, self.source,
+ self.old_pyname, self.old_name)
+ self.import_tools = self.tools.import_tools
+ self._check_exceptional_conditions()
+
+ def _check_exceptional_conditions(self):
+ if self.old_pyname is None or \
+ not isinstance(self.old_pyname.get_object(),
+ pyobjects.PyDefinedObject):
+ raise exceptions.RefactoringError(
+ 'Move refactoring should be performed on a class/function.')
+ moving_pyobject = self.old_pyname.get_object()
+ if not self._is_global(moving_pyobject):
+ raise exceptions.RefactoringError(
+ 'Move refactoring should be performed ' +
+ 'on a global class/function.')
+
+ def _is_global(self, pyobject):
+ return pyobject.get_scope().parent == pyobject.get_module().get_scope()
+
+ def get_changes(self, dest, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ if resources is None:
+ resources = self.project.get_python_files()
+ if dest is None or not dest.exists():
+ raise exceptions.RefactoringError(
+ 'Move destination does not exist.')
+ if dest.is_folder() and dest.has_child('__init__.py'):
+ dest = dest.get_child('__init__.py')
+ if dest.is_folder():
+ raise exceptions.RefactoringError(
+ 'Move destination for non-modules should not be folders.')
+ if self.source == dest:
+ raise exceptions.RefactoringError(
+ 'Moving global elements to the same module.')
+ return self._calculate_changes(dest, resources, task_handle)
+
+ def _calculate_changes(self, dest, resources, task_handle):
+ changes = ChangeSet('Moving global <%s>' % self.old_name)
+ job_set = task_handle.create_jobset('Collecting Changes',
+ len(resources))
+ for file_ in resources:
+ job_set.started_job(file_.path)
+ if file_ == self.source:
+ changes.add_change(self._source_module_changes(dest))
+ elif file_ == dest:
+ changes.add_change(self._dest_module_changes(dest))
+ elif self.tools.occurs_in_module(resource=file_):
+ pymodule = self.project.get_pymodule(file_)
+ # Changing occurrences
+ placeholder = '__rope_renaming_%s_' % self.old_name
+ source = self.tools.rename_in_module(placeholder,
+ resource=file_)
+ should_import = source is not None
+ # Removing out of date imports
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self.tools.remove_old_imports(pymodule)
+ # Adding new import
+ if should_import:
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source, imported = importutils.add_import(
+ self.project, pymodule, self._new_modname(dest),
+ self.old_name)
+ source = source.replace(placeholder, imported)
+ source = self.tools.new_source(pymodule, source)
+ if source != file_.read():
+ changes.add_change(ChangeContents(file_, source))
+ job_set.finished_job()
+ return changes
+
+ def _source_module_changes(self, dest):
+ placeholder = '__rope_moving_%s_' % self.old_name
+ handle = _ChangeMoveOccurrencesHandle(placeholder)
+ occurrence_finder = occurrences.create_finder(
+ self.project, self.old_name, self.old_pyname)
+ start, end = self._get_moving_region()
+ renamer = ModuleSkipRenamer(occurrence_finder, self.source,
+ handle, start, end)
+ source = renamer.get_changed_module()
+ if handle.occurred:
+ pymodule = libutils.get_string_module(
+ self.project, source, self.source)
+ # Adding new import
+ source, imported = importutils.add_import(
+ self.project, pymodule, self._new_modname(dest), self.old_name)
+ source = source.replace(placeholder, imported)
+ return ChangeContents(self.source, source)
+
+ def _new_modname(self, dest):
+ return libutils.modname(dest)
+
+ def _dest_module_changes(self, dest):
+ # Changing occurrences
+ pymodule = self.project.get_pymodule(dest)
+ source = self.tools.rename_in_module(self.old_name, pymodule)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+
+ moving, imports = self._get_moving_element_with_imports()
+ source = self.tools.remove_old_imports(pymodule)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ pymodule, has_changed = self._add_imports2(pymodule, imports)
+
+ module_with_imports = self.import_tools.module_imports(pymodule)
+ source = pymodule.source_code
+ lineno = 0
+ if module_with_imports.imports:
+ lineno = module_with_imports.imports[-1].end_line - 1
+ else:
+ while lineno < pymodule.lines.length() and \
+ pymodule.lines.get_line(lineno + 1).\
+ lstrip().startswith('#'):
+ lineno += 1
+ if lineno > 0:
+ cut = pymodule.lines.get_line_end(lineno) + 1
+ result = source[:cut] + '\n\n' + moving + source[cut:]
+ else:
+ result = moving + source
+
+ # Organizing imports
+ source = result
+ pymodule = libutils.get_string_module(self.project, source, dest)
+ source = self.import_tools.organize_imports(pymodule, sort=False,
+ unused=False)
+ return ChangeContents(dest, source)
+
+ def _get_moving_element_with_imports(self):
+ return moving_code_with_imports(
+ self.project, self.source, self._get_moving_element())
+
+ def _get_module_with_imports(self, source_code, resource):
+ pymodule = libutils.get_string_module(
+ self.project, source_code, resource)
+ return self.import_tools.module_imports(pymodule)
+
+ def _get_moving_element(self):
+ start, end = self._get_moving_region()
+ moving = self.source.read()[start:end]
+ return moving.rstrip() + '\n'
+
+ def _get_moving_region(self):
+ pymodule = self.project.get_pymodule(self.source)
+ lines = pymodule.lines
+ scope = self.old_pyname.get_object().get_scope()
+ start = lines.get_line_start(scope.get_start())
+ end_line = scope.get_end()
+ while end_line < lines.length() and \
+ lines.get_line(end_line + 1).strip() == '':
+ end_line += 1
+ end = min(lines.get_line_end(end_line) + 1, len(pymodule.source_code))
+ return start, end
+
+ def _add_imports2(self, pymodule, new_imports):
+ source = self.tools.add_imports(pymodule, new_imports)
+ if source is None:
+ return pymodule, False
+ else:
+ resource = pymodule.get_resource()
+ pymodule = libutils.get_string_module(
+ self.project, source, resource)
+ return pymodule, True
+
+
+class MoveModule(object):
+ """For moving modules and packages"""
+
+ def __init__(self, project, resource):
+ self.project = project
+ if not resource.is_folder() and resource.name == '__init__.py':
+ resource = resource.parent
+ if resource.is_folder() and not resource.has_child('__init__.py'):
+ raise exceptions.RefactoringError(
+ 'Cannot move non-package folder.')
+ dummy_pymodule = libutils.get_string_module(self.project, '')
+ self.old_pyname = pynames.ImportedModule(dummy_pymodule,
+ resource=resource)
+ self.source = self.old_pyname.get_object().get_resource()
+ if self.source.is_folder():
+ self.old_name = self.source.name
+ else:
+ self.old_name = self.source.name[:-3]
+ self.tools = _MoveTools(self.project, self.source,
+ self.old_pyname, self.old_name)
+ self.import_tools = self.tools.import_tools
+
+ def get_changes(self, dest, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ if resources is None:
+ resources = self.project.get_python_files()
+ if dest is None or not dest.is_folder():
+ raise exceptions.RefactoringError(
+ 'Move destination for modules should be packages.')
+ return self._calculate_changes(dest, resources, task_handle)
+
+ def _calculate_changes(self, dest, resources, task_handle):
+ changes = ChangeSet('Moving module <%s>' % self.old_name)
+ job_set = task_handle.create_jobset('Collecting changes',
+ len(resources))
+ for module in resources:
+ job_set.started_job(module.path)
+ if module == self.source:
+ self._change_moving_module(changes, dest)
+ else:
+ source = self._change_occurrences_in_module(dest,
+ resource=module)
+ if source is not None:
+ changes.add_change(ChangeContents(module, source))
+ job_set.finished_job()
+ if self.project == self.source.project:
+ changes.add_change(MoveResource(self.source, dest.path))
+ return changes
+
+ def _new_modname(self, dest):
+ destname = libutils.modname(dest)
+ if destname:
+ return destname + '.' + self.old_name
+ return self.old_name
+
+ def _new_import(self, dest):
+ return importutils.NormalImport([(self._new_modname(dest), None)])
+
+ def _change_moving_module(self, changes, dest):
+ if not self.source.is_folder():
+ pymodule = self.project.get_pymodule(self.source)
+ source = self.import_tools.relatives_to_absolutes(pymodule)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self._change_occurrences_in_module(dest, pymodule)
+ source = self.tools.new_source(pymodule, source)
+ if source != self.source.read():
+ changes.add_change(ChangeContents(self.source, source))
+
+ def _change_occurrences_in_module(self, dest, pymodule=None,
+ resource=None):
+ if not self.tools.occurs_in_module(pymodule=pymodule,
+ resource=resource):
+ return
+ if pymodule is None:
+ pymodule = self.project.get_pymodule(resource)
+ new_name = self._new_modname(dest)
+ module_imports = importutils.get_module_imports(self.project, pymodule)
+ changed = False
+
+ source = None
+ if libutils.modname(dest):
+ changed = self._change_import_statements(dest, new_name,
+ module_imports)
+ if changed:
+ source = module_imports.get_changed_source()
+ source = self.tools.new_source(pymodule, source)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+
+ new_import = self._new_import(dest)
+ source = self.tools.rename_in_module(
+ new_name, imports=True, pymodule=pymodule,
+ resource=resource if not changed else None)
+ should_import = self.tools.occurs_in_module(
+ pymodule=pymodule, resource=resource, imports=False)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self.tools.remove_old_imports(pymodule)
+ if should_import:
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self.tools.add_imports(pymodule, [new_import])
+ source = self.tools.new_source(pymodule, source)
+ if source is not None and source != pymodule.resource.read():
+ return source
+ return None
+
+
+ def _change_import_statements(self, dest, new_name, module_imports):
+ moving_module = self.source
+ parent_module = moving_module.parent
+
+ changed = False
+ for import_stmt in module_imports.imports:
+ if not any(name_and_alias[0] == self.old_name
+ for name_and_alias in
+ import_stmt.import_info.names_and_aliases) and \
+ not any(name_and_alias[0] == libutils.modname(self.source)
+ for name_and_alias in
+ import_stmt.import_info.names_and_aliases):
+ continue
+
+ # Case 1: Look for normal imports of the moving module.
+ if isinstance(import_stmt.import_info, importutils.NormalImport):
+ continue
+
+ # Case 2: The moving module is from-imported.
+ changed = self._handle_moving_in_from_import_stmt(
+ dest, import_stmt, module_imports, parent_module) or changed
+
+ # Case 3: Names are imported from the moving module.
+ context = importutils.importinfo.ImportContext(self.project, None)
+ if not import_stmt.import_info.is_empty() and \
+ import_stmt.import_info.get_imported_resource(context) == \
+ moving_module:
+ import_stmt.import_info = importutils.FromImport(
+ new_name, import_stmt.import_info.level,
+ import_stmt.import_info.names_and_aliases)
+ changed = True
+
+ return changed
+
+ def _handle_moving_in_from_import_stmt(self, dest, import_stmt,
+ module_imports, parent_module):
+ changed = False
+ context = importutils.importinfo.ImportContext(self.project, None)
+ if import_stmt.import_info.get_imported_resource(context) == \
+ parent_module:
+ imports = import_stmt.import_info.names_and_aliases
+ new_imports = []
+ for name, alias in imports:
+ # The moving module was imported.
+ if name == self.old_name:
+ changed = True
+ new_import = importutils.FromImport(
+ libutils.modname(dest), 0,
+ [(self.old_name, alias)])
+ module_imports.add_import(new_import)
+ else:
+ new_imports.append((name, alias))
+
+ # Update the imports if the imported names were changed.
+ if new_imports != imports:
+ changed = True
+ if new_imports:
+ import_stmt.import_info = importutils.FromImport(
+ import_stmt.import_info.module_name,
+ import_stmt.import_info.level,
+ new_imports)
+ else:
+ import_stmt.empty_import()
+ return changed
+
+
+class _ChangeMoveOccurrencesHandle(object):
+
+ def __init__(self, new_name):
+ self.new_name = new_name
+ self.occurred = False
+
+ def occurred_inside_skip(self, change_collector, occurrence):
+ pass
+
+ def occurred_outside_skip(self, change_collector, occurrence):
+ start, end = occurrence.get_primary_range()
+ change_collector.add_change(start, end, self.new_name)
+ self.occurred = True
+
+
+class _MoveTools(object):
+
+ def __init__(self, project, source, pyname, old_name):
+ self.project = project
+ self.source = source
+ self.old_pyname = pyname
+ self.old_name = old_name
+ self.import_tools = importutils.ImportTools(self.project)
+
+ def remove_old_imports(self, pymodule):
+ old_source = pymodule.source_code
+ module_with_imports = self.import_tools.module_imports(pymodule)
+
+ class CanSelect(object):
+ changed = False
+ old_name = self.old_name
+ old_pyname = self.old_pyname
+
+ def __call__(self, name):
+ try:
+ if name == self.old_name and \
+ pymodule[name].get_object() == \
+ self.old_pyname.get_object():
+ self.changed = True
+ return False
+ except exceptions.AttributeNotFoundError:
+ pass
+ return True
+ can_select = CanSelect()
+ module_with_imports.filter_names(can_select)
+ new_source = module_with_imports.get_changed_source()
+ if old_source != new_source:
+ return new_source
+
+ def rename_in_module(self, new_name, pymodule=None,
+ imports=False, resource=None):
+ occurrence_finder = self._create_finder(imports)
+ source = rename.rename_in_module(
+ occurrence_finder, new_name, replace_primary=True,
+ pymodule=pymodule, resource=resource)
+ return source
+
+ def occurs_in_module(self, pymodule=None, resource=None, imports=True):
+ finder = self._create_finder(imports)
+ for occurrence in finder.find_occurrences(pymodule=pymodule,
+ resource=resource):
+ return True
+ return False
+
+ def _create_finder(self, imports):
+ return occurrences.create_finder(self.project, self.old_name,
+ self.old_pyname, imports=imports)
+
+ def new_pymodule(self, pymodule, source):
+ if source is not None:
+ return libutils.get_string_module(
+ self.project, source, pymodule.get_resource())
+ return pymodule
+
+ def new_source(self, pymodule, source):
+ if source is None:
+ return pymodule.source_code
+ return source
+
+ def add_imports(self, pymodule, new_imports):
+ return _add_imports_to_module(self.import_tools, pymodule, new_imports)
+
+
+def _add_imports_to_module(import_tools, pymodule, new_imports):
+ module_with_imports = import_tools.module_imports(pymodule)
+ for new_import in new_imports:
+ module_with_imports.add_import(new_import)
+ return module_with_imports.get_changed_source()
+
+
+def moving_code_with_imports(project, resource, source):
+ import_tools = importutils.ImportTools(project)
+ pymodule = libutils.get_string_module(project, source, resource)
+ origin = project.get_pymodule(resource)
+
+ imports = []
+ for stmt in import_tools.module_imports(origin).imports:
+ imports.append(stmt.import_info)
+
+ back_names = []
+ for name in origin:
+ if name not in pymodule:
+ back_names.append(name)
+ imports.append(import_tools.get_from_import(resource, back_names))
+
+ source = _add_imports_to_module(import_tools, pymodule, imports)
+ pymodule = libutils.get_string_module(project, source, resource)
+
+ source = import_tools.relatives_to_absolutes(pymodule)
+ pymodule = libutils.get_string_module(project, source, resource)
+ source = import_tools.organize_imports(pymodule, selfs=False)
+ pymodule = libutils.get_string_module(project, source, resource)
+
+ # extracting imports after changes
+ module_imports = import_tools.module_imports(pymodule)
+ imports = [import_stmt.import_info
+ for import_stmt in module_imports.imports]
+ start = 1
+ if module_imports.imports:
+ start = module_imports.imports[-1].end_line
+ lines = codeanalyze.SourceLinesAdapter(source)
+ while start < lines.length() and not lines.get_line(start).strip():
+ start += 1
+ moving = source[lines.get_line_start(start):]
+ return moving, imports
+
+
+class ModuleSkipRenamerHandle(object):
+
+ def occurred_outside_skip(self, change_collector, occurrence):
+ pass
+
+ def occurred_inside_skip(self, change_collector, occurrence):
+ pass
+
+
+class ModuleSkipRenamer(object):
+ """Rename occurrences in a module
+
+ This class can be used when you want to treat a region in a file
+ separately from other parts when renaming.
+
+ """
+
+ def __init__(self, occurrence_finder, resource, handle=None,
+ skip_start=0, skip_end=0, replacement=''):
+ """Constructor
+
+ if replacement is `None` the region is not changed. Otherwise
+ it is replaced with `replacement`.
+
+ """
+ self.occurrence_finder = occurrence_finder
+ self.resource = resource
+ self.skip_start = skip_start
+ self.skip_end = skip_end
+ self.replacement = replacement
+ self.handle = handle
+ if self.handle is None:
+ self.handle = ModuleSkipRenamerHandle()
+
+ def get_changed_module(self):
+ source = self.resource.read()
+ change_collector = codeanalyze.ChangeCollector(source)
+ if self.replacement is not None:
+ change_collector.add_change(self.skip_start, self.skip_end,
+ self.replacement)
+ for occurrence in self.occurrence_finder.find_occurrences(
+ self.resource):
+ start, end = occurrence.get_primary_range()
+ if self.skip_start <= start < self.skip_end:
+ self.handle.occurred_inside_skip(change_collector, occurrence)
+ else:
+ self.handle.occurred_outside_skip(change_collector, occurrence)
+ result = change_collector.get_changed()
+ if result is not None and result != source:
+ return result

Powered by Google App Engine
This is Rietveld 408576698