init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
388
.venv/lib/python3.8/site-packages/rope/contrib/generate.py
Normal file
388
.venv/lib/python3.8/site-packages/rope/contrib/generate.py
Normal file
|
|
@ -0,0 +1,388 @@
|
|||
import rope.base.evaluate
|
||||
from rope.base import libutils
|
||||
from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze
|
||||
from rope.refactor import sourceutils, importutils, functionutils, suites
|
||||
|
||||
|
||||
def create_generate(kind, project, resource, offset, goal_resource=None):
|
||||
"""A factory for creating `Generate` objects
|
||||
|
||||
`kind` can be 'variable', 'function', 'class', 'module' or
|
||||
'package'.
|
||||
|
||||
"""
|
||||
generate = eval("Generate" + kind.title())
|
||||
return generate(project, resource, offset, goal_resource=goal_resource)
|
||||
|
||||
|
||||
def create_module(project, name, sourcefolder=None):
|
||||
"""Creates a module and returns a `rope.base.resources.File`"""
|
||||
if sourcefolder is None:
|
||||
sourcefolder = project.root
|
||||
packages = name.split(".")
|
||||
parent = sourcefolder
|
||||
for package in packages[:-1]:
|
||||
parent = parent.get_child(package)
|
||||
return parent.create_file(packages[-1] + ".py")
|
||||
|
||||
|
||||
def create_package(project, name, sourcefolder=None):
|
||||
"""Creates a package and returns a `rope.base.resources.Folder`"""
|
||||
if sourcefolder is None:
|
||||
sourcefolder = project.root
|
||||
packages = name.split(".")
|
||||
parent = sourcefolder
|
||||
for package in packages[:-1]:
|
||||
parent = parent.get_child(package)
|
||||
made_packages = parent.create_folder(packages[-1])
|
||||
made_packages.create_file("__init__.py")
|
||||
return made_packages
|
||||
|
||||
|
||||
class _Generate(object):
|
||||
def __init__(self, project, resource, offset, goal_resource=None):
|
||||
self.project = project
|
||||
self.resource = resource
|
||||
self.goal_resource = goal_resource
|
||||
self.info = self._generate_info(project, resource, offset)
|
||||
self.name = self.info.get_name()
|
||||
self._check_exceptional_conditions()
|
||||
|
||||
def _generate_info(self, project, resource, offset):
|
||||
return _GenerationInfo(project.pycore, resource, offset, self.goal_resource)
|
||||
|
||||
def _check_exceptional_conditions(self):
|
||||
if self.info.element_already_exists():
|
||||
raise exceptions.RefactoringError(
|
||||
"Element <%s> already exists." % self.name
|
||||
)
|
||||
if not self.info.primary_is_found():
|
||||
raise exceptions.RefactoringError(
|
||||
"Cannot determine the scope <%s> should be defined in." % self.name
|
||||
)
|
||||
|
||||
def get_changes(self):
|
||||
changes = change.ChangeSet(
|
||||
"Generate %s <%s>" % (self._get_element_kind(), self.name)
|
||||
)
|
||||
indents = self.info.get_scope_indents()
|
||||
blanks = self.info.get_blank_lines()
|
||||
base_definition = sourceutils.fix_indentation(self._get_element(), indents)
|
||||
definition = "\n" * blanks[0] + base_definition + "\n" * blanks[1]
|
||||
|
||||
resource = self.info.get_insertion_resource()
|
||||
start, end = self.info.get_insertion_offsets()
|
||||
|
||||
collector = codeanalyze.ChangeCollector(resource.read())
|
||||
collector.add_change(start, end, definition)
|
||||
changes.add_change(change.ChangeContents(resource, collector.get_changed()))
|
||||
if self.goal_resource:
|
||||
relative_import = _add_relative_import_to_module(
|
||||
self.project, self.resource, self.goal_resource, self.name
|
||||
)
|
||||
changes.add_change(relative_import)
|
||||
return changes
|
||||
|
||||
def get_location(self):
|
||||
return (self.info.get_insertion_resource(), self.info.get_insertion_lineno())
|
||||
|
||||
def _get_element_kind(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _get_element(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class GenerateFunction(_Generate):
|
||||
def _generate_info(self, project, resource, offset):
|
||||
return _FunctionGenerationInfo(project.pycore, resource, offset)
|
||||
|
||||
def _get_element(self):
|
||||
decorator = ""
|
||||
args = []
|
||||
if self.info.is_static_method():
|
||||
decorator = "@staticmethod\n"
|
||||
if (
|
||||
self.info.is_method()
|
||||
or self.info.is_constructor()
|
||||
or self.info.is_instance()
|
||||
):
|
||||
args.append("self")
|
||||
args.extend(self.info.get_passed_args())
|
||||
definition = "%sdef %s(%s):\n pass\n" % (
|
||||
decorator,
|
||||
self.name,
|
||||
", ".join(args),
|
||||
)
|
||||
return definition
|
||||
|
||||
def _get_element_kind(self):
|
||||
return "Function"
|
||||
|
||||
|
||||
class GenerateVariable(_Generate):
|
||||
def _get_element(self):
|
||||
return "%s = None\n" % self.name
|
||||
|
||||
def _get_element_kind(self):
|
||||
return "Variable"
|
||||
|
||||
|
||||
class GenerateClass(_Generate):
|
||||
def _get_element(self):
|
||||
return "class %s(object):\n pass\n" % self.name
|
||||
|
||||
def _get_element_kind(self):
|
||||
return "Class"
|
||||
|
||||
|
||||
class GenerateModule(_Generate):
|
||||
def get_changes(self):
|
||||
package = self.info.get_package()
|
||||
changes = change.ChangeSet("Generate Module <%s>" % self.name)
|
||||
new_resource = self.project.get_file("%s/%s.py" % (package.path, self.name))
|
||||
if new_resource.exists():
|
||||
raise exceptions.RefactoringError(
|
||||
"Module <%s> already exists" % new_resource.path
|
||||
)
|
||||
changes.add_change(change.CreateResource(new_resource))
|
||||
changes.add_change(
|
||||
_add_import_to_module(self.project, self.resource, new_resource)
|
||||
)
|
||||
return changes
|
||||
|
||||
def get_location(self):
|
||||
package = self.info.get_package()
|
||||
return (package.get_child("%s.py" % self.name), 1)
|
||||
|
||||
|
||||
class GeneratePackage(_Generate):
|
||||
def get_changes(self):
|
||||
package = self.info.get_package()
|
||||
changes = change.ChangeSet("Generate Package <%s>" % self.name)
|
||||
new_resource = self.project.get_folder("%s/%s" % (package.path, self.name))
|
||||
if new_resource.exists():
|
||||
raise exceptions.RefactoringError(
|
||||
"Package <%s> already exists" % new_resource.path
|
||||
)
|
||||
changes.add_change(change.CreateResource(new_resource))
|
||||
changes.add_change(
|
||||
_add_import_to_module(self.project, self.resource, new_resource)
|
||||
)
|
||||
child = self.project.get_folder(package.path + "/" + self.name)
|
||||
changes.add_change(change.CreateFile(child, "__init__.py"))
|
||||
return changes
|
||||
|
||||
def get_location(self):
|
||||
package = self.info.get_package()
|
||||
child = package.get_child(self.name)
|
||||
return (child.get_child("__init__.py"), 1)
|
||||
|
||||
|
||||
def _add_import_to_module(project, resource, imported):
|
||||
pymodule = project.get_pymodule(resource)
|
||||
import_tools = importutils.ImportTools(project)
|
||||
module_imports = import_tools.module_imports(pymodule)
|
||||
module_name = libutils.modname(imported)
|
||||
new_import = importutils.NormalImport(((module_name, None),))
|
||||
module_imports.add_import(new_import)
|
||||
return change.ChangeContents(resource, module_imports.get_changed_source())
|
||||
|
||||
|
||||
def _add_relative_import_to_module(project, resource, imported, name):
|
||||
pymodule = project.get_pymodule(resource)
|
||||
import_tools = importutils.ImportTools(project)
|
||||
module_imports = import_tools.module_imports(pymodule)
|
||||
new_import = import_tools.get_from_import(imported, name)
|
||||
module_imports.add_import(new_import)
|
||||
return change.ChangeContents(resource, module_imports.get_changed_source())
|
||||
|
||||
|
||||
class _GenerationInfo(object):
|
||||
def __init__(self, pycore, resource, offset, goal_resource=None):
|
||||
self.pycore = pycore
|
||||
self.resource = resource
|
||||
self.offset = offset
|
||||
self.goal_resource = goal_resource
|
||||
self.source_pymodule = self.pycore.project.get_pymodule(resource)
|
||||
finder = rope.base.evaluate.ScopeNameFinder(self.source_pymodule)
|
||||
self.primary, self.pyname = finder.get_primary_and_pyname_at(offset)
|
||||
self._init_fields()
|
||||
|
||||
def _init_fields(self):
|
||||
self.source_scope = self._get_source_scope()
|
||||
self.goal_scope = self._get_goal_scope()
|
||||
self.goal_pymodule = self._get_goal_module(self.goal_scope)
|
||||
|
||||
def _get_goal_scope(self):
|
||||
if self.primary is None:
|
||||
if self.goal_resource:
|
||||
return self.pycore.project.get_pymodule(self.goal_resource).get_scope()
|
||||
else:
|
||||
return self._get_source_scope()
|
||||
pyobject = self.primary.get_object()
|
||||
if isinstance(pyobject, pyobjects.PyDefinedObject):
|
||||
return pyobject.get_scope()
|
||||
elif isinstance(pyobject.get_type(), pyobjects.PyClass):
|
||||
return pyobject.get_type().get_scope()
|
||||
|
||||
def _get_goal_module(self, scope):
|
||||
if scope is None:
|
||||
return
|
||||
while scope.parent is not None:
|
||||
scope = scope.parent
|
||||
return scope.pyobject
|
||||
|
||||
def _get_source_scope(self):
|
||||
module_scope = self.source_pymodule.get_scope()
|
||||
lineno = self.source_pymodule.lines.get_line_number(self.offset)
|
||||
return module_scope.get_inner_scope_for_line(lineno)
|
||||
|
||||
def get_insertion_lineno(self):
|
||||
lines = self.goal_pymodule.lines
|
||||
if self.goal_scope == self.source_scope:
|
||||
line_finder = self.goal_pymodule.logical_lines
|
||||
lineno = lines.get_line_number(self.offset)
|
||||
lineno = line_finder.logical_line_in(lineno)[0]
|
||||
root = suites.ast_suite_tree(self.goal_scope.pyobject.get_ast())
|
||||
suite = root.find_suite(lineno)
|
||||
indents = sourceutils.get_indents(lines, lineno)
|
||||
while self.get_scope_indents() < indents:
|
||||
lineno = suite.get_start()
|
||||
indents = sourceutils.get_indents(lines, lineno)
|
||||
suite = suite.parent
|
||||
return lineno
|
||||
else:
|
||||
return min(self.goal_scope.get_end() + 1, lines.length())
|
||||
|
||||
def get_insertion_resource(self):
|
||||
return self.goal_pymodule.get_resource()
|
||||
|
||||
def get_insertion_offsets(self):
|
||||
if self.goal_scope.get_kind() == "Class":
|
||||
start, end = sourceutils.get_body_region(self.goal_scope.pyobject)
|
||||
if self.goal_pymodule.source_code[start:end].strip() == "pass":
|
||||
return start, end
|
||||
lines = self.goal_pymodule.lines
|
||||
start = lines.get_line_start(self.get_insertion_lineno())
|
||||
return (start, start)
|
||||
|
||||
def get_scope_indents(self):
|
||||
if self.goal_scope.get_kind() == "Module":
|
||||
return 0
|
||||
return (
|
||||
sourceutils.get_indents(
|
||||
self.goal_pymodule.lines, self.goal_scope.get_start()
|
||||
)
|
||||
+ 4
|
||||
)
|
||||
|
||||
def get_blank_lines(self):
|
||||
if self.goal_scope.get_kind() == "Module":
|
||||
base_blanks = 2
|
||||
if self.goal_pymodule.source_code.strip() == "":
|
||||
base_blanks = 0
|
||||
if self.goal_scope.get_kind() == "Class":
|
||||
base_blanks = 1
|
||||
if self.goal_scope.get_kind() == "Function":
|
||||
base_blanks = 0
|
||||
if self.goal_scope == self.source_scope:
|
||||
return (0, base_blanks)
|
||||
return (base_blanks, 0)
|
||||
|
||||
def get_package(self):
|
||||
primary = self.primary
|
||||
if self.primary is None:
|
||||
return self.pycore.project.get_source_folders()[0]
|
||||
if isinstance(primary.get_object(), pyobjects.PyPackage):
|
||||
return primary.get_object().get_resource()
|
||||
raise exceptions.RefactoringError(
|
||||
"A module/package can be only created in a package."
|
||||
)
|
||||
|
||||
def primary_is_found(self):
|
||||
return self.goal_scope is not None
|
||||
|
||||
def element_already_exists(self):
|
||||
if self.pyname is None or isinstance(self.pyname, pynames.UnboundName):
|
||||
return False
|
||||
return self.get_name() in self.goal_scope.get_defined_names()
|
||||
|
||||
def get_name(self):
|
||||
return worder.get_name_at(self.resource, self.offset)
|
||||
|
||||
|
||||
class _FunctionGenerationInfo(_GenerationInfo):
|
||||
def _get_goal_scope(self):
|
||||
if self.is_constructor():
|
||||
return self.pyname.get_object().get_scope()
|
||||
if self.is_instance():
|
||||
return self.pyname.get_object().get_type().get_scope()
|
||||
if self.primary is None:
|
||||
return self._get_source_scope()
|
||||
pyobject = self.primary.get_object()
|
||||
if isinstance(pyobject, pyobjects.PyDefinedObject):
|
||||
return pyobject.get_scope()
|
||||
elif isinstance(pyobject.get_type(), pyobjects.PyClass):
|
||||
return pyobject.get_type().get_scope()
|
||||
|
||||
def element_already_exists(self):
|
||||
if self.pyname is None or isinstance(self.pyname, pynames.UnboundName):
|
||||
return False
|
||||
return self.get_name() in self.goal_scope.get_defined_names()
|
||||
|
||||
def is_static_method(self):
|
||||
return self.primary is not None and isinstance(
|
||||
self.primary.get_object(), pyobjects.PyClass
|
||||
)
|
||||
|
||||
def is_method(self):
|
||||
return self.primary is not None and isinstance(
|
||||
self.primary.get_object().get_type(), pyobjects.PyClass
|
||||
)
|
||||
|
||||
def is_constructor(self):
|
||||
return self.pyname is not None and isinstance(
|
||||
self.pyname.get_object(), pyobjects.PyClass
|
||||
)
|
||||
|
||||
def is_instance(self):
|
||||
if self.pyname is None:
|
||||
return False
|
||||
pyobject = self.pyname.get_object()
|
||||
return isinstance(pyobject.get_type(), pyobjects.PyClass)
|
||||
|
||||
def get_name(self):
|
||||
if self.is_constructor():
|
||||
return "__init__"
|
||||
if self.is_instance():
|
||||
return "__call__"
|
||||
return worder.get_name_at(self.resource, self.offset)
|
||||
|
||||
def get_passed_args(self):
|
||||
result = []
|
||||
source = self.source_pymodule.source_code
|
||||
finder = worder.Worder(source)
|
||||
if finder.is_a_function_being_called(self.offset):
|
||||
start, end = finder.get_primary_range(self.offset)
|
||||
parens_start, parens_end = finder.get_word_parens_range(end - 1)
|
||||
call = source[start:parens_end]
|
||||
parser = functionutils._FunctionParser(call, False)
|
||||
args, keywords = parser.get_parameters()
|
||||
for arg in args:
|
||||
if self._is_id(arg):
|
||||
result.append(arg)
|
||||
else:
|
||||
result.append("arg%d" % len(result))
|
||||
for name, value in keywords:
|
||||
result.append(name)
|
||||
return result
|
||||
|
||||
def _is_id(self, arg):
|
||||
def id_or_underline(c):
|
||||
return c.isalpha() or c == "_"
|
||||
|
||||
for c in arg:
|
||||
if not id_or_underline(c) and not c.isdigit():
|
||||
return False
|
||||
return id_or_underline(arg[0])
|
||||
Loading…
Add table
Add a link
Reference in a new issue