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