예제 #1
0
    def get_changes(self,
                    remove=True,
                    only_current=False,
                    resources=None,
                    docs=False,
                    task_handle=taskhandle.NullTaskHandle()):
        if resources is None:
            if rename._is_local(self.pyname):
                resources = [self.resource]
            else:
                resources = self.project.get_python_files()
        if only_current:
            resources = [self.original]
            if remove and self.original != self.resource:
                resources.append(self.resource)
        changes = ChangeSet('Inline variable <%s>' % self.name)
        jobset = task_handle.create_jobset('Calculating changes',
                                           len(resources))

        for resource in resources:
            jobset.started_job(resource.path)
            if resource == self.resource:
                source = self._change_main_module(remove, only_current, docs)
                changes.add_change(ChangeContents(self.resource, source))
            else:
                result = self._change_module(resource, remove, only_current)
                if result is not None:
                    result = _add_imports(self.project, result, resource,
                                          self.imports)
                    changes.add_change(ChangeContents(resource, result))
            jobset.finished_job()
        return changes
예제 #2
0
    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` 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
예제 #3
0
    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)
예제 #4
0
 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
예제 #5
0
 def _change_calls(
         self,
         call_changer,
         in_hierarchy=None,
         resources=None,
         handle=taskhandle.NullTaskHandle(),
 ):
     if resources is None:
         resources = self.project.get_python_files()
     changes = ChangeSet("Changing signature of <%s>" % self.name)
     job_set = handle.create_jobset("Collecting Changes", len(resources))
     finder = occurrences.create_finder(
         self.project,
         self.name,
         self.pyname,
         instance=self.primary,
         in_hierarchy=in_hierarchy and self.is_method(),
     )
     if self.others:
         name, pyname = self.others
         constructor_finder = occurrences.create_finder(self.project,
                                                        name,
                                                        pyname,
                                                        only_calls=True)
         finder = _MultipleFinders([finder, constructor_finder])
     for file in resources:
         job_set.started_job(file.path)
         change_calls = _ChangeCallsInModule(self.project, finder, file,
                                             call_changer)
         changed_file = change_calls.get_changed_module()
         if changed_file is not None:
             changes.add_change(ChangeContents(file, changed_file))
         job_set.finished_job()
     return changes
예제 #6
0
    def _change_module(self, resources, changes,
                       factory_name, global_, job_set):
        if global_:
            replacement = '__rope_factory_%s_' % factory_name
        else:
            replacement = self._new_function_name(factory_name, global_)

        for file_ in resources:
            job_set.started_job(file_.path)
            if file_ == self.resource:
                self._change_resource(changes, factory_name, global_)
                job_set.finished_job()
                continue
            changed_code = self._rename_occurrences(file_, replacement,
                                                    global_)
            if changed_code is not None:
                if global_:
                    new_pymodule = libutils.get_string_module(
                        self.project, changed_code, self.resource)
                    modname = libutils.modname(self.resource)
                    changed_code, imported = importutils.add_import(
                        self.project, new_pymodule, modname, factory_name)
                    changed_code = changed_code.replace(replacement, imported)
                changes.add_change(ChangeContents(file_, changed_code))
            job_set.finished_job()
예제 #7
0
    def _dest_module_changes(self, dest):
        # Changing occurrences
        pymodule = self.pycore.resource_to_pyobject(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
        if module_with_imports.imports:
            start = pymodule.lines.get_line_end(
                module_with_imports.imports[-1].end_line - 1)
            result = source[:start + 1] + '\n\n'
        else:
            result = ''
            start = -1
        result += moving + source[start + 1:]

        # Organizing imports
        source = result
        pymodule = self.pycore.get_string_module(source, dest)
        source = self.import_tools.organize_imports(pymodule, sort=False,
                                                    unused=False)
        return ChangeContents(dest, source)
예제 #8
0
    def get_changes(self, new_name, in_file=None, in_hierarchy=False,
                    unsure=None, docs=False, resources=None,
                    task_handle=taskhandle.NullTaskHandle()):
        """Get the changes needed for this refactoring

        Parameters:

        - `in_hierarchy`: when renaming a method this keyword forces
          to rename all matching methods in the hierarchy
        - `docs`: when `True` rename refactoring will rename
          occurrences in comments and strings where the name is
          visible.  Setting it will make renames faster, too.
        - `unsure`: decides what to do about unsure occurrences.
          If `None`, they are ignored.  Otherwise `unsure` is
          called with an instance of `occurrence.Occurrence` as
          parameter.  If it returns `True`, the occurrence is
          considered to be a match.
        - `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.
        - `in_file`: this argument has been deprecated; use
          `resources` instead.

        """
        if unsure in (True, False):
            warnings.warn(
                'unsure parameter should be a function that returns '
                'True or False', DeprecationWarning, stacklevel=2)
            def unsure_func(value=unsure):
                return value
            unsure = unsure_func
        if in_file is not None:
            warnings.warn(
                '`in_file` argument has been deprecated; use `resources` '
                'instead. ', DeprecationWarning, stacklevel=2)
            if in_file:
                resources = [self.resource]
        if _is_local(self.old_pyname):
            resources = [self.resource]
        if resources is None:
            resources = self.pycore.get_python_files()
        changes = ChangeSet('Renaming <%s> to <%s>' %
                            (self.old_name, new_name))
        finder = occurrences.create_finder(
            self.pycore, self.old_name, self.old_pyname, unsure=unsure,
            docs=docs, instance=self.old_instance,
            in_hierarchy=in_hierarchy and self.is_method())
        job_set = task_handle.create_jobset('Collecting Changes', len(resources))
        for file_ in resources:
            job_set.started_job(file_.path)
            new_content = rename_in_module(finder, new_name, resource=file_)
            if new_content is not None:
                changes.add_change(ChangeContents(file_, new_content))
            job_set.finished_job()
        if self._is_renaming_a_module():
            resource = self.old_pyname.get_object().get_resource()
            if self._is_allowed_to_move(resources, resource):
                self._rename_module(resource, new_name, changes)
        return changes
예제 #9
0
 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))
예제 #10
0
    def get_changes(self,
                    getter=None,
                    setter=None,
                    resources=None,
                    task_handle=taskhandle.NullTaskHandle()):
        """Get the changes this refactoring makes

        If `getter` is not `None`, that will be the name of the
        getter, otherwise ``get_${field_name}`` will be used.  The
        same is true for `setter` and if it is None set_${field_name} is
        used.

        `resources` can be a list of `rope.base.resource.File`\s that
        the refactoring should be applied on; if `None` all python
        files in the project are searched.

        """
        if resources is None:
            resources = self.project.get_python_files()
        changes = ChangeSet('Encapsulate field <%s>' % self.name)
        job_set = task_handle.create_jobset('Collecting Changes',
                                            len(resources))
        if getter is None:
            getter = 'get_' + self.name
        if setter is None:
            setter = 'set_' + self.name
        renamer = GetterSetterRenameInModule(self.project, self.name,
                                             self.pyname, getter, setter)
        for file in resources:
            job_set.started_job(file.path)
            if file == self.resource:
                result = self._change_holding_module(changes, renamer, getter,
                                                     setter)
                changes.add_change(ChangeContents(self.resource, result))
            else:
                result = renamer.get_changed_module(file)
                if result is not None:
                    changes.add_change(ChangeContents(file, result))
            job_set.finished_job()
        return changes
예제 #11
0
 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
예제 #12
0
 def get_changes(self, new_name, only_calls=False, reads=True, writes=True):
     changes = ChangeSet('Changing <%s> occurrences to <%s>' %
                         (self.old_name, new_name))
     scope_start, scope_end = self._get_scope_offset()
     finder = occurrences.create_finder(
         self.pycore, self.old_name, self.old_pyname,
         imports=False, only_calls=only_calls)
     new_contents = rename_in_module(
         finder, new_name, pymodule=self.pymodule, replace_primary=True,
         region=(scope_start, scope_end), reads=reads, writes=writes)
     if new_contents is not None:
         changes.add_change(ChangeContents(self.resource, new_contents))
     return changes
예제 #13
0
 def _source_module_changes(self, dest):
     placeholder = '__rope_moving_%s_' % self.old_name
     handle = _ChangeMoveOccurrencesHandle(placeholder)
     occurrence_finder = occurrences.create_finder(
         self.pycore, 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 = self.pycore.get_string_module(source, self.source)
         # Adding new import
         source, imported = importutils.add_import(
             self.pycore, pymodule, self._new_modname(dest), self.old_name)
         source = source.replace(placeholder, imported)
     return ChangeContents(self.source, source)
예제 #14
0
 def get_changes(self):
     changes = ChangeSet('Transform <%s> module to package' %
                         self.resource.path)
     new_content = self._transform_relatives_to_absolute(self.resource)
     if new_content is not None:
         changes.add_change(ChangeContents(self.resource, new_content))
     parent = self.resource.parent
     name = self.resource.name[:-3]
     changes.add_change(CreateFolder(parent, name))
     parent_path = parent.path + '/'
     if not parent.path:
         parent_path = ''
     new_path = parent_path + '%s/__init__.py' % name
     if self.resource.project == self.project:
         changes.add_change(MoveResource(self.resource, new_path))
     return changes
예제 #15
0
 def _change_resource(self, changes, factory_name, global_):
     class_scope = self.old_pyname.get_object().get_scope()
     source_code = self._rename_occurrences(
         self.resource, self._new_function_name(factory_name,
                                                global_), global_)
     if source_code is None:
         source_code = self.pymodule.source_code
     else:
         self.pymodule = libutils.get_string_module(
             self.project, source_code, resource=self.resource)
     lines = self.pymodule.lines
     start = self._get_insertion_offset(class_scope, lines)
     result = source_code[:start]
     result += self._get_factory_method(lines, class_scope,
                                        factory_name, global_)
     result += source_code[start:]
     changes.add_change(ChangeContents(self.resource, result))
예제 #16
0
 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
예제 #17
0
    def get_changes(self,
                    remove=True,
                    only_current=False,
                    resources=None,
                    task_handle=taskhandle.NullTaskHandle()):
        """Get the changes this refactoring makes

        If `remove` is `False` the definition will not be removed.  If
        `only_current` is `True`, the the current occurrence will be
        inlined, only.
        """
        changes = ChangeSet('Inline method <%s>' % self.name)
        if resources is None:
            resources = self.project.get_python_files()
        if only_current:
            resources = [self.original]
            if remove:
                resources.append(self.resource)
        job_set = task_handle.create_jobset('Collecting Changes',
                                            len(resources))
        for file in resources:
            job_set.started_job(file.path)
            if file == self.resource:
                changes.add_change(
                    self._defining_file_changes(changes,
                                                remove=remove,
                                                only_current=only_current))
            else:
                aim = None
                if only_current and self.original == file:
                    aim = self.offset
                handle = _InlineFunctionCallsForModuleHandle(
                    self.project, file, self.others_generator, aim)
                result = move.ModuleSkipRenamer(self.occurrence_finder, file,
                                                handle).get_changed_module()
                if result is not None:
                    result = _add_imports(self.project, result, file,
                                          self.imports)
                    if remove:
                        result = _remove_from(self.project, self.pyname,
                                              result, file)
                    changes.add_change(ChangeContents(file, result))
            job_set.finished_job()
        return changes
예제 #18
0
    def get_changes(self, extracted_name, similar=False, global_=False):
        """Get the changes this refactoring makes

        :parameters:
            - `similar`: if `True`, similar expressions/statements are also
              replaced.
            - `global_`: if `True`, the extracted method/variable will
              be global.

        """
        info = _ExtractInfo(
            self.project, self.resource, self.start_offset, self.end_offset,
            extracted_name, variable=self.kind == 'variable',
            similar=similar, make_global=global_)
        new_contents = _ExtractPerformer(info).extract()
        changes = ChangeSet('Extract %s <%s>' % (self.kind,
                                                 extracted_name))
        changes.add_change(ChangeContents(self.resource, new_contents))
        return changes
예제 #19
0
 def _defining_file_changes(self, changes, remove, only_current):
     start_offset, end_offset = self._get_removed_range()
     aim = None
     if only_current:
         if self.resource == self.original:
             aim = self.offset
         else:
             # we don't want to change any of them
             aim = len(self.resource.read()) + 100
     handle = _InlineFunctionCallsForModuleHandle(
         self.project, self.resource,
         self.normal_generator, aim_offset=aim)
     replacement = None
     if remove:
         replacement = self._get_method_replacement()
     result = move.ModuleSkipRenamer(
         self.occurrence_finder, self.resource, handle, start_offset,
         end_offset, replacement).get_changed_module()
     return ChangeContents(self.resource, result)