init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
501
.venv/lib/python3.8/site-packages/rope/base/project.py
Normal file
501
.venv/lib/python3.8/site-packages/rope/base/project.py
Normal file
|
|
@ -0,0 +1,501 @@
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import rope.base.fscommands
|
||||
import rope.base.resourceobserver as resourceobserver
|
||||
import rope.base.utils.pycompat as pycompat
|
||||
from rope.base import exceptions, taskhandle, prefs, history, pycore, utils
|
||||
from rope.base.exceptions import ModuleNotFoundError
|
||||
from rope.base.resources import File, Folder, _ResourceMatcher
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
|
||||
|
||||
class _Project(object):
|
||||
def __init__(self, fscommands):
|
||||
self.observers = []
|
||||
self.fscommands = fscommands
|
||||
self.prefs = prefs.Prefs()
|
||||
self.data_files = _DataFiles(self)
|
||||
self._custom_source_folders = []
|
||||
|
||||
def get_resource(self, resource_name):
|
||||
"""Get a resource in a project.
|
||||
|
||||
`resource_name` is the path of a resource in a project. It is
|
||||
the path of a resource relative to project root. Project root
|
||||
folder address is an empty string. If the resource does not
|
||||
exist a `exceptions.ResourceNotFound` exception would be
|
||||
raised. Use `get_file()` and `get_folder()` when you need to
|
||||
get nonexistent `Resource`.
|
||||
|
||||
"""
|
||||
path = self._get_resource_path(resource_name)
|
||||
if not os.path.exists(path):
|
||||
raise exceptions.ResourceNotFoundError(
|
||||
"Resource <%s> does not exist" % resource_name
|
||||
)
|
||||
elif os.path.isfile(path):
|
||||
return File(self, resource_name)
|
||||
elif os.path.isdir(path):
|
||||
return Folder(self, resource_name)
|
||||
else:
|
||||
raise exceptions.ResourceNotFoundError("Unknown resource " + resource_name)
|
||||
|
||||
def get_module(self, name, folder=None):
|
||||
"""Returns a `PyObject` if the module was found."""
|
||||
# check if this is a builtin module
|
||||
pymod = self.pycore.builtin_module(name)
|
||||
if pymod is not None:
|
||||
return pymod
|
||||
module = self.find_module(name, folder)
|
||||
if module is None:
|
||||
raise ModuleNotFoundError("Module %s not found" % name)
|
||||
return self.pycore.resource_to_pyobject(module)
|
||||
|
||||
def get_python_path_folders(self):
|
||||
result = []
|
||||
for src in self.prefs.get("python_path", []) + sys.path:
|
||||
try:
|
||||
src_folder = get_no_project().get_resource(src)
|
||||
result.append(src_folder)
|
||||
except exceptions.ResourceNotFoundError:
|
||||
pass
|
||||
return result
|
||||
|
||||
# INFO: It was decided not to cache source folders, since:
|
||||
# - Does not take much time when the root folder contains
|
||||
# packages, that is most of the time
|
||||
# - We need a separate resource observer; `self.observer`
|
||||
# does not get notified about module and folder creations
|
||||
def get_source_folders(self):
|
||||
"""Returns project source folders"""
|
||||
if self.root is None:
|
||||
return []
|
||||
result = list(self._custom_source_folders)
|
||||
result.extend(self.pycore._find_source_folders(self.root))
|
||||
return result
|
||||
|
||||
def validate(self, folder):
|
||||
"""Validate files and folders contained in this folder
|
||||
|
||||
It validates all of the files and folders contained in this
|
||||
folder if some observers are interested in them.
|
||||
|
||||
"""
|
||||
for observer in list(self.observers):
|
||||
observer.validate(folder)
|
||||
|
||||
def add_observer(self, observer):
|
||||
"""Register a `ResourceObserver`
|
||||
|
||||
See `FilteredResourceObserver`.
|
||||
"""
|
||||
self.observers.append(observer)
|
||||
|
||||
def remove_observer(self, observer):
|
||||
"""Remove a registered `ResourceObserver`"""
|
||||
if observer in self.observers:
|
||||
self.observers.remove(observer)
|
||||
|
||||
def do(self, changes, task_handle=taskhandle.NullTaskHandle()):
|
||||
"""Apply the changes in a `ChangeSet`
|
||||
|
||||
Most of the time you call this function for committing the
|
||||
changes for a refactoring.
|
||||
"""
|
||||
self.history.do(changes, task_handle=task_handle)
|
||||
|
||||
def get_pymodule(self, resource, force_errors=False):
|
||||
return self.pycore.resource_to_pyobject(resource, force_errors)
|
||||
|
||||
def get_pycore(self):
|
||||
return self.pycore
|
||||
|
||||
def get_file(self, path):
|
||||
"""Get the file with `path` (it may not exist)"""
|
||||
return File(self, path)
|
||||
|
||||
def get_folder(self, path):
|
||||
"""Get the folder with `path` (it may not exist)"""
|
||||
return Folder(self, path)
|
||||
|
||||
def get_prefs(self):
|
||||
return self.prefs
|
||||
|
||||
def get_relative_module(self, name, folder, level):
|
||||
module = self.find_relative_module(name, folder, level)
|
||||
if module is None:
|
||||
raise ModuleNotFoundError("Module %s not found" % name)
|
||||
return self.pycore.resource_to_pyobject(module)
|
||||
|
||||
def find_module(self, modname, folder=None):
|
||||
"""Returns a resource corresponding to the given module
|
||||
|
||||
returns None if it can not be found
|
||||
"""
|
||||
for src in self.get_source_folders():
|
||||
module = _find_module_in_folder(src, modname)
|
||||
if module is not None:
|
||||
return module
|
||||
for src in self.get_python_path_folders():
|
||||
module = _find_module_in_folder(src, modname)
|
||||
if module is not None:
|
||||
return module
|
||||
if folder is not None:
|
||||
module = _find_module_in_folder(folder, modname)
|
||||
if module is not None:
|
||||
return module
|
||||
return None
|
||||
|
||||
def find_relative_module(self, modname, folder, level):
|
||||
for i in range(level - 1):
|
||||
folder = folder.parent
|
||||
if modname == "":
|
||||
return folder
|
||||
else:
|
||||
return _find_module_in_folder(folder, modname)
|
||||
|
||||
def is_ignored(self, resource):
|
||||
return False
|
||||
|
||||
def _get_resource_path(self, name):
|
||||
pass
|
||||
|
||||
@property
|
||||
@utils.saveit
|
||||
def history(self):
|
||||
return history.History(self)
|
||||
|
||||
@property
|
||||
@utils.saveit
|
||||
def pycore(self):
|
||||
return pycore.PyCore(self)
|
||||
|
||||
def close(self):
|
||||
warnings.warn("Cannot close a NoProject", DeprecationWarning, stacklevel=2)
|
||||
|
||||
ropefolder = None
|
||||
|
||||
|
||||
class Project(_Project):
|
||||
"""A Project containing files and folders"""
|
||||
|
||||
def __init__(
|
||||
self, projectroot, fscommands=None, ropefolder=".ropeproject", **prefs
|
||||
):
|
||||
"""A rope project
|
||||
|
||||
:parameters:
|
||||
- `projectroot`: The address of the root folder of the project
|
||||
- `fscommands`: Implements the file system operations used
|
||||
by rope; have a look at `rope.base.fscommands`
|
||||
- `ropefolder`: The name of the folder in which rope stores
|
||||
project configurations and data. Pass `None` for not using
|
||||
such a folder at all.
|
||||
- `prefs`: Specify project preferences. These values
|
||||
overwrite config file preferences.
|
||||
|
||||
"""
|
||||
if projectroot != "/":
|
||||
projectroot = _realpath(projectroot).rstrip("/\\")
|
||||
self._address = projectroot
|
||||
self._ropefolder_name = ropefolder
|
||||
if not os.path.exists(self._address):
|
||||
os.mkdir(self._address)
|
||||
elif not os.path.isdir(self._address):
|
||||
raise exceptions.RopeError("Project root exists and" " is not a directory")
|
||||
if fscommands is None:
|
||||
fscommands = rope.base.fscommands.create_fscommands(self._address)
|
||||
super(Project, self).__init__(fscommands)
|
||||
self.ignored = _ResourceMatcher()
|
||||
self.file_list = _FileListCacher(self)
|
||||
self.prefs.add_callback("ignored_resources", self.ignored.set_patterns)
|
||||
if ropefolder is not None:
|
||||
self.prefs["ignored_resources"] = [ropefolder]
|
||||
self._init_prefs(prefs)
|
||||
self._init_source_folders()
|
||||
|
||||
@utils.deprecated("Delete once deprecated functions are gone")
|
||||
def _init_source_folders(self):
|
||||
for path in self.prefs.get("source_folders", []):
|
||||
folder = self.get_resource(path)
|
||||
self._custom_source_folders.append(folder)
|
||||
|
||||
def get_files(self):
|
||||
return self.file_list.get_files()
|
||||
|
||||
def get_python_files(self):
|
||||
"""Returns all python files available in the project"""
|
||||
return [
|
||||
resource
|
||||
for resource in self.get_files()
|
||||
if self.pycore.is_python_file(resource)
|
||||
]
|
||||
|
||||
def _get_resource_path(self, name):
|
||||
return os.path.join(self._address, *name.split("/"))
|
||||
|
||||
def _init_ropefolder(self):
|
||||
if self.ropefolder is not None:
|
||||
if not self.ropefolder.exists():
|
||||
self._create_recursively(self.ropefolder)
|
||||
if not self.ropefolder.has_child("config.py"):
|
||||
config = self.ropefolder.create_file("config.py")
|
||||
config.write(self._default_config())
|
||||
|
||||
def _create_recursively(self, folder):
|
||||
if folder.parent != self.root and not folder.parent.exists():
|
||||
self._create_recursively(folder.parent)
|
||||
folder.create()
|
||||
|
||||
def _init_prefs(self, prefs):
|
||||
run_globals = {}
|
||||
if self.ropefolder is not None:
|
||||
config = self.get_file(self.ropefolder.path + "/config.py")
|
||||
run_globals.update(
|
||||
{
|
||||
"__name__": "__main__",
|
||||
"__builtins__": __builtins__,
|
||||
"__file__": config.real_path,
|
||||
}
|
||||
)
|
||||
if config.exists():
|
||||
config = self.ropefolder.get_child("config.py")
|
||||
pycompat.execfile(config.real_path, run_globals)
|
||||
else:
|
||||
exec(self._default_config(), run_globals)
|
||||
if "set_prefs" in run_globals:
|
||||
run_globals["set_prefs"](self.prefs)
|
||||
for key, value in prefs.items():
|
||||
self.prefs[key] = value
|
||||
self._init_other_parts()
|
||||
self._init_ropefolder()
|
||||
if "project_opened" in run_globals:
|
||||
run_globals["project_opened"](self)
|
||||
|
||||
def _default_config(self):
|
||||
import rope.base.default_config
|
||||
import inspect
|
||||
|
||||
return inspect.getsource(rope.base.default_config)
|
||||
|
||||
def _init_other_parts(self):
|
||||
# Forcing the creation of `self.pycore` to register observers
|
||||
self.pycore
|
||||
|
||||
def is_ignored(self, resource):
|
||||
return self.ignored.does_match(resource)
|
||||
|
||||
def sync(self):
|
||||
"""Closes project open resources"""
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
"""Closes project open resources"""
|
||||
self.data_files.write()
|
||||
|
||||
def set(self, key, value):
|
||||
"""Set the `key` preference to `value`"""
|
||||
self.prefs.set(key, value)
|
||||
|
||||
@property
|
||||
def ropefolder(self):
|
||||
if self._ropefolder_name is not None:
|
||||
return self.get_folder(self._ropefolder_name)
|
||||
|
||||
def validate(self, folder=None):
|
||||
if folder is None:
|
||||
folder = self.root
|
||||
super(Project, self).validate(folder)
|
||||
|
||||
root = property(lambda self: self.get_resource(""))
|
||||
address = property(lambda self: self._address)
|
||||
|
||||
|
||||
class NoProject(_Project):
|
||||
"""A null object for holding out of project files.
|
||||
|
||||
This class is singleton use `get_no_project` global function
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
fscommands = rope.base.fscommands.FileSystemCommands()
|
||||
super(NoProject, self).__init__(fscommands)
|
||||
|
||||
def _get_resource_path(self, name):
|
||||
real_name = name.replace("/", os.path.sep)
|
||||
return _realpath(real_name)
|
||||
|
||||
def get_resource(self, name):
|
||||
universal_name = _realpath(name).replace(os.path.sep, "/")
|
||||
return super(NoProject, self).get_resource(universal_name)
|
||||
|
||||
def get_files(self):
|
||||
return []
|
||||
|
||||
def get_python_files(self):
|
||||
return []
|
||||
|
||||
_no_project = None
|
||||
|
||||
|
||||
def get_no_project():
|
||||
if NoProject._no_project is None:
|
||||
NoProject._no_project = NoProject()
|
||||
return NoProject._no_project
|
||||
|
||||
|
||||
class _FileListCacher(object):
|
||||
def __init__(self, project):
|
||||
self.project = project
|
||||
self.files = None
|
||||
rawobserver = resourceobserver.ResourceObserver(
|
||||
self._changed, self._invalid, self._invalid, self._invalid, self._invalid
|
||||
)
|
||||
self.project.add_observer(rawobserver)
|
||||
|
||||
def get_files(self):
|
||||
if self.files is None:
|
||||
self.files = set()
|
||||
self._add_files(self.project.root)
|
||||
return self.files
|
||||
|
||||
def _add_files(self, folder):
|
||||
for child in folder.get_children():
|
||||
if child.is_folder():
|
||||
self._add_files(child)
|
||||
elif not self.project.is_ignored(child):
|
||||
self.files.add(child)
|
||||
|
||||
def _changed(self, resource):
|
||||
if resource.is_folder():
|
||||
self.files = None
|
||||
|
||||
def _invalid(self, resource, new_resource=None):
|
||||
self.files = None
|
||||
|
||||
|
||||
class _DataFiles(object):
|
||||
def __init__(self, project):
|
||||
self.project = project
|
||||
self.hooks = []
|
||||
|
||||
def read_data(self, name, compress=False, import_=False):
|
||||
if self.project.ropefolder is None:
|
||||
return None
|
||||
compress = compress and self._can_compress()
|
||||
opener = self._get_opener(compress)
|
||||
file = self._get_file(name, compress)
|
||||
if not compress and import_:
|
||||
self._import_old_files(name)
|
||||
if file.exists():
|
||||
input = opener(file.real_path, "rb")
|
||||
try:
|
||||
result = []
|
||||
try:
|
||||
while True:
|
||||
result.append(pickle.load(input))
|
||||
except EOFError:
|
||||
pass
|
||||
if len(result) == 1:
|
||||
return result[0]
|
||||
if len(result) > 1:
|
||||
return result
|
||||
finally:
|
||||
input.close()
|
||||
|
||||
def write_data(self, name, data, compress=False):
|
||||
if self.project.ropefolder is not None:
|
||||
compress = compress and self._can_compress()
|
||||
file = self._get_file(name, compress)
|
||||
opener = self._get_opener(compress)
|
||||
output = opener(file.real_path, "wb")
|
||||
try:
|
||||
pickle.dump(data, output, 2)
|
||||
finally:
|
||||
output.close()
|
||||
|
||||
def add_write_hook(self, hook):
|
||||
self.hooks.append(hook)
|
||||
|
||||
def write(self):
|
||||
for hook in self.hooks:
|
||||
hook()
|
||||
|
||||
def _can_compress(self):
|
||||
try:
|
||||
import gzip # noqa
|
||||
|
||||
return True
|
||||
except ImportError:
|
||||
return False
|
||||
|
||||
def _import_old_files(self, name):
|
||||
old = self._get_file(name + ".pickle", False)
|
||||
new = self._get_file(name, False)
|
||||
if old.exists() and not new.exists():
|
||||
shutil.move(old.real_path, new.real_path)
|
||||
|
||||
def _get_opener(self, compress):
|
||||
if compress:
|
||||
try:
|
||||
import gzip
|
||||
|
||||
return gzip.open
|
||||
except ImportError:
|
||||
pass
|
||||
return open
|
||||
|
||||
def _get_file(self, name, compress):
|
||||
path = self.project.ropefolder.path + "/" + name
|
||||
if compress:
|
||||
path += ".gz"
|
||||
return self.project.get_file(path)
|
||||
|
||||
|
||||
def _realpath(path):
|
||||
"""Return the real path of `path`
|
||||
|
||||
Is equivalent to ``realpath(abspath(expanduser(path)))``.
|
||||
|
||||
Of the particular notice is the hack dealing with the unfortunate
|
||||
situation of running native-Windows python (os.name == 'nt') inside
|
||||
of Cygwin (abspath starts with '/'), which apparently normal
|
||||
os.path.realpath completely messes up.
|
||||
|
||||
"""
|
||||
# there is a bug in cygwin for os.path.abspath() for abs paths
|
||||
if sys.platform == "cygwin":
|
||||
if path[1:3] == ":\\":
|
||||
return path
|
||||
elif path[1:3] == ":/":
|
||||
path = "/cygdrive/" + path[0] + path[2:]
|
||||
return os.path.abspath(os.path.expanduser(path))
|
||||
return os.path.realpath(os.path.abspath(os.path.expanduser(path)))
|
||||
|
||||
|
||||
def _find_module_in_folder(folder, modname):
|
||||
module = folder
|
||||
packages = modname.split(".")
|
||||
for pkg in packages[:-1]:
|
||||
if module.is_folder() and module.has_child(pkg):
|
||||
module = module.get_child(pkg)
|
||||
else:
|
||||
return None
|
||||
if module.is_folder():
|
||||
if (
|
||||
module.has_child(packages[-1])
|
||||
and module.get_child(packages[-1]).is_folder()
|
||||
):
|
||||
return module.get_child(packages[-1])
|
||||
elif (
|
||||
module.has_child(packages[-1] + ".py")
|
||||
and not module.get_child(packages[-1] + ".py").is_folder()
|
||||
):
|
||||
return module.get_child(packages[-1] + ".py")
|
||||
Loading…
Add table
Add a link
Reference in a new issue