diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fa900e16..0fbad4fe2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - #733 skip directories with perm error when building autoimport index (@MrBago) - #722, #723 Remove site-packages from packages search tree (@tkrabel) +- #738 Implement os.PathLike on Resource (@lieryan) # Release 1.11.0 diff --git a/rope/base/resources.py b/rope/base/resources.py index eaf194857..b284ba9f1 100644 --- a/rope/base/resources.py +++ b/rope/base/resources.py @@ -34,7 +34,7 @@ from rope.base import change, exceptions, fscommands -class Resource: +class Resource(os.PathLike): """Represents files and folders in a project""" def __init__(self, project, path): @@ -49,6 +49,10 @@ def __repr__(self): hex(id(self)), ) + def __fspath__(self) -> str: + """Return the file system path of this resource""" + return self.project._get_resource_path(self.path) + def move(self, new_location): """Move resource to `new_location`""" self._perform_change( @@ -60,14 +64,17 @@ def remove(self): """Remove resource from the project""" self._perform_change(change.RemoveResource(self), "Removing <%s>" % self.path) + def is_dir(self): + """Alias for `is_folder()`""" + def is_folder(self): - """Return true if the resource is a folder""" + """Return True if the resource is a Folder""" def create(self): """Create this resource""" def exists(self): - return os.path.exists(self.real_path) + return os.path.exists(self) @property def parent(self): @@ -75,7 +82,7 @@ def parent(self): return self.project.get_folder(parent) @property - def path(self): + def path(self) -> str: """Return the path of this resource relative to the project root The path is the list of parent directories separated by '/' followed @@ -84,19 +91,18 @@ def path(self): return self._path @property - def name(self): + def name(self) -> str: """Return the name of this resource""" return self.path.split("/")[-1] @property - def real_path(self): - """Return the file system path of this resource""" - return self.project._get_resource_path(self.path) + def real_path(self) -> str: + return os.fspath(self) @property - def pathlib(self): + def pathlib(self) -> Path: """Return the file as a pathlib path.""" - return Path(self.real_path) + return Path(self) def __eq__(self, obj): return self.__class__ == obj.__class__ and self.path == obj.path @@ -135,7 +141,7 @@ def read_bytes(self): DeprecationWarning, stacklevel=2, ) - with open(self.real_path, "rb") as handle: + with open(self, "rb") as handle: return handle.read() return self.project.fscommands.read(self.real_path) @@ -165,7 +171,7 @@ def is_folder(self): def get_children(self): """Return the children of this folder""" try: - children = os.listdir(self.real_path) + children = os.listdir(self) except OSError: return [] result = [] diff --git a/rope/contrib/autoimport/sqlite.py b/rope/contrib/autoimport/sqlite.py index 1755f2f2b..563cebd63 100644 --- a/rope/contrib/autoimport/sqlite.py +++ b/rope/contrib/autoimport/sqlite.py @@ -113,7 +113,7 @@ def __init__( autoimport = AutoImport(..., memory=True) """ self.project = project - project_package = get_package_tuple(Path(project.root.real_path), project) + project_package = get_package_tuple(project.root.pathlib, project) assert project_package is not None assert project_package.path is not None self.project_package = project_package @@ -175,9 +175,7 @@ def calculate_project_hash(data: str) -> str: f"file:rope-{project_hash}:?mode=memory&cache=shared", uri=True ) else: - return sqlite3.connect( - str(Path(project.ropefolder.real_path) / "autoimport.db") - ) + return sqlite3.connect(project.ropefolder.pathlib / "autoimport.db") @property def connection(self): @@ -627,7 +625,7 @@ def _resource_to_module( ) -> ModuleFile: assert self.project_package.path underlined = underlined if underlined else self.underlined - resource_path: Path = Path(resource.real_path) + resource_path: Path = resource.pathlib # The project doesn't need its name added to the path, # since the standard python file layout accounts for that # so we set add_package_name to False diff --git a/ropetest/projecttest.py b/ropetest/projecttest.py index 2efa25183..151384518 100644 --- a/ropetest/projecttest.py +++ b/ropetest/projecttest.py @@ -9,6 +9,7 @@ from rope.base.libutils import path_to_resource from rope.base.project import NoProject, Project, _realpath from rope.base.resourceobserver import FilteredResourceObserver +from rope.base.resources import File, Folder from ropetest import testutils @@ -610,6 +611,18 @@ def test_multi_source_folders2(self): self.assertEqual(2, len(source_folders)) self.assertTrue(self.project.root in source_folders and src in source_folders) + def test_folder_is_pathlike(self): + resource = self.project.root.create_folder("src") + self.assertIsInstance(resource, Folder) + + self.assertIsInstance(os.fspath(resource), str) + + def test_file_is_pathlike(self): + resource = self.project.root.create_file("mod.py") + self.assertIsInstance(resource, File) + + self.assertIsInstance(os.fspath(resource), str) + class ResourceObserverTest(unittest.TestCase): def setUp(self):