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

Unified Diff: tools/telemetry/third_party/rope/rope/refactor/importutils/actions.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/actions.py
diff --git a/tools/telemetry/third_party/rope/rope/refactor/importutils/actions.py b/tools/telemetry/third_party/rope/rope/refactor/importutils/actions.py
new file mode 100644
index 0000000000000000000000000000000000000000..fd0f70542b10521b2126d0134efa1db30d1e028b
--- /dev/null
+++ b/tools/telemetry/third_party/rope/rope/refactor/importutils/actions.py
@@ -0,0 +1,361 @@
+from rope.base import libutils
+from rope.base import pyobjects, exceptions, stdmods
+from rope.refactor import occurrences
+from rope.refactor.importutils import importinfo
+
+
+class ImportInfoVisitor(object):
+
+ def dispatch(self, import_):
+ try:
+ method_name = 'visit' + import_.import_info.__class__.__name__
+ method = getattr(self, method_name)
+ return method(import_, import_.import_info)
+ except exceptions.ModuleNotFoundError:
+ pass
+
+ def visitEmptyImport(self, import_stmt, import_info):
+ pass
+
+ def visitNormalImport(self, import_stmt, import_info):
+ pass
+
+ def visitFromImport(self, import_stmt, import_info):
+ pass
+
+
+class RelativeToAbsoluteVisitor(ImportInfoVisitor):
+
+ def __init__(self, project, current_folder):
+ self.to_be_absolute = []
+ self.project = project
+ self.folder = current_folder
+ self.context = importinfo.ImportContext(project, current_folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ self.to_be_absolute.extend(
+ self._get_relative_to_absolute_list(import_info))
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ resource = self.project.find_module(name, folder=self.folder)
+ if resource is None:
+ new_pairs.append((name, alias))
+ continue
+ absolute_name = libutils.modname(resource)
+ new_pairs.append((absolute_name, alias))
+ if not import_info._are_name_and_alias_lists_equal(
+ new_pairs, import_info.names_and_aliases):
+ import_stmt.import_info = importinfo.NormalImport(new_pairs)
+
+ def _get_relative_to_absolute_list(self, import_info):
+ result = []
+ for name, alias in import_info.names_and_aliases:
+ if alias is not None:
+ continue
+ resource = self.project.find_module(name, folder=self.folder)
+ if resource is None:
+ continue
+ absolute_name = libutils.modname(resource)
+ if absolute_name != name:
+ result.append((name, absolute_name))
+ return result
+
+ def visitFromImport(self, import_stmt, import_info):
+ resource = import_info.get_imported_resource(self.context)
+ if resource is None:
+ return None
+ absolute_name = libutils.modname(resource)
+ if import_info.module_name != absolute_name:
+ import_stmt.import_info = importinfo.FromImport(
+ absolute_name, 0, import_info.names_and_aliases)
+
+
+class FilteringVisitor(ImportInfoVisitor):
+
+ def __init__(self, project, folder, can_select):
+ self.to_be_absolute = []
+ self.project = project
+ self.can_select = self._transform_can_select(can_select)
+ self.context = importinfo.ImportContext(project, folder)
+
+ def _transform_can_select(self, can_select):
+ def can_select_name_and_alias(name, alias):
+ imported = name
+ if alias is not None:
+ imported = alias
+ return can_select(imported)
+ return can_select_name_and_alias
+
+ def visitNormalImport(self, import_stmt, import_info):
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ if self.can_select(name, alias):
+ new_pairs.append((name, alias))
+ return importinfo.NormalImport(new_pairs)
+
+ def visitFromImport(self, import_stmt, import_info):
+ if _is_future(import_info):
+ return import_info
+ new_pairs = []
+ if import_info.is_star_import():
+ for name in import_info.get_imported_names(self.context):
+ if self.can_select(name, None):
+ new_pairs.append(import_info.names_and_aliases[0])
+ break
+ else:
+ for name, alias in import_info.names_and_aliases:
+ if self.can_select(name, alias):
+ new_pairs.append((name, alias))
+ return importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+
+
+class RemovingVisitor(ImportInfoVisitor):
+
+ def __init__(self, project, folder, can_select):
+ self.to_be_absolute = []
+ self.project = project
+ self.filtering = FilteringVisitor(project, folder, can_select)
+
+ def dispatch(self, import_):
+ result = self.filtering.dispatch(import_)
+ if result is not None:
+ import_.import_info = result
+
+
+class AddingVisitor(ImportInfoVisitor):
+ """A class for adding imports
+
+ Given a list of `ImportInfo`\s, it tries to add each import to the
+ module and returns `True` and gives up when an import can be added
+ to older ones.
+
+ """
+
+ def __init__(self, project, import_list):
+ self.project = project
+ self.import_list = import_list
+ self.import_info = None
+
+ def dispatch(self, import_):
+ for import_info in self.import_list:
+ self.import_info = import_info
+ if ImportInfoVisitor.dispatch(self, import_):
+ return True
+
+ # TODO: Handle adding relative and absolute imports
+ def visitNormalImport(self, import_stmt, import_info):
+ if not isinstance(self.import_info, import_info.__class__):
+ return False
+ # Adding ``import x`` and ``import x.y`` that results ``import x.y``
+ if len(import_info.names_and_aliases) == \
+ len(self.import_info.names_and_aliases) == 1:
+ imported1 = import_info.names_and_aliases[0]
+ imported2 = self.import_info.names_and_aliases[0]
+ if imported1[1] == imported2[1] is None:
+ if imported1[0].startswith(imported2[0] + '.'):
+ return True
+ if imported2[0].startswith(imported1[0] + '.'):
+ import_stmt.import_info = self.import_info
+ return True
+ # Multiple imports using a single import statement is discouraged
+ # so we won't bother adding them.
+ if self.import_info._are_name_and_alias_lists_equal(
+ import_info.names_and_aliases,
+ self.import_info.names_and_aliases):
+ return True
+
+ def visitFromImport(self, import_stmt, import_info):
+ if isinstance(self.import_info, import_info.__class__) and \
+ import_info.module_name == self.import_info.module_name and \
+ import_info.level == self.import_info.level:
+ if import_info.is_star_import():
+ return True
+ if self.import_info.is_star_import():
+ import_stmt.import_info = self.import_info
+ return True
+ if self.project.prefs.get("split_imports"):
+ return self.import_info.names_and_aliases == \
+ import_info.names_and_aliases
+ new_pairs = list(import_info.names_and_aliases)
+ for pair in self.import_info.names_and_aliases:
+ if pair not in new_pairs:
+ new_pairs.append(pair)
+ import_stmt.import_info = importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+ return True
+
+
+class ExpandStarsVisitor(ImportInfoVisitor):
+
+ def __init__(self, project, folder, can_select):
+ self.project = project
+ self.filtering = FilteringVisitor(project, folder, can_select)
+ self.context = importinfo.ImportContext(project, folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ self.filtering.dispatch(import_stmt)
+
+ def visitFromImport(self, import_stmt, import_info):
+ if import_info.is_star_import():
+ new_pairs = []
+ for name in import_info.get_imported_names(self.context):
+ new_pairs.append((name, None))
+ new_import = importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+ import_stmt.import_info = \
+ self.filtering.visitFromImport(None, new_import)
+ else:
+ self.filtering.dispatch(import_stmt)
+
+
+class SelfImportVisitor(ImportInfoVisitor):
+
+ def __init__(self, project, current_folder, resource):
+ self.project = project
+ self.folder = current_folder
+ self.resource = resource
+ self.to_be_fixed = set()
+ self.to_be_renamed = set()
+ self.context = importinfo.ImportContext(project, current_folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ resource = self.project.find_module(name, folder=self.folder)
+ if resource is not None and resource == self.resource:
+ imported = name
+ if alias is not None:
+ imported = alias
+ self.to_be_fixed.add(imported)
+ else:
+ new_pairs.append((name, alias))
+ if not import_info._are_name_and_alias_lists_equal(
+ new_pairs, import_info.names_and_aliases):
+ import_stmt.import_info = importinfo.NormalImport(new_pairs)
+
+ def visitFromImport(self, import_stmt, import_info):
+ resource = import_info.get_imported_resource(self.context)
+ if resource is None:
+ return
+ if resource == self.resource:
+ self._importing_names_from_self(import_info, import_stmt)
+ return
+ pymodule = self.project.get_pymodule(resource)
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ try:
+ result = pymodule[name].get_object()
+ if isinstance(result, pyobjects.PyModule) and \
+ result.get_resource() == self.resource:
+ imported = name
+ if alias is not None:
+ imported = alias
+ self.to_be_fixed.add(imported)
+ else:
+ new_pairs.append((name, alias))
+ except exceptions.AttributeNotFoundError:
+ new_pairs.append((name, alias))
+ if not import_info._are_name_and_alias_lists_equal(
+ new_pairs, import_info.names_and_aliases):
+ import_stmt.import_info = importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+
+ def _importing_names_from_self(self, import_info, import_stmt):
+ if not import_info.is_star_import():
+ for name, alias in import_info.names_and_aliases:
+ if alias is not None:
+ self.to_be_renamed.add((alias, name))
+ import_stmt.empty_import()
+
+
+class SortingVisitor(ImportInfoVisitor):
+
+ def __init__(self, project, current_folder):
+ self.project = project
+ self.folder = current_folder
+ self.standard = set()
+ self.third_party = set()
+ self.in_project = set()
+ self.future = set()
+ self.context = importinfo.ImportContext(project, current_folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ if import_info.names_and_aliases:
+ name, alias = import_info.names_and_aliases[0]
+ resource = self.project.find_module(
+ name, folder=self.folder)
+ self._check_imported_resource(import_stmt, resource, name)
+
+ def visitFromImport(self, import_stmt, import_info):
+ resource = import_info.get_imported_resource(self.context)
+ self._check_imported_resource(import_stmt, resource,
+ import_info.module_name)
+
+ def _check_imported_resource(self, import_stmt, resource, imported_name):
+ info = import_stmt.import_info
+ if resource is not None and resource.project == self.project:
+ self.in_project.add(import_stmt)
+ elif _is_future(info):
+ self.future.add(import_stmt)
+ elif imported_name.split('.')[0] in stdmods.standard_modules():
+ self.standard.add(import_stmt)
+ else:
+ self.third_party.add(import_stmt)
+
+
+class LongImportVisitor(ImportInfoVisitor):
+
+ def __init__(self, current_folder, project, maxdots, maxlength):
+ self.maxdots = maxdots
+ self.maxlength = maxlength
+ self.to_be_renamed = set()
+ self.current_folder = current_folder
+ self.project = project
+ self.new_imports = []
+
+ def visitNormalImport(self, import_stmt, import_info):
+ for name, alias in import_info.names_and_aliases:
+ if alias is None and self._is_long(name):
+ self.to_be_renamed.add(name)
+ last_dot = name.rindex('.')
+ from_ = name[:last_dot]
+ imported = name[last_dot + 1:]
+ self.new_imports.append(
+ importinfo.FromImport(from_, 0, ((imported, None), )))
+
+ def _is_long(self, name):
+ return name.count('.') > self.maxdots or \
+ ('.' in name and len(name) > self.maxlength)
+
+
+class RemovePyNameVisitor(ImportInfoVisitor):
+
+ def __init__(self, project, pymodule, pyname, folder):
+ self.pymodule = pymodule
+ self.pyname = pyname
+ self.context = importinfo.ImportContext(project, folder)
+
+ def visitFromImport(self, import_stmt, import_info):
+ new_pairs = []
+ if not import_info.is_star_import():
+ for name, alias in import_info.names_and_aliases:
+ try:
+ pyname = self.pymodule[alias or name]
+ if occurrences.same_pyname(self.pyname, pyname):
+ continue
+ except exceptions.AttributeNotFoundError:
+ pass
+ new_pairs.append((name, alias))
+ return importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+
+ def dispatch(self, import_):
+ result = ImportInfoVisitor.dispatch(self, import_)
+ if result is not None:
+ import_.import_info = result
+
+
+def _is_future(info):
+ return isinstance(info, importinfo.FromImport) and \
+ info.module_name == '__future__'

Powered by Google App Engine
This is Rietveld 408576698