Skip to content

Commit 5c3990e

Browse files
author
Atlas
committed
fix: extract test files from git diff format in workspace export
- Fixed _extract_test_files to parse git diff format properly - Extracts lines starting with '+' (added content) from diffs - Handles '+++ b/path' to get file paths - Supports '# Test file:' format from TestGenerator - Tests are now correctly extracted to tests/ directory
1 parent 464636e commit 5c3990e

File tree

55 files changed

+6032
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+6032
-4
lines changed

src/swe_forge/export/workspace.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,71 @@ def export_tasks_to_workspace(
182182

183183

184184
def _extract_test_files(test_patch: str, tests_dir: Path) -> None:
185-
"""Extract test files from diff format."""
186-
pattern = r"#\s*(.+\.py)\n(.+?)(?=#\s*.+\.py\n|$)"
187-
matches = re.findall(pattern, test_patch, re.DOTALL)
185+
"""Extract test files from test_patch.
188186
189-
for file_path, content in matches:
187+
Handles multiple formats:
188+
1. Git diff format (diff --git ... +lines)
189+
2. "# Test file: path" format (from TestGenerator)
190+
3. Legacy "# file.py" format
191+
"""
192+
tests_dir.mkdir(parents=True, exist_ok=True)
193+
194+
# Format 1: Git diff format
195+
if "diff --git" in test_patch:
196+
diffs = test_patch.split("diff --git")
197+
198+
for diff in diffs[1:]:
199+
plus_match = re.search(r"\+\+\+ b/(.+)", diff)
200+
if not plus_match:
201+
continue
202+
file_path = plus_match.group(1).strip()
203+
204+
content_lines = []
205+
in_hunk = False
206+
207+
for line in diff.split("\n"):
208+
if line.startswith("---") or line.startswith("+++"):
209+
continue
210+
if line.startswith("index") or line.startswith("new file"):
211+
continue
212+
if line.startswith("@@"):
213+
in_hunk = True
214+
continue
215+
if not in_hunk:
216+
continue
217+
if line.startswith("+"):
218+
content_lines.append(line[1:])
219+
220+
if content_lines:
221+
while content_lines and not content_lines[-1].strip():
222+
content_lines.pop()
223+
224+
test_file = tests_dir / Path(file_path).name
225+
with open(test_file, "w", encoding="utf-8") as f:
226+
f.write("\n".join(content_lines))
227+
if content_lines:
228+
f.write("\n")
229+
return
230+
231+
# Format 2: "# Test file: path"
232+
pattern2 = r"#\s*Test file:\s*(.+)\n(.+?)(?=#\s*Test file:|$)"
233+
matches2 = re.findall(pattern2, test_patch, re.DOTALL)
234+
235+
if matches2:
236+
for file_path, content in matches2:
237+
file_path = file_path.strip()
238+
if not file_path:
239+
continue
240+
test_file = tests_dir / Path(file_path).name
241+
with open(test_file, "w", encoding="utf-8") as f:
242+
f.write(content.strip() + "\n")
243+
return
244+
245+
# Format 3: Legacy "# file.py" format
246+
pattern3 = r"#\s*(.+\.py)\n(.+?)(?=#\s*.+\.py\n|$)"
247+
matches3 = re.findall(pattern3, test_patch, re.DOTALL)
248+
249+
for file_path, content in matches3:
190250
file_path = file_path.strip()
191251
if not file_path:
192252
continue
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
diff --git a/src/app.py b/src/app.py
2+
index cdec0c3d..58418d41 100644
3+
--- a/src/app.py
4+
+++ b/src/app.py
5+
@@ -16,6 +16,7 @@
6+
import os
7+
import sys
8+
import threading
9+
+import urllib.request
10+
from datetime import datetime
11+
12+
# === Custom Modules ===
13+
@@ -39,6 +40,33 @@
14+
CONFIG = load_config()
15+
16+
# === Helper Functions ===
17+
+def ensure_tars_onnx():
18+
+ """
19+
+ Checks that src/tts/TARS.onnx exists. If not, downloads it from HuggingFace.
20+
+ """
21+
+ onnx_path = os.path.join(BASE_DIR, "src", "tts", "TARS.onnx")
22+
+ onnx_url = "https://huggingface.co/olivierdion007/TARS-AI/resolve/main/TARS.onnx"
23+
+
24+
+ if os.path.isfile(onnx_path):
25+
+ queue_message(f"LOAD: TARS.onnx found at {onnx_path}")
26+
+ return
27+
+
28+
+ queue_message(f"LOAD: TARS.onnx not found. Downloading from HuggingFace...")
29+
+ os.makedirs(os.path.dirname(onnx_path), exist_ok=True)
30+
+
31+
+ try:
32+
+ def _progress(block_num, block_size, total_size):
33+
+ if total_size > 0:
34+
+ pct = min(block_num * block_size / total_size * 100, 100)
35+
+ print(f"\r Downloading TARS.onnx: {pct:.1f}%", end="", flush=True)
36+
+
37+
+ urllib.request.urlretrieve(onnx_url, onnx_path, reporthook=_progress)
38+
+ print() # newline after progress
39+
+ queue_message(f"LOAD: TARS.onnx downloaded successfully to {onnx_path}")
40+
+ except Exception as e:
41+
+ queue_message(f"ERROR: Failed to download TARS.onnx: {e}")
42+
+ raise
43+
+
44+
def init_app():
45+
"""
46+
Performs initial setup for the application
47+
@@ -52,6 +80,9 @@ def init_app():
48+
if CONFIG['TTS']['ttsoption'] == 'xttsv2':
49+
update_tts_settings(CONFIG['TTS']['ttsurl'])
50+
51+
+ # Ensure TARS voice model is present
52+
+ ensure_tars_onnx()
53+
+
54+
def start_discord_in_thread():
55+
"""
56+
Start the Discord bot in a separate thread to prevent blocking.
57+
@@ -117,4 +148,4 @@ def start_discord_in_thread():
58+
finally:
59+
stt_manager.stop()
60+
bt_controller_thread.join()
61+
- queue_message(f"INFO: All threads and executor stopped gracefully.")
62+
\ No newline at end of file
63+
+ queue_message(f"INFO: All threads and executor stopped gracefully.")
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
task_id: TARS-AI-Community-TARS-AI-353
2+
repo:
3+
url: https://github.com/TARS-AI-Community/TARS-AI.git
4+
base_commit: b00108e2a5ac2845d4132532fbcd0c5c4de7adba
5+
merge_commit: 0da7e163c6f27e0f32ee59e3d282c9bdde15f7b1
6+
language: python
7+
difficulty_score: 1
8+
prompt: Update app.py
9+
environment:
10+
image: ubuntu:24.04
11+
language_version: '3.12'
12+
install:
13+
commands: []
14+
tests:
15+
fail_to_pass: []
16+
pass_to_pass: []

0 commit comments

Comments
 (0)