Skip to content

Commit 9fffec1

Browse files
committed
Avoid timeouts on project_eval (ht christoph)
1 parent f1c3d7a commit 9fffec1

File tree

3 files changed

+16
-8
lines changed

3 files changed

+16
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Tidewave
22

3-
> Tidewave Web for Django and Flask is currently in alpha testing!
3+
> Tidewave Web for Django, FastAPI, and Flask is currently in alpha testing!
44
55
Tidewave is the coding agent for full-stack web app development, deeply integrated with Python web frameworks, from the database to the UI. [See our website](https://tidewave.ai) for more information.
66

src/tidewave/tools/project_eval.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import io
33
import json as json_module
44
import multiprocessing
5+
import queue as q
56
from typing import Any, Optional
67

78

@@ -33,15 +34,15 @@ def project_eval(
3334
# us to terminate it once a timeout is reached. If we were to run
3435
# the code in another thread instead, we would have no clean way
3536
# of stopping it (other than signals, but those only work on Unix).
36-
37-
timeout = timeout / 1000 # Convert milliseconds to seconds.
37+
timeout = timeout / 1000 # Convert milliseconds to seconds
3838

3939
queue = multiprocessing.Queue()
4040
process = multiprocessing.Process(target=execute_code, args=(code, arguments, queue))
4141
process.start()
42-
process.join(timeout)
4342

44-
if process.is_alive():
43+
try:
44+
output = queue.get(timeout=timeout)
45+
except q.Empty:
4546
process.terminate()
4647
process.join()
4748
result = f"Code execution timed out after {timeout} seconds"
@@ -50,7 +51,7 @@ def project_eval(
5051
stderr = ""
5152
error_message = result
5253
else:
53-
output = queue.get() if not queue.empty() else {}
54+
process.join()
5455
result = output.get("result", "")
5556
success = output.get("success", False)
5657
stdout = output.get("stdout", "")
@@ -76,7 +77,7 @@ def project_eval(
7677
f"STDERR:\n{stderr}",
7778
f"Result:\n{str(result)}",
7879
]
79-
return "".join(output)
80+
return "\n".join(output)
8081

8182

8283
# Note: Defined at the module level so it can be used in the multiprocessing context.

tests/test_project_eval.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,16 @@ def test_non_json_output(self):
8181
"""Test non-JSON output"""
8282
code = "print('hello world')\nresult = 42"
8383
result = project_eval(code, json=False)
84-
expected_output = "STDOUT:\nhello world\nSTDERR:\nResult:\n42"
84+
expected_output = "STDOUT:\nhello world\n\nSTDERR:\n\nResult:\n42"
8585
self.assertEqual(result, expected_output)
8686

87+
def test_large_output(self):
88+
"""Test large output"""
89+
code = "'a' * 1_000_000"
90+
result = project_eval(code, json=True)
91+
output = self._collect_output(result)
92+
self.assertEqual(len(output["result"]), 1_000_000)
93+
8794
def test_multiline_code_execution(self):
8895
"""Test multi-line Python code"""
8996
code = "a = 10\nb = 20\nresult = a + b"

0 commit comments

Comments
 (0)