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__' |