Skip to content

Commit 7df58b9

Browse files
matheperMarcCote
authored andcommitted
Pull changes from #107 and #212
1 parent d4581e6 commit 7df58b9

File tree

7 files changed

+82
-46
lines changed

7 files changed

+82
-46
lines changed

debug_gym/gym/envs/aider.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,37 @@
55
from debug_gym.constants import DEBUG_GYM_CACHE_DIR
66
from debug_gym.gym.entities import EvalOutput
77
from debug_gym.gym.envs.env import RepoEnv
8+
from debug_gym.gym.terminal import DockerTerminal, Terminal
89

910

1011
class AiderBenchmarkEnv(RepoEnv):
1112
REPO_URL = "https://github.com/exercism/python"
1213
REPO_PATH = DEBUG_GYM_CACHE_DIR / "exercism"
1314

15+
def __init__(
16+
self,
17+
entrypoint: str = "python -m pytest -s .",
18+
terminal: Terminal | None = None,
19+
**kwargs,
20+
):
21+
terminal = terminal or DockerTerminal(
22+
base_image="python:3.12-slim",
23+
setup_commands=[
24+
"apt update",
25+
"apt install -y git",
26+
"pip install pytest",
27+
],
28+
logger=kwargs.get("logger"),
29+
)
30+
if not isinstance(terminal, DockerTerminal):
31+
raise ValueError("AiderBenchmarkEnv only supports DockerTerminal.")
32+
33+
super().__init__(entrypoint=entrypoint, terminal=terminal, **kwargs)
34+
1435
@property
1536
def instructions(self) -> str:
1637
return self.current_sample["instructions"]
1738

18-
def __init__(self, entrypoint: str = "python -m pytest -s .", **kwargs):
19-
super().__init__(entrypoint=entrypoint, **kwargs)
20-
2139
def calculate_max_score(self, eval_output: EvalOutput) -> int:
2240
return utils.extract_max_score_from_pytest_output(eval_output.output)
2341

@@ -30,11 +48,26 @@ def eval(self, **kwargs) -> EvalOutput:
3048
self.last_eval = EvalOutput(success, output)
3149
return self.last_eval
3250

51+
def setup_terminal(self):
52+
self.logger.info(f"Configuring docker container: {self.terminal.container}")
53+
54+
self.terminal.run("git init")
55+
self.terminal.run("git config user.name 'debug-gym'")
56+
self.terminal.run("git config user.email '<>'")
57+
58+
self.terminal.run("git add *.py")
59+
self.terminal.run("git commit -am 'Init'")
60+
61+
self.terminal.run("git add .debugignore")
62+
self.terminal.run("git add .debugreadonly")
63+
self.terminal.run("git commit -am 'Add debug-gym ignore and read-only files'")
64+
3365
def reset(self, *, options: dict = None):
3466
options = options or {}
3567
self.current_sample = self.dataset[options["task_name"]]
3668
directory = self.current_sample["base_directory"]
3769
self.setup_workspace(directory, entrypoint=self.entrypoint)
70+
self.setup_terminal()
3871
infos = super().reset(options=options)
3972
return infos
4073

debug_gym/gym/envs/env.py

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import atexit
2-
import os
32
import shutil
4-
import subprocess
53
import tempfile
64
from dataclasses import dataclass
7-
from glob import glob
85
from pathlib import Path
96

107
import numpy as np
@@ -300,20 +297,6 @@ def display_files(self):
300297
msg += self.directory_tree()
301298
return msg
302299

303-
def restore(self, *filepaths):
304-
filepaths = filepaths or glob(
305-
f"{self.path}/**",
306-
root_dir=self.path,
307-
recursive=True,
308-
)
309-
relative_filepaths = [os.path.relpath(f, self.path) for f in filepaths]
310-
for filepath in relative_filepaths:
311-
if os.path.isdir(self.path / filepath):
312-
os.makedirs(self.working_dir / filepath, exist_ok=True)
313-
continue
314-
315-
shutil.copy2(self.path / filepath, self.working_dir / filepath)
316-
317300
def reset(self, *, options: dict = None):
318301
"""Resets the environment and returns eval as the initial observation."""
319302
self.logger.info("Resetting environment")
@@ -507,10 +490,12 @@ def current_breakpoints(self):
507490

508491
@property
509492
def patch(self):
510-
command = ["git", "diff", "--no-index", self.path, self.working_dir]
511-
result = subprocess.run(command, text=True, capture_output=True)
512-
patch = result.stdout.replace(str(self.working_dir), str(self.path))
513-
return patch
493+
success, output = self.terminal.run("git diff")
494+
if not success:
495+
self.logger.error("Failed to get git diff. {output}")
496+
return None
497+
498+
return output
514499

515500
def apply_gold_patch(self):
516501
raise NotImplementedError(

debug_gym/gym/envs/mini_nightmare.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import debug_gym.gym.utils as utils
55
from debug_gym.gym.entities import EvalOutput
66
from debug_gym.gym.envs.env import RepoEnv
7+
from debug_gym.gym.terminal import DockerTerminal, Terminal
78

89

910
class MiniNightmareEnv(RepoEnv):
@@ -21,13 +22,30 @@ class MiniNightmareEnv(RepoEnv):
2122
"tomorrow_date",
2223
]
2324

25+
def __init__(
26+
self,
27+
entrypoint: str = "python -m pytest -s test.py",
28+
terminal: Terminal | None = None,
29+
**kwargs,
30+
):
31+
terminal = terminal or DockerTerminal(
32+
base_image="python:3.12-slim",
33+
setup_commands=[
34+
"apt update",
35+
"apt install -y git",
36+
"pip install pytest pandas",
37+
],
38+
logger=kwargs.get("logger"),
39+
)
40+
if not isinstance(terminal, DockerTerminal):
41+
raise ValueError("MiniNightmareEnv only supports DockerTerminal.")
42+
43+
super().__init__(entrypoint=entrypoint, terminal=terminal, **kwargs)
44+
2445
@property
2546
def instructions(self) -> str:
2647
return self.current_sample["instructions"]
2748

28-
def __init__(self, entrypoint: str = "python -m pytest -s test.py", **kwargs):
29-
super().__init__(entrypoint=entrypoint, **kwargs)
30-
3149
def calculate_max_score(self, eval_output: EvalOutput) -> int:
3250
return utils.extract_max_score_from_pytest_output(eval_output.output)
3351

@@ -40,11 +58,26 @@ def eval(self, **kwargs) -> EvalOutput:
4058
self.last_eval = EvalOutput(success, output)
4159
return self.last_eval
4260

61+
def setup_terminal(self):
62+
self.logger.info(f"Configuring docker container: {self.terminal.container}")
63+
64+
self.terminal.run("git init")
65+
self.terminal.run("git config user.name 'debug-gym'")
66+
self.terminal.run("git config user.email '<>'")
67+
68+
self.terminal.run("git add *.py")
69+
self.terminal.run("git commit -am 'Init'")
70+
71+
self.terminal.run("git add .debugignore")
72+
self.terminal.run("git add .debugreadonly")
73+
self.terminal.run("git commit -am 'Add debug-gym ignore and read-only files'")
74+
4375
def reset(self, *, options: dict = None):
4476
options = options or {}
4577
self.current_sample = self.dataset[options["task_name"]]
4678
directory = self.current_sample["base_directory"]
4779
self.setup_workspace(directory, entrypoint=self.entrypoint)
80+
self.setup_terminal()
4881
infos = super().reset(options=options)
4982
return infos
5083

debug_gym/gym/terminal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,15 +457,15 @@ def setup_container(self) -> docker.models.containers.Container:
457457
container.rename(container_name)
458458
container.reload()
459459
self._run_setup_commands(container)
460-
self.logger.debug(f"Container {container_name} started successfully.")
460+
self.logger.debug(f"{container} ({container_name}) started successfully.")
461461
atexit.register(self.clean_up)
462462
return container
463463

464464
def _run_setup_commands(self, container):
465465
"""Run setup commands if any. If commands fail, stop the container."""
466466
if self.setup_commands:
467467
setup_commands = " && ".join(self.setup_commands)
468-
self.logger.debug(f"Running setup commands: {setup_commands}")
468+
self.logger.debug(f"{container} Running setup commands: {setup_commands}")
469469
status, output = container.exec_run(
470470
["/bin/bash", "-c", setup_commands],
471471
user="root", # Run as root to allow installations

scripts/config_aider.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ base:
2020
# session_commands define commands that are always executed before starting a shell session or running a single command in the terminal.
2121
# session_commands:["conda activate aider"],
2222
# setup_commands define commands that are executed only once when the terminal is created. This is only supported for Docker terminal.
23-
setup_commands: ["pip install pytest"],
23+
setup_commands: ["apt update", "apt install -y git", "pip install pytest"],
2424
}
2525

2626
# LLM configs

scripts/config_mini_nightmare.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ base:
2020
# session_commands define commands that are always executed before starting a shell session or running a single command in the terminal.
2121
# session_commands:["conda activate aider"],
2222
# setup_commands define commands that are executed only once when the terminal is created. This is only supported for Docker terminal.
23-
setup_commands: ["pip install pytest pandas"],
23+
setup_commands: ["apt update", "apt install -y git", "pip install pytest pandas"],
2424
}
2525

2626
# LLM configs

tests/gym/envs/test_env.py

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -204,21 +204,6 @@ def env(tmp_path):
204204
return env
205205

206206

207-
def test_restore(env):
208-
# Change the content of a file
209-
file1 = env.working_dir / "file1.txt"
210-
with open(file1, "w") as f:
211-
f.write("Hello, World!")
212-
213-
def hash_file(file):
214-
with open(file, "rb") as f:
215-
return hash(f.read())
216-
217-
assert hash_file(env.path / "file1.txt") != hash_file(file1)
218-
env.restore()
219-
assert hash_file(env.path / "file1.txt") == hash_file(file1)
220-
221-
222207
def test_display_files(env):
223208
result = env.display_files()
224209
assert result == (

0 commit comments

Comments
 (0)