Skip to content

Commit 8c39bfa

Browse files
authored
Merge pull request #13 from commit-0/fix_errors
Fix errors
2 parents f3b3dfb + 8fbf041 commit 8c39bfa

File tree

9 files changed

+116
-61
lines changed

9 files changed

+116
-61
lines changed

commit0/__main__.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,47 @@
11
import commit0.harness.run_pytest_ids
22
import commit0.harness.build
33
import commit0.harness.setup
4+
import copy
45
import sys
6+
import hydra
7+
from hydra.core.config_store import ConfigStore
8+
from commit0.configs.config_class import Commit0Config
59

610

711
def main() -> None:
812
command = sys.argv[1]
13+
# type check config values
14+
cs = ConfigStore.instance()
15+
cs.store(name="base", node=Commit0Config)
16+
# have hydra to ignore all command-line arguments
17+
sys_argv = copy.deepcopy(sys.argv)
18+
sys.argv = [sys.argv[0]]
19+
hydra.initialize(version_base=None, config_path="configs")
20+
config = hydra.compose(config_name="base")
21+
# after hydra gets all configs, put command-line arguments back
22+
sys.argv = sys_argv
923

1024
if command == "clone":
11-
commit0.harness.setup.main()
25+
commit0.harness.setup.main(
26+
config.dataset_name, config.dataset_split, config.base_dir
27+
)
1228
elif command == "build":
13-
commit0.harness.build.main()
29+
commit0.harness.build.main(
30+
config.dataset_name, config.dataset_split, config.num_workers
31+
)
1432
elif command == "test":
15-
commit0.harness.run_pytest_ids.main()
33+
repo = sys.argv[2]
34+
test_ids = sys.argv[3]
35+
commit0.harness.run_pytest_ids.main(
36+
config.dataset_name,
37+
config.dataset_split,
38+
config.base_dir,
39+
repo,
40+
config.branch,
41+
test_ids,
42+
config.backend,
43+
config.timeout,
44+
)
1645

1746

1847
if __name__ == "__main__":

commit0/configs/base.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
defaults:
2+
- _self_
3+
4+
# shared in all steps
5+
dataset_name: wentingzhao/commit0_docstring
6+
dataset_split: test
7+
8+
# clone related
9+
base_dir: repos/
10+
11+
# build related
12+
build: all
13+
num_workers: 8
14+
15+
# test related
16+
backend: local
17+
branch: ai
18+
timeout: 1_800

commit0/configs/config_class.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from dataclasses import dataclass
2+
3+
4+
@dataclass
5+
class Commit0Config:
6+
# shared in all steps
7+
dataset_name: str
8+
dataset_split: str
9+
10+
# clone related
11+
base_dir: str
12+
13+
# build related
14+
# which repo to build, all or one repo
15+
build: str
16+
num_workers: int
17+
18+
# test related
19+
backend: str
20+
# which branch to work on
21+
branch: str
22+
# timeout for running pytest
23+
timeout: int

commit0/harness/build.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,25 @@
44
from datasets import load_dataset
55
from typing import Iterator
66

7-
from omegaconf import DictConfig
87
from commit0.harness.docker_build import build_repo_images
98
from commit0.harness.spec import make_spec
109
from commit0.harness.constants import RepoInstance
11-
import hydra
1210

1311
logging.basicConfig(
1412
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
1513
)
1614
logger = logging.getLogger(__name__)
1715

1816

19-
@hydra.main(version_base=None, config_path="configs", config_name="base")
20-
def main(config: DictConfig) -> None:
21-
dataset: Iterator[RepoInstance] = load_dataset(hf_name, split="test") # type: ignore
17+
def main(dataset_name: str, dataset_split: str, num_workers: int) -> None:
18+
dataset: Iterator[RepoInstance] = load_dataset(dataset_name, split=dataset_split) # type: ignore
2219
specs = []
2320
for example in dataset:
2421
spec = make_spec(example)
2522
specs.append(spec)
2623

2724
client = docker.from_env()
28-
build_repo_images(client, specs)
25+
build_repo_images(client, specs, num_workers)
2926
logger.info("Done building docker images")
3027

3128

commit0/harness/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
from enum import Enum
22
from pathlib import Path
3-
from typing import TypedDict
3+
from typing import Dict, TypedDict
44

55

66
class RepoInstance(TypedDict):
77
repo: str
88
base_commit: str
99
reference_commit: str
1010
setup: dict
11-
test: str
11+
test: Dict[str, str]
1212

1313

1414
# Constants - Evaluation Log Directories

commit0/harness/docker_build.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,24 +119,14 @@ def build_image(
119119
)
120120

121121
# Log the build process continuously
122-
buildlog = ""
123122
for chunk in response:
124123
if "stream" in chunk:
125124
# Remove ANSI escape sequences from the log
126125
chunk_stream = ansi_escape.sub("", chunk["stream"])
127126
logger.info(chunk_stream.strip())
128-
buildlog += chunk_stream
129-
elif "errorDetail" in chunk:
130-
# Decode error message, raise BuildError
131-
logger.error(
132-
f"Error: {ansi_escape.sub('', chunk['errorDetail']['message'])}"
133-
)
134-
raise docker.errors.BuildError(
135-
chunk["errorDetail"]["message"], buildlog
136-
)
137127
logger.info("Image built successfully!")
138-
except docker.errors.BuildError as e:
139-
logger.error(f"docker.errors.BuildError during {image_name}: {e}")
128+
except docker.errors.APIError as e:
129+
logger.error(f"docker.errors.APIError during {image_name}: {e}")
140130
raise BuildImageError(image_name, str(e), logger) from e
141131
except Exception as e:
142132
logger.error(f"Error building image {image_name}: {e}")

commit0/harness/docker_utils.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
from pathlib import Path
1212
from io import BytesIO
1313
from typing import Optional, List, Union
14-
import docker.errors
1514

15+
import docker.errors
1616
from docker.models.containers import Container
1717

1818
HEREDOC_DELIMITER = "EOF_1399519320" # different from dataset HEREDOC_DELIMITERs!
@@ -330,7 +330,6 @@ def log_error(x: str) -> None:
330330
def log_info(x: str) -> None:
331331
print(x)
332332

333-
raise_error = True
334333
elif logger == "quiet":
335334
# if logger is "quiet", don't print anything
336335
def log_info(x: str) -> None:
@@ -386,34 +385,31 @@ def exec_run_with_timeout(
386385
# Local variables to store the result of executing the command
387386
exec_result = ""
388387
exec_id = None
389-
exception = None
390388
timed_out = False
391389

392390
# Wrapper function to run the command
393391
def run_command() -> None:
394-
nonlocal exec_result, exec_id, exception
392+
nonlocal exec_result, exec_id
395393
try:
396-
assert container.client is not None, "Client did not load"
397-
exec_id = container.client.api.exec_create(container.id, cmd)["Id"]
398-
exec_stream = container.client.api.exec_start(exec_id, stream=True)
394+
exec_id = container.client.api.exec_create(container=container.id, cmd=cmd)[ # pyright: ignore
395+
"Id"
396+
]
397+
exec_stream = container.client.api.exec_start(exec_id=exec_id, stream=True) # pyright: ignore
399398
for chunk in exec_stream:
400399
exec_result += chunk.decode("utf-8", errors="replace")
401-
except Exception as e:
402-
exception = e
400+
except docker.errors.APIError as e:
401+
raise Exception(f"Container {container.id} cannot execute {cmd}.\n{str(e)}")
403402

404403
# Start the command in a separate thread
405404
thread = threading.Thread(target=run_command)
406405
start_time = time.time()
407406
thread.start()
408407
thread.join(timeout)
409408

410-
if exception:
411-
raise exception
412-
413409
# If the thread is still alive, the command timed out
414410
if thread.is_alive():
415411
if exec_id is not None:
416-
exec_pid = container.client.api.exec_inspect(exec_id)["Pid"]
412+
exec_pid = container.client.api.exec_inspect(exec_id=exec_id)["Pid"] # pyright: ignore
417413
container.exec_run(f"kill -TERM {exec_pid}", detach=True)
418414
timed_out = True
419415
end_time = time.time()

commit0/harness/run_pytest_ids.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
from pathlib import Path
77
import logging
88

9-
from omegaconf import DictConfig, OmegaConf
10-
import hydra
11-
12-
from commit0.harness.constants import RUN_PYTEST_LOG_DIR
9+
from typing import Iterator
10+
from commit0.harness.constants import RUN_PYTEST_LOG_DIR, RepoInstance
1311
from commit0.harness.docker_build import (
1412
close_logger,
1513
setup_logger,
@@ -196,39 +194,46 @@ def run_modal(
196194
)
197195

198196

199-
@hydra.main(version_base=None, config_path="configs", config_name="base")
200-
def main(config: DictConfig) -> None:
201-
OmegaConf.to_yaml(config)
202-
dataset = load_dataset(config.dataset_name, split="test")
197+
def main(
198+
dataset_name: str,
199+
dataset_split: str,
200+
base_dir: str,
201+
repo: str,
202+
branch: str,
203+
test_ids: str,
204+
backend: str,
205+
timeout: int,
206+
) -> None:
207+
dataset: Iterator[RepoInstance] = load_dataset(dataset_name, split=dataset_split) # type: ignore
203208
spec = None
204209
for example in dataset:
205-
if example["repo"].endswith(config.repo):
210+
if example["repo"].endswith(repo):
206211
spec = make_spec(example)
207212
break
208213
assert spec is not None, "No spec available"
209214

210-
hashed_test_ids = get_hash_string(config.test_ids)
215+
hashed_test_ids = get_hash_string(test_ids)
211216
# set up logging
212-
log_dir = RUN_PYTEST_LOG_DIR / config.repo / hashed_test_ids
217+
log_dir = RUN_PYTEST_LOG_DIR / repo / hashed_test_ids
213218
log_dir.mkdir(parents=True, exist_ok=True)
214219
log_file = log_dir / "run_pytest.log"
215-
logger = setup_logger(config.repo, log_file)
220+
logger = setup_logger(repo, log_file)
216221

217222
# make eval file
218223
eval_script = spec.eval_script.format(
219-
local_repo=f"{config.base_dir}/{config.repo}",
220-
branch_name=config.branch,
221-
test_ids=config.test_ids,
222-
ip=get_ip(config.backend),
224+
local_repo=f"{base_dir}/{repo}",
225+
branch_name=branch,
226+
test_ids=test_ids,
227+
ip=get_ip(backend),
223228
user=get_user(),
224229
)
225230
eval_file = Path(log_dir / "eval.sh")
226231
eval_file.write_text(eval_script)
227232

228-
if ExecutionBackend(config.backend) == ExecutionBackend.LOCAL:
229-
run_docker(spec, logger, eval_file, config.timeout, log_dir)
230-
elif ExecutionBackend(config.backend) == ExecutionBackend.MODAL:
231-
run_modal(spec, logger, eval_file, config.timeout, log_dir)
233+
if ExecutionBackend(backend) == ExecutionBackend.LOCAL:
234+
run_docker(spec, logger, eval_file, timeout, log_dir)
235+
elif ExecutionBackend(backend) == ExecutionBackend.MODAL:
236+
run_modal(spec, logger, eval_file, timeout, log_dir)
232237

233238

234239
__all__ = []

commit0/harness/setup.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
import os
33

44
import docker
5-
import hydra
65
from datasets import load_dataset
7-
from omegaconf import DictConfig
86

97
from typing import Iterator
108
from commit0.harness.utils import clone_repo
@@ -19,9 +17,8 @@
1917
logger = logging.getLogger(__name__)
2018

2119

22-
@hydra.main(version_base=None, config_path="configs", config_name="base")
23-
def main(config: DictConfig) -> None:
24-
dataset: Iterator[RepoInstance] = load_dataset(hf_name, split="test") # type: ignore
20+
def main(dataset_name: str, dataset_split: str, base_dir: str) -> None:
21+
dataset: Iterator[RepoInstance] = load_dataset(dataset_name, split=dataset_split) # type: ignore
2522
out = dict()
2623
specs = []
2724
for example in dataset:

0 commit comments

Comments
 (0)