|
@contextmanager |
|
def isolated_filesystem(copy_cwd: bool = False): |
|
"""Context manager to create an isolated file system. |
|
And to navigate to it and then to clean it up. |
|
""" |
|
original_path = Path.cwd() |
|
with tempfile.TemporaryDirectory(dir=tempfile.gettempdir()) as temp_dir: |
|
temp_dir_path = Path(temp_dir).resolve() |
|
os.chdir(temp_dir_path) |
|
if copy_cwd: |
|
# we copy the content of the original directory into the temporary one |
|
for file_name in os.listdir(original_path): |
|
if file_name == "__pycache__": |
|
continue |
|
file_path = Path(original_path, file_name) |
|
if file_path.is_file(): |
|
shutil.copy(file_path, temp_dir_path) |
|
elif file_path.is_dir(): |
|
shutil.copytree(file_path, Path(temp_dir, file_name)) |
|
yield str(Path(temp_dir_path)) |
|
os.chdir(original_path) |
The design of this context manager is problematic in more ways than one:
- copying is slow
sys.path not modified
- cached imports; cannot import newly scaffolded modules for testing
- changing directory, but not restoring properly (no
finally clause)
- and many more!
And if all of that is not enough, let me show you something I have witnessed before and again now. When i use this fixture (or rather a derivative) and place a breakpoint in the test to debug (here after first assert result)
|
def test_scaffold_protocol(cli_runner, dummy_agent_tim): |
|
"""Test scaffold protocol.""" |
|
|
|
path = Path.cwd() / ".." / "tests" / "data" / "dummy_protocol.yaml" |
|
command = ["adev", "scaffold", "protocol", str(path)] |
|
runner = cli_runner(command) |
|
result = runner.execute() |
|
assert result, runner.output |
|
|
|
assert runner.return_code == 0, result.output |
|
assert "New protocol scaffolded" in runner.output |
|
|
|
protocol = read_protocol(str(path)) |
|
original_content = path.read_text(encoding=DEFAULT_ENCODING) |
|
readme_path = dummy_agent_tim / "protocols" / protocol.metadata["name"] / "README.md" |
|
assert original_content in readme_path.read_text(encoding=DEFAULT_ENCODING) |
and check where the hell i am since i seem unable to access local variables, I get
(Pdb) __file__
'/home/zarathustra/.cache/pypoetry/virtualenvs/autonomy-dev-IM6WInhx-py3.11/lib/python3.11/site-packages/_pytest/logging.py'
amazing!
Turns out test was just updated to pass again. So I go in, place breakpoint and check where i end up now!
(Pdb) __file__
'/home/zarathustra/Projects/auto_dev/auto_dev/cli_executor.py'
that is amazing! I wonder where we'll end up next time we make some changes...
Alright enough sarcasm. It is time to replace the isolated_filesystem with something better. I have gone over various designs for this and found all of them to be faulty to a degree, I will share some implementations i tried below
auto_dev/auto_dev/utils.py
Lines 191 to 211 in 18db783
The design of this context manager is problematic in more ways than one:
sys.pathnot modifiedfinallyclause)And if all of that is not enough, let me show you something I have witnessed before and again now. When i use this fixture (or rather a derivative) and place a
breakpointin the test to debug (here after firstassert result)auto_dev/tests/test_scaffold.py
Lines 92 to 107 in 18db783
and check where the hell i am since i seem unable to access local variables, I get
amazing!
Turns out test was just updated to pass again. So I go in, place breakpoint and check where i end up now!
that is amazing! I wonder where we'll end up next time we make some changes...
Alright enough sarcasm. It is time to replace the
isolated_filesystemwith something better. I have gone over various designs for this and found all of them to be faulty to a degree, I will share some implementations i tried below