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
def find_occurrences(project, resource, offset, unsure=False, resources=None, in_hierarchy=False, task_handle=taskhandle.NullTaskHandle()): """Return a list of `Location`\s If `unsure` is `True`, possible matches are returned, too. You can use `Location.unsure` to see which are unsure occurrences. `resources` can be a list of `rope.base.resource.File`\s that should be searched for occurrences; if `None` all python files in the project are searched. """ name = worder.get_name_at(resource, offset) this_pymodule = project.pycore.resource_to_pyobject(resource) primary, pyname = rope.base.evaluate.eval_location2(this_pymodule, offset) def is_match(occurrence): return unsure finder = occurrences.create_finder(project.pycore, name, pyname, unsure=is_match, in_hierarchy=in_hierarchy, instance=primary) if resources is None: resources = project.pycore.get_python_files() job_set = task_handle.create_jobset('Finding Occurrences', count=len(resources)) return _find_locations(finder, resources, job_set)
def _change_function_occurances(self, collector, function_start, function_end, new_name): finder = occurrences.create_finder(self.pycore, self.name, self.pyname) for occurrence in finder.find_occurrences(resource=self.resource): start, end = occurrence.get_primary_range() if function_start <= start < function_end: collector.add_change(start, end, new_name)
def _inline_variable(pycore, pymodule, pyname, name, remove=True, region=None): assignment = pyname.assignments[0] definition_line = assignment.ast_node.lineno lines = pymodule.lines logicals = pymodule.logical_lines start, end = logicals.logical_line_in(definition_line) definition_with_assignment = _join_lines( [lines.get_line(n) for n in range(start, end + 1)]) if assignment.levels: raise rope.base.exceptions.RefactoringError( 'Cannot inline tuple assignments.') definition = definition_with_assignment[definition_with_assignment.\ index('=') + 1:].strip() occurrence_finder = occurrences.create_finder(pycore, name, pyname) changed_source = rename.rename_in_module( occurrence_finder, definition, pymodule=pymodule, replace_primary=True, writes=False, region=region) if changed_source is None: changed_source = pymodule.source_code if remove: lines = codeanalyze.SourceLinesAdapter(changed_source) source = changed_source[:lines.get_line_start(start)] + \ changed_source[lines.get_line_end(end) + 1:] else: source = changed_source return source
def _calculate_definition(self, primary, pyname, call, host_vars, returns): header, to_be_inlined = self._calculate_header(primary, pyname, call) source = header + self.body mod = libutils.get_string_module(self.project, source) name_dict = mod.get_scope().get_names() all_names = [x for x in name_dict if not isinstance(name_dict[x], rope.base.builtins.BuiltinName)] # If there is a name conflict, all variable names # inside the inlined function are renamed if len(set(all_names).intersection(set(host_vars))) > 0: prefix = _DefinitionGenerator.unique_prefix.next() guest = libutils.get_string_module(self.project, source, self.resource) to_be_inlined = [prefix + item for item in to_be_inlined] for item in all_names: pyname = guest[item] occurrence_finder = occurrences.create_finder(self.project, item, pyname) source = rename.rename_in_module(occurrence_finder, prefix + item, pymodule=guest) guest = libutils.get_string_module(self.project, source, self.resource) # parameters not reassigned inside the functions are now inlined. for name in to_be_inlined: pymodule = libutils.get_string_module(self.project, source, self.resource) pyname = pymodule[name] source = _inline_variable(self.project, pymodule, pyname, name) return self._replace_returns_with(source, returns)
def find_occurrences(project, resource, offset, unsure=False, resources=None, in_hierarchy=False, task_handle=taskhandle.NullTaskHandle()): """Return a list of `Location`\s If `unsure` is `True`, possible matches are returned, too. You can use `Location.unsure` to see which are unsure occurrences. `resources` can be a list of `rope.base.resource.File`\s that should be searched for occurrences; if `None` all python files in the project are searched. """ name = worder.get_name_at(resource, offset) this_pymodule = project.get_pymodule(resource) primary, pyname = rope.base.evaluate.eval_location2( this_pymodule, offset) def is_match(occurrence): return unsure finder = occurrences.create_finder( project, name, pyname, unsure=is_match, in_hierarchy=in_hierarchy, instance=primary) if resources is None: resources = project.get_python_files() job_set = task_handle.create_jobset('Finding Occurrences', count=len(resources)) return _find_locations(finder, resources, job_set)
def _inline_variable(project, pymodule, pyname, name, remove=True, region=None, docs=False): definition = _getvardef(pymodule, pyname) start, end = _assigned_lineno(pymodule, pyname) occurrence_finder = occurrences.create_finder(project, name, pyname, docs=docs) changed_source = rename.rename_in_module(occurrence_finder, definition, pymodule=pymodule, replace_primary=True, writes=False, region=region) if changed_source is None: changed_source = pymodule.source_code if remove: lines = codeanalyze.SourceLinesAdapter(changed_source) source = changed_source[:lines.get_line_start(start)] + \ changed_source[lines.get_line_end(end) + 1:] else: source = changed_source return source
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 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
def __init__(self, *args, **kwds): super(InlineMethod, self).__init__(*args, **kwds) self.pyfunction = self.pyname.get_object() self.pymodule = self.pyfunction.get_module() self.resource = self.pyfunction.get_module().get_resource() self.occurrence_finder = occurrences.create_finder(self.project, self.name, self.pyname) self.normal_generator = _DefinitionGenerator(self.project, self.pyfunction) self._init_imports()
def _create_finder(self, imports): return occurrences.create_finder( self.project, self.old_name, self.old_pyname, imports=imports, keywords=False, )
def _get_body(self, host="host"): self_name = self._get_self_name() body = self_name + " = None\n" + self._get_unchanged_body() pymodule = libutils.get_string_module(self.project, body) finder = occurrences.create_finder(self.project, self_name, pymodule[self_name]) result = rename.rename_in_module(finder, host, pymodule=pymodule) if result is None: result = body return result[result.index("\n") + 1 :]
def __init__(self, *args, **kwds): super(InlineMethod, self).__init__(*args, **kwds) self.pyfunction = self.pyname.get_object() self.pymodule = self.pyfunction.get_module() self.resource = self.pyfunction.get_module().get_resource() self.occurrence_finder = occurrences.create_finder( self.project, self.name, self.pyname) self.normal_generator = _DefinitionGenerator(self.project, self.pyfunction) self._init_imports()
def _rename_occurrences(self, file_, changed_name, global_factory): finder = occurrences.create_finder(self.project, self.old_name, self.old_pyname, only_calls=True) result = rename.rename_in_module(finder, changed_name, resource=file_, replace_primary=global_factory) return result
def _get_body(self, host='host'): self_name = self._get_self_name() body = self_name + ' = None\n' + self._get_unchanged_body() pymodule = self.pycore.get_string_module(body) finder = occurrences.create_finder( self.pycore, self_name, pymodule[self_name]) result = rename.rename_in_module(finder, host, pymodule=pymodule) if result is None: result = body return result[result.index('\n') + 1:]
def _get_body(self, host='host'): self_name = self._get_self_name() body = self_name + ' = None\n' + self._get_unchanged_body() pymodule = libutils.get_string_module(self.project, body) finder = occurrences.create_finder(self.project, self_name, pymodule[self_name]) result = rename.rename_in_module(finder, host, pymodule=pymodule) if result is None: result = body return result[result.index('\n') + 1:]
def _get_body(self): body = sourceutils.get_body(self.pyfunction) for param in self._get_parameter_names(): body = param + ' = None\n' + body pymod = self.pycore.get_string_module(body, self.resource) pyname = pymod[param] finder = occurrences.create_finder(self.pycore, param, pyname) result = rename.rename_in_module(finder, 'self.' + param, pymodule=pymod) body = result[result.index('\n') + 1:] return body
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
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)
def _get_body(self): body = sourceutils.get_body(self.pyfunction) for param in self._get_parameter_names(): body = param + " = None\n" + body pymod = libutils.get_string_module(self.project, body, self.resource) pyname = pymod[param] finder = occurrences.create_finder(self.project, param, pyname) result = rename.rename_in_module(finder, "self." + param, pymodule=pymod) body = result[result.index("\n") + 1:] return body
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
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 _inline_variable(project, pymodule, pyname, name, remove=True, region=None): definition = _getvardef(pymodule, pyname) start, end = _assigned_lineno(pymodule, pyname) occurrence_finder = occurrences.create_finder(project, name, pyname) changed_source = rename.rename_in_module( occurrence_finder, definition, pymodule=pymodule, replace_primary=True, writes=False, region=region ) if changed_source is None: changed_source = pymodule.source_code if remove: lines = codeanalyze.SourceLinesAdapter(changed_source) source = changed_source[: lines.get_line_start(start)] + changed_source[lines.get_line_end(end) + 1 :] else: source = changed_source return source
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)
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 _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 _calculate_definition(self, primary, pyname, call, host_vars, returns): header, to_be_inlined = self._calculate_header(primary, pyname, call) source = header + self.body mod = libutils.get_string_module(self.project, source) name_dict = mod.get_scope().get_names() all_names = [ x for x in name_dict if not isinstance(name_dict[x], rope.base.builtins.BuiltinName) ] # If there is a name conflict, all variable names # inside the inlined function are renamed if len(set(all_names).intersection(set(host_vars))) > 0: prefix = next(_DefinitionGenerator.unique_prefix) guest = libutils.get_string_module(self.project, source, self.resource) to_be_inlined = [prefix + item for item in to_be_inlined] for item in all_names: pyname = guest[item] occurrence_finder = occurrences.create_finder( self.project, item, pyname) source = rename.rename_in_module(occurrence_finder, prefix + item, pymodule=guest) guest = libutils.get_string_module(self.project, source, self.resource) #parameters not reassigned inside the functions are now inlined. for name in to_be_inlined: pymodule = libutils.get_string_module(self.project, source, self.resource) pyname = pymodule[name] source = _inline_variable(self.project, pymodule, pyname, name) return self._replace_returns_with(source, returns)
def _create_finder(self, imports): return occurrences.create_finder(self.project, self.old_name, self.old_pyname, imports=imports, keywords=False)
def _rename_occurrences(self, file_, changed_name, global_factory): finder = occurrences.create_finder(self.pycore, self.old_name, self.old_pyname, only_calls=True) result = rename.rename_in_module(finder, changed_name, resource=file_, replace_primary=global_factory) return result
def __init__(self, project, name, pyname, getter, setter): self.project = project self.name = name self.finder = occurrences.create_finder(project, name, pyname) self.getter = getter self.setter = setter
def _create_finder(self, imports): return occurrences.create_finder(self.pycore, self.old_name, self.old_pyname, imports=imports)
def __init__(self, pycore, name, pyname, getter, setter): self.pycore = pycore self.name = name self.finder = occurrences.create_finder(pycore, name, pyname) self.getter = getter self.setter = setter