Skip to content

Commit

Permalink
feat: ctx-mgmt for changing into proj
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Jan 14, 2025
1 parent a1eed98 commit 59fae27
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 14 deletions.
33 changes: 19 additions & 14 deletions src/ape/managers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
get_relative_path,
in_tempdir,
path_match,
within_directory,
)


Expand Down Expand Up @@ -2583,28 +2584,22 @@ def clean(self):
self.sources._path_cache = None
self._clear_cached_config()

def chdir(self, path: Path):
def chdir(self, path: Optional[Path] = None):
"""
Change the local project to the new path.
Args:
path (Path): The path of the new project.
"""
if self.path == path:
return # Already there!

path = path or self.path
os.chdir(path)
if self.path == path:
return # Already setup.

# Clear cached properties.
for prop in (
"path",
"_deduced_contracts_folder",
"project_api",
"contracts",
"interfaces_folder",
"sources",
):
self.__dict__.pop(prop, None)
# New path: clear cached properties.
for attr in list(self.__dict__.keys()):
if isinstance(getattr(type(self), attr, None), cached_property):
del self.__dict__[attr]

# Re-initialize
self._session_source_change_check = set()
Expand All @@ -2613,6 +2608,16 @@ def chdir(self, path: Path):
self.manifest_path = self._base_path / ".build" / "__local__.json"
self._manifest = self.load_manifest()

@contextmanager
def within_project_path(self):
"""
A context-manager for changing the current working directory to the
project's ``.path``. Then, switch back to whatever the current
directory was before calling this method.
"""
with within_directory(self.path):
yield

def reload_config(self):
"""
Reload the local ape-config.yaml file.
Expand Down
18 changes: 18 additions & 0 deletions src/ape/utils/os.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,3 +436,21 @@ def get_data(self, key: str) -> dict:
def delete_data(self, key: str):
file = self.get_file(key)
file.unlink(missing_ok=True)


@contextmanager
def within_directory(directory: Path):
"""
A context-manager for changing the cwd to the given path.
Args:
directory (Path): The directory to change.
"""
here = Path.cwd()
if directory != here:
os.chdir(directory)
try:
yield
finally:
if Path.cwd() != here:
os.chdir(here)
12 changes: 12 additions & 0 deletions tests/functional/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -1064,3 +1064,15 @@ def test_chdir(project):
# Undo.
project.chdir(original_path)
assert project.path == original_path


def test_within_project_path():
start_cwd = Path.cwd()
with create_tempdir() as new_path:
project = Project(new_path)
assert Path.cwd() != new_path

with project.within_project_path():
assert Path.cwd() == project.path

assert Path.cwd() == start_cwd

0 comments on commit 59fae27

Please sign in to comment.