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

Unified Diff: tools/telemetry/third_party/rope/rope/refactor/importutils/__init__.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/importutils/__init__.py
diff --git a/tools/telemetry/third_party/rope/rope/refactor/importutils/__init__.py b/tools/telemetry/third_party/rope/rope/refactor/importutils/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..4871faf317fab26c43fe54e44eb70c279172fa54
--- /dev/null
+++ b/tools/telemetry/third_party/rope/rope/refactor/importutils/__init__.py
@@ -0,0 +1,311 @@
+"""A package for handling imports
+
+This package provides tools for modifying module imports after
+refactorings or as a separate task.
+
+"""
+import rope.base.evaluate
+from rope.base import libutils
+from rope.base.change import ChangeSet, ChangeContents
+from rope.refactor import occurrences, rename
+from rope.refactor.importutils import module_imports, actions
+from rope.refactor.importutils.importinfo import NormalImport, FromImport
+import rope.base.codeanalyze
+
+
+class ImportOrganizer(object):
+ """Perform some import-related commands
+
+ Each method returns a `rope.base.change.Change` object.
+
+ """
+
+ def __init__(self, project):
+ self.project = project
+ self.import_tools = ImportTools(self.project)
+
+ def organize_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.organize_imports, resource, offset)
+
+ def expand_star_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.expand_stars, resource, offset)
+
+ def froms_to_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.froms_to_imports, resource, offset)
+
+ def relatives_to_absolutes(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.relatives_to_absolutes, resource, offset)
+
+ def handle_long_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.handle_long_imports, resource, offset)
+
+ def _perform_command_on_import_tools(self, method, resource, offset):
+ pymodule = self.project.get_pymodule(resource)
+ before_performing = pymodule.source_code
+ import_filter = None
+ if offset is not None:
+ import_filter = self._line_filter(
+ pymodule.lines.get_line_number(offset))
+ result = method(pymodule, import_filter=import_filter)
+ if result is not None and result != before_performing:
+ changes = ChangeSet(method.__name__.replace('_', ' ') +
+ ' in <%s>' % resource.path)
+ changes.add_change(ChangeContents(resource, result))
+ return changes
+
+ def _line_filter(self, lineno):
+ def import_filter(import_stmt):
+ return import_stmt.start_line <= lineno < import_stmt.end_line
+ return import_filter
+
+
+class ImportTools(object):
+
+ def __init__(self, project):
+ self.project = project
+
+ def get_import(self, resource):
+ """The import statement for `resource`"""
+ module_name = libutils.modname(resource)
+ return NormalImport(((module_name, None), ))
+
+ def get_from_import(self, resource, name):
+ """The from import statement for `name` in `resource`"""
+ module_name = libutils.modname(resource)
+ names = []
+ if isinstance(name, list):
+ names = [(imported, None) for imported in name]
+ else:
+ names = [(name, None), ]
+ return FromImport(module_name, 0, tuple(names))
+
+ def module_imports(self, module, imports_filter=None):
+ return module_imports.ModuleImports(self.project, module,
+ imports_filter)
+
+ def froms_to_imports(self, pymodule, import_filter=None):
+ pymodule = self._clean_up_imports(pymodule, import_filter)
+ module_imports = self.module_imports(pymodule, import_filter)
+ for import_stmt in module_imports.imports:
+ if import_stmt.readonly or \
+ not self._is_transformable_to_normal(import_stmt.import_info):
+ continue
+ pymodule = self._from_to_normal(pymodule, import_stmt)
+
+ # Adding normal imports in place of froms
+ module_imports = self.module_imports(pymodule, import_filter)
+ for import_stmt in module_imports.imports:
+ if not import_stmt.readonly and \
+ self._is_transformable_to_normal(import_stmt.import_info):
+ import_stmt.import_info = \
+ NormalImport(((import_stmt.import_info.module_name,
+ None),))
+ module_imports.remove_duplicates()
+ return module_imports.get_changed_source()
+
+ def expand_stars(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.expand_stars()
+ return module_imports.get_changed_source()
+
+ def _from_to_normal(self, pymodule, import_stmt):
+ resource = pymodule.get_resource()
+ from_import = import_stmt.import_info
+ module_name = from_import.module_name
+ for name, alias in from_import.names_and_aliases:
+ imported = name
+ if alias is not None:
+ imported = alias
+ occurrence_finder = occurrences.create_finder(
+ self.project, imported, pymodule[imported], imports=False)
+ source = rename.rename_in_module(
+ occurrence_finder, module_name + '.' + name,
+ pymodule=pymodule, replace_primary=True)
+ if source is not None:
+ pymodule = libutils.get_string_module(
+ self.project, source, resource)
+ return pymodule
+
+ def _clean_up_imports(self, pymodule, import_filter):
+ resource = pymodule.get_resource()
+ module_with_imports = self.module_imports(pymodule, import_filter)
+ module_with_imports.expand_stars()
+ source = module_with_imports.get_changed_source()
+ if source is not None:
+ pymodule = libutils.get_string_module(
+ self.project, source, resource)
+ source = self.relatives_to_absolutes(pymodule)
+ if source is not None:
+ pymodule = libutils.get_string_module(
+ self.project, source, resource)
+
+ module_with_imports = self.module_imports(pymodule, import_filter)
+ module_with_imports.remove_duplicates()
+ module_with_imports.remove_unused_imports()
+ source = module_with_imports.get_changed_source()
+ if source is not None:
+ pymodule = libutils.get_string_module(
+ self.project, source, resource)
+ return pymodule
+
+ def relatives_to_absolutes(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ to_be_absolute_list = module_imports.get_relative_to_absolute_list()
+ for name, absolute_name in to_be_absolute_list:
+ pymodule = self._rename_in_module(pymodule, name, absolute_name)
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.get_relative_to_absolute_list()
+ source = module_imports.get_changed_source()
+ if source is None:
+ source = pymodule.source_code
+ return source
+
+ def _is_transformable_to_normal(self, import_info):
+ if not isinstance(import_info, FromImport):
+ return False
+ return True
+
+ def organize_imports(self, pymodule,
+ unused=True, duplicates=True,
+ selfs=True, sort=True, import_filter=None):
+ if unused or duplicates:
+ module_imports = self.module_imports(pymodule, import_filter)
+ if unused:
+ module_imports.remove_unused_imports()
+ if self.project.prefs.get("split_imports"):
+ module_imports.force_single_imports()
+ if duplicates:
+ module_imports.remove_duplicates()
+ source = module_imports.get_changed_source()
+ if source is not None:
+ pymodule = libutils.get_string_module(
+ self.project, source, pymodule.get_resource())
+ if selfs:
+ pymodule = self._remove_self_imports(pymodule, import_filter)
+ if sort:
+ return self.sort_imports(pymodule, import_filter)
+ else:
+ return pymodule.source_code
+
+ def _remove_self_imports(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ to_be_fixed, to_be_renamed = \
+ module_imports.get_self_import_fix_and_rename_list()
+ for name in to_be_fixed:
+ try:
+ pymodule = self._rename_in_module(pymodule, name, '',
+ till_dot=True)
+ except ValueError:
+ # There is a self import with direct access to it
+ return pymodule
+ for name, new_name in to_be_renamed:
+ pymodule = self._rename_in_module(pymodule, name, new_name)
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.get_self_import_fix_and_rename_list()
+ source = module_imports.get_changed_source()
+ if source is not None:
+ pymodule = libutils.get_string_module(
+ self.project, source, pymodule.get_resource())
+ return pymodule
+
+ def _rename_in_module(self, pymodule, name, new_name, till_dot=False):
+ old_name = name.split('.')[-1]
+ old_pyname = rope.base.evaluate.eval_str(pymodule.get_scope(), name)
+ occurrence_finder = occurrences.create_finder(
+ self.project, old_name, old_pyname, imports=False)
+ changes = rope.base.codeanalyze.ChangeCollector(pymodule.source_code)
+ for occurrence in occurrence_finder.find_occurrences(
+ pymodule=pymodule):
+ start, end = occurrence.get_primary_range()
+ if till_dot:
+ new_end = pymodule.source_code.index('.', end) + 1
+ space = pymodule.source_code[end:new_end - 1].strip()
+ if not space == '':
+ for c in space:
+ if not c.isspace() and c not in '\\':
+ raise ValueError()
+ end = new_end
+ changes.add_change(start, end, new_name)
+ source = changes.get_changed()
+ if source is not None:
+ pymodule = libutils.get_string_module(
+ self.project, source, pymodule.get_resource())
+ return pymodule
+
+ def sort_imports(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.sort_imports()
+ return module_imports.get_changed_source()
+
+ def handle_long_imports(self, pymodule, maxdots=2, maxlength=27,
+ import_filter=None):
+ # IDEA: `maxdots` and `maxlength` can be specified in project config
+ # adding new from imports
+ module_imports = self.module_imports(pymodule, import_filter)
+ to_be_fixed = module_imports.handle_long_imports(maxdots, maxlength)
+ # performing the renaming
+ pymodule = libutils.get_string_module(
+ self.project, module_imports.get_changed_source(),
+ resource=pymodule.get_resource())
+ for name in to_be_fixed:
+ pymodule = self._rename_in_module(pymodule, name,
+ name.split('.')[-1])
+ # organizing imports
+ return self.organize_imports(pymodule, selfs=False, sort=False,
+ import_filter=import_filter)
+
+
+def get_imports(project, pydefined):
+ """A shortcut for getting the `ImportInfo`\s used in a scope"""
+ pymodule = pydefined.get_module()
+ module = module_imports.ModuleImports(project, pymodule)
+ if pymodule == pydefined:
+ return [stmt.import_info for stmt in module.imports]
+ return module.get_used_imports(pydefined)
+
+
+def get_module_imports(project, pymodule):
+ """A shortcut for creating a `module_imports.ModuleImports` object"""
+ return module_imports.ModuleImports(project, pymodule)
+
+
+def add_import(project, pymodule, module_name, name=None):
+ imports = get_module_imports(project, pymodule)
+ candidates = []
+ names = []
+ # from mod import name
+ if name is not None:
+ from_import = FromImport(module_name, 0, [(name, None)])
+ names.append(name)
+ candidates.append(from_import)
+ # from pkg import mod
+ if '.' in module_name:
+ pkg, mod = module_name.rsplit('.', 1)
+ candidates.append(FromImport(pkg, 0, [(mod, None)]))
+ if name:
+ names.append(mod + '.' + name)
+ else:
+ names.append(mod)
+ # import mod
+ normal_import = NormalImport([(module_name, None)])
+ if name:
+ names.append(module_name + '.' + name)
+ else:
+ names.append(module_name)
+
+ candidates.append(normal_import)
+
+ visitor = actions.AddingVisitor(project, candidates)
+ selected_import = normal_import
+ for import_statement in imports.imports:
+ if import_statement.accept(visitor):
+ selected_import = visitor.import_info
+ break
+ imports.add_import(selected_import)
+ imported_name = names[candidates.index(selected_import)]
+ return imports.get_changed_source(), imported_name

Powered by Google App Engine
This is Rietveld 408576698