init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
265
.venv/lib/python3.8/site-packages/rope/refactor/rename.py
Normal file
265
.venv/lib/python3.8/site-packages/rope/refactor/rename.py
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
import warnings
|
||||
|
||||
from rope.base import (
|
||||
exceptions,
|
||||
pyobjects,
|
||||
pynames,
|
||||
taskhandle,
|
||||
evaluate,
|
||||
worder,
|
||||
codeanalyze,
|
||||
libutils,
|
||||
)
|
||||
from rope.base.change import ChangeSet, ChangeContents, MoveResource
|
||||
from rope.refactor import occurrences
|
||||
|
||||
|
||||
class Rename(object):
|
||||
"""A class for performing rename refactoring
|
||||
|
||||
It can rename everything: classes, functions, modules, packages,
|
||||
methods, variables and keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, project, resource, offset=None):
|
||||
"""If `offset` is None, the `resource` itself will be renamed"""
|
||||
self.project = project
|
||||
self.resource = resource
|
||||
if offset is not None:
|
||||
self.old_name = worder.get_name_at(self.resource, offset)
|
||||
this_pymodule = self.project.get_pymodule(self.resource)
|
||||
self.old_instance, self.old_pyname = evaluate.eval_location2(
|
||||
this_pymodule, offset
|
||||
)
|
||||
if self.old_pyname is None:
|
||||
raise exceptions.RefactoringError(
|
||||
"Rename refactoring should be performed"
|
||||
" on resolvable python identifiers."
|
||||
)
|
||||
else:
|
||||
if not resource.is_folder() and resource.name == "__init__.py":
|
||||
resource = resource.parent
|
||||
dummy_pymodule = libutils.get_string_module(self.project, "")
|
||||
self.old_instance = None
|
||||
self.old_pyname = pynames.ImportedModule(dummy_pymodule, resource=resource)
|
||||
if resource.is_folder():
|
||||
self.old_name = resource.name
|
||||
else:
|
||||
self.old_name = resource.name[:-3]
|
||||
|
||||
def get_old_name(self):
|
||||
return self.old_name
|
||||
|
||||
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` 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.project.get_python_files()
|
||||
changes = ChangeSet("Renaming <%s> to <%s>" % (self.old_name, new_name))
|
||||
finder = occurrences.create_finder(
|
||||
self.project,
|
||||
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 _is_allowed_to_move(self, resources, resource):
|
||||
if resource.is_folder():
|
||||
try:
|
||||
return resource.get_child("__init__.py") in resources
|
||||
except exceptions.ResourceNotFoundError:
|
||||
return False
|
||||
else:
|
||||
return resource in resources
|
||||
|
||||
def _is_renaming_a_module(self):
|
||||
if isinstance(self.old_pyname.get_object(), pyobjects.AbstractModule):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_method(self):
|
||||
pyname = self.old_pyname
|
||||
return (
|
||||
isinstance(pyname, pynames.DefinedName)
|
||||
and isinstance(pyname.get_object(), pyobjects.PyFunction)
|
||||
and isinstance(pyname.get_object().parent, pyobjects.PyClass)
|
||||
)
|
||||
|
||||
def _rename_module(self, resource, new_name, changes):
|
||||
if not resource.is_folder():
|
||||
new_name = new_name + ".py"
|
||||
parent_path = resource.parent.path
|
||||
if parent_path == "":
|
||||
new_location = new_name
|
||||
else:
|
||||
new_location = parent_path + "/" + new_name
|
||||
changes.add_change(MoveResource(resource, new_location))
|
||||
|
||||
|
||||
class ChangeOccurrences(object):
|
||||
"""A class for changing the occurrences of a name in a scope
|
||||
|
||||
This class replaces the occurrences of a name. Note that it only
|
||||
changes the scope containing the offset passed to the constructor.
|
||||
What's more it does not have any side-effects. That is for
|
||||
example changing occurrences of a module does not rename the
|
||||
module; it merely replaces the occurrences of that module in a
|
||||
scope with the given expression. This class is useful for
|
||||
performing many custom refactorings.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, project, resource, offset):
|
||||
self.project = project
|
||||
self.resource = resource
|
||||
self.offset = offset
|
||||
self.old_name = worder.get_name_at(resource, offset)
|
||||
self.pymodule = project.get_pymodule(self.resource)
|
||||
self.old_pyname = evaluate.eval_location(self.pymodule, offset)
|
||||
|
||||
def get_old_name(self):
|
||||
word_finder = worder.Worder(self.resource.read())
|
||||
return word_finder.get_primary_at(self.offset)
|
||||
|
||||
def _get_scope_offset(self):
|
||||
scope = self.pymodule.get_scope().get_inner_scope_for_offset(self.offset)
|
||||
return scope.get_region()
|
||||
|
||||
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.project,
|
||||
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 rename_in_module(
|
||||
occurrences_finder,
|
||||
new_name,
|
||||
resource=None,
|
||||
pymodule=None,
|
||||
replace_primary=False,
|
||||
region=None,
|
||||
reads=True,
|
||||
writes=True,
|
||||
):
|
||||
"""Returns the changed source or `None` if there is no changes"""
|
||||
if resource is not None:
|
||||
source_code = resource.read()
|
||||
else:
|
||||
source_code = pymodule.source_code
|
||||
change_collector = codeanalyze.ChangeCollector(source_code)
|
||||
for occurrence in occurrences_finder.find_occurrences(resource, pymodule):
|
||||
if replace_primary and occurrence.is_a_fixed_primary():
|
||||
continue
|
||||
if replace_primary:
|
||||
start, end = occurrence.get_primary_range()
|
||||
else:
|
||||
start, end = occurrence.get_word_range()
|
||||
if (not reads and not occurrence.is_written()) or (
|
||||
not writes and occurrence.is_written()
|
||||
):
|
||||
continue
|
||||
if region is None or region[0] <= start < region[1]:
|
||||
change_collector.add_change(start, end, new_name)
|
||||
return change_collector.get_changed()
|
||||
|
||||
|
||||
def _is_local(pyname):
|
||||
module, lineno = pyname.get_definition_location()
|
||||
if lineno is None:
|
||||
return False
|
||||
scope = module.get_scope().get_inner_scope_for_line(lineno)
|
||||
if isinstance(pyname, pynames.DefinedName) and scope.get_kind() in (
|
||||
"Function",
|
||||
"Class",
|
||||
):
|
||||
scope = scope.parent
|
||||
return (
|
||||
scope.get_kind() == "Function"
|
||||
and pyname in scope.get_names().values()
|
||||
and isinstance(pyname, pynames.AssignedName)
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue