Skip to content

Commit fb8cfdc

Browse files
authored
feat: allow keeping stuff when isolating data dir (#2515)
1 parent 47c1a5f commit fb8cfdc

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

src/ape/managers/config.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import os
2-
from collections.abc import Iterator
2+
import shutil
3+
from collections.abc import Iterable, Iterator
34
from contextlib import contextmanager
45
from functools import cached_property
56
from pathlib import Path
6-
from typing import TYPE_CHECKING, Any, Optional
7+
from typing import TYPE_CHECKING, Any, Optional, Union
78

89
from ape.api.config import ApeConfig
910
from ape.managers.base import BaseManager
@@ -113,20 +114,41 @@ def extract_config(cls, manifest: "PackageManifest", **overrides) -> ApeConfig:
113114
return ApeConfig.from_manifest(manifest, **overrides)
114115

115116
@contextmanager
116-
def isolate_data_folder(self) -> Iterator[Path]:
117+
def isolate_data_folder(
118+
self, keep: Optional[Union[Iterable[str], str]] = None
119+
) -> Iterator[Path]:
117120
"""
118121
Change Ape's DATA_FOLDER to point a temporary path,
119122
in a context, for testing purposes. Any data
120123
cached to disk will not persist.
124+
125+
Args:
126+
keep (Optional[Union[Iterable[str], str]]): Optionally, pass in
127+
a key of subdirectory names to include in the new isolated
128+
data folder. For example, pass ing ``"packages"`` to avoid
129+
having to re-download dependencies in an isolated environment.
130+
131+
Returns:
132+
Iterator[Path]: The temporary data folder.
121133
"""
122134
original_data_folder = self.DATA_FOLDER
123135
if in_tempdir(original_data_folder):
124136
# Already isolated.
125137
yield original_data_folder
126138

127139
else:
140+
keep = [keep] if isinstance(keep, str) else keep or []
128141
try:
129142
with create_tempdir() as temp_data_folder:
143+
# Copy in items from "keep".
144+
for item in keep:
145+
path_to_keep = original_data_folder / item
146+
if not path_to_keep.is_dir():
147+
continue
148+
149+
dest_path = temp_data_folder / item
150+
shutil.copytree(path_to_keep, dest_path)
151+
130152
self.DATA_FOLDER = temp_data_folder
131153
yield temp_data_folder
132154

tests/functional/test_config.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import re
3+
import shutil
34
from pathlib import Path
45
from typing import TYPE_CHECKING, Any, Callable, Optional, Union
56

@@ -689,3 +690,44 @@ def test_project_level_settings(project):
689690
assert project.config.my_string == "my_string"
690691
assert project.config.my_int == 123
691692
assert project.config.my_bool is True
693+
694+
695+
def test_isolate_data_folder(config):
696+
original_data_folder = config.DATA_FOLDER
697+
madeup_path = Path.home() / ".ape" / "__madeup__"
698+
config.DATA_FOLDER = madeup_path
699+
try:
700+
with config.isolate_data_folder():
701+
assert config.DATA_FOLDER != original_data_folder
702+
finally:
703+
config.DATA_FOLDER = original_data_folder
704+
705+
706+
def test_isolate_data_folder_already_isolated(config):
707+
data_folder = config.DATA_FOLDER
708+
with config.isolate_data_folder():
709+
# Already isolated, so there is no change.
710+
assert config.DATA_FOLDER == data_folder
711+
712+
713+
def test_isolate_data_folder_keep(config):
714+
original_data_folder = config.DATA_FOLDER
715+
madeup_path = Path.home() / ".ape" / "__core_aoe_test__"
716+
madeup_path.mkdir(parents=True, exist_ok=True)
717+
sub_dir = madeup_path / "subdir"
718+
file = sub_dir / "file.txt"
719+
sub_dir.mkdir(parents=True, exist_ok=True)
720+
file.write_text("search for 'test_isolate_data_folder_keep' ape's tests.")
721+
722+
config.DATA_FOLDER = madeup_path
723+
try:
724+
with config.isolate_data_folder(keep="subdir"):
725+
assert config.DATA_FOLDER != original_data_folder
726+
727+
expected_file = config.DATA_FOLDER / "subdir" / "file.txt"
728+
assert expected_file.is_file()
729+
730+
finally:
731+
config.DATA_FOLDER = original_data_folder
732+
if madeup_path.is_dir():
733+
shutil.rmtree(str(madeup_path), ignore_errors=True)

0 commit comments

Comments
 (0)