Spaces:
Sleeping
Sleeping
Create safe_executor.py
Browse files- core/safe_executor.py +131 -0
core/safe_executor.py
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# algoforge_prime/core/safe_executor.py
|
2 |
+
# WARNING: THIS IS A SIMULATED SAFE EXECUTOR. DO NOT USE FOR REAL UNTRUSTED CODE.
|
3 |
+
# A real implementation would require robust sandboxing (Docker, nsjail, Firecracker, WASM, etc.)
|
4 |
+
# This simulation is purely for demonstrating the application flow.
|
5 |
+
|
6 |
+
import time
|
7 |
+
import random
|
8 |
+
import traceback
|
9 |
+
|
10 |
+
class ExecutionResult:
|
11 |
+
def __init__(self, success: bool, output: str = None, error: str = None, execution_time: float = 0.0, passed_tests: int = 0, total_tests: int = 0):
|
12 |
+
self.success = success # True if code ran without crashing (not necessarily if tests passed)
|
13 |
+
self.output = output # Stdout from the execution
|
14 |
+
self.error = error # Stderr or exception message
|
15 |
+
self.execution_time = execution_time
|
16 |
+
self.passed_tests = passed_tests # Number of 'assert' statements that passed
|
17 |
+
self.total_tests = total_tests # Total 'assert' statements found and attempted
|
18 |
+
|
19 |
+
def __str__(self):
|
20 |
+
if self.success:
|
21 |
+
test_summary = f"Tests: {self.passed_tests}/{self.total_tests} passed. " if self.total_tests > 0 else ""
|
22 |
+
return f"Execution OK. {test_summary}Time: {self.execution_time:.4f}s. Output: {str(self.output)[:200]}"
|
23 |
+
else:
|
24 |
+
return f"Execution FAILED. Error: {str(self.error)[:300]}. Time: {self.execution_time:.4f}s"
|
25 |
+
|
26 |
+
def execute_python_code_with_tests(code_string: str, tests_string: str, timeout_seconds: int = 5) -> ExecutionResult:
|
27 |
+
"""
|
28 |
+
SIMULATES sandboxed execution of Python code against a set of assert-based tests.
|
29 |
+
In a real system, this function would be a complex interface to a secure sandbox.
|
30 |
+
"""
|
31 |
+
print(f"SIMULATOR: Attempting to 'execute' code with tests. Timeout: {timeout_seconds}s")
|
32 |
+
start_time = time.time()
|
33 |
+
|
34 |
+
if not code_string.strip():
|
35 |
+
return ExecutionResult(success=False, error="No code provided to execute.", execution_time=time.time() - start_time)
|
36 |
+
|
37 |
+
# Basic simulation:
|
38 |
+
# 1. Check for obvious syntax issues (very naive)
|
39 |
+
if "def " not in code_string and "class " not in code_string and not any(op in code_string for op in ["=", "+", "-", "*", "/"]):
|
40 |
+
# If it doesn't look like defining something or doing operations, maybe it's just a malformed snippet
|
41 |
+
if len(code_string) < 50 and "print" not in code_string : # very arbitrary
|
42 |
+
return ExecutionResult(success=False, error="Simulated: Code appears incomplete or malformed for execution.", execution_time=time.time()-start_time)
|
43 |
+
|
44 |
+
|
45 |
+
# 2. Simulate test parsing and execution
|
46 |
+
test_lines = [line.strip() for line in tests_string.splitlines() if line.strip().startswith("assert")]
|
47 |
+
total_tests = len(test_lines)
|
48 |
+
passed_tests = 0
|
49 |
+
simulated_stdout = []
|
50 |
+
simulated_stderr = None
|
51 |
+
|
52 |
+
if total_tests == 0 and tests_string.strip(): # If tests were provided but no asserts found
|
53 |
+
simulated_stderr = "Simulated: Test string provided, but no 'assert' statements found."
|
54 |
+
# We can still "run" the code itself without asserts
|
55 |
+
|
56 |
+
# Simulate code "running"
|
57 |
+
try:
|
58 |
+
if "loop forever" in code_string.lower() or "while True:" in code_string and "break" not in code_string: # Timeout simulation
|
59 |
+
time.sleep(timeout_seconds + 0.1) # Exceed timeout
|
60 |
+
raise TimeoutError("Simulated: Code execution timed out.")
|
61 |
+
|
62 |
+
# Simulate print statements
|
63 |
+
if "print('hello world')" in code_string:
|
64 |
+
simulated_stdout.append("hello world")
|
65 |
+
if "print(1+1)" in code_string:
|
66 |
+
simulated_stdout.append("2")
|
67 |
+
|
68 |
+
# Simulate errors
|
69 |
+
if "1/0" in code_string or "zerodivisionerror" in code_string:
|
70 |
+
raise ZeroDivisionError("Simulated: division by zero")
|
71 |
+
if "undefined_variable" in code_string:
|
72 |
+
raise NameError("Simulated: name 'undefined_variable' is not defined")
|
73 |
+
|
74 |
+
# Simulate test passing/failing (very naively)
|
75 |
+
if total_tests > 0:
|
76 |
+
for i, test_line in enumerate(test_lines):
|
77 |
+
# This is extremely basic and not real evaluation.
|
78 |
+
# A real system would execute each assert in the context of the provided code.
|
79 |
+
if "==" in test_line:
|
80 |
+
if "True" in test_line or "120" in test_line or "correct" in test_line.lower(): # Naive pass conditions
|
81 |
+
if random.random() > 0.1: # 90% chance of passing "good" tests
|
82 |
+
passed_tests += 1
|
83 |
+
simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): PASSED")
|
84 |
+
else:
|
85 |
+
simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): FAILED (Random Sim)")
|
86 |
+
if not simulated_stderr: simulated_stderr = f"Simulated: Assertion failed on test {i+1}"
|
87 |
+
elif "False" in test_line or "wrong" in test_line.lower(): # Naive fail conditions
|
88 |
+
if random.random() > 0.1: # 90% chance of failing "bad" tests
|
89 |
+
simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): FAILED (Expected by Sim)")
|
90 |
+
if not simulated_stderr: simulated_stderr = f"Simulated: Assertion failed on test {i+1} (Expected by Sim)"
|
91 |
+
else: # 10% chance of unexpectedly passing
|
92 |
+
passed_tests +=1
|
93 |
+
simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): PASSED (Unexpected by Sim)")
|
94 |
+
else: # Other asserts
|
95 |
+
if random.random() > 0.5: # 50/50
|
96 |
+
passed_tests += 1
|
97 |
+
simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): PASSED (Random Sim)")
|
98 |
+
else:
|
99 |
+
simulated_stdout.append(f"Simulated Test {i+1} ({test_line[:30]}...): FAILED (Random Sim)")
|
100 |
+
if not simulated_stderr: simulated_stderr = f"Simulated: Assertion failed on test {i+1} (Random Sim)"
|
101 |
+
else: # Non-equality asserts, just pass some randomly
|
102 |
+
if random.random() > 0.3: passed_tests +=1
|
103 |
+
|
104 |
+
# If no explicit error, but not all tests passed
|
105 |
+
if total_tests > 0 and passed_tests < total_tests and not simulated_stderr:
|
106 |
+
simulated_stderr = f"Simulated: {total_tests - passed_tests} out of {total_tests} assertions failed."
|
107 |
+
|
108 |
+
execution_time = time.time() - start_time
|
109 |
+
if execution_time > timeout_seconds: # Check after simulated work
|
110 |
+
raise TimeoutError("Simulated: Code execution exceeded timeout.")
|
111 |
+
|
112 |
+
return ExecutionResult(
|
113 |
+
success=True if not simulated_stderr or (total_tests > 0 and passed_tests == total_tests) else False, # Success if no errors or all tests pass
|
114 |
+
output="\n".join(simulated_stdout) if simulated_stdout else None,
|
115 |
+
error=simulated_stderr,
|
116 |
+
execution_time=execution_time,
|
117 |
+
passed_tests=passed_tests,
|
118 |
+
total_tests=total_tests
|
119 |
+
)
|
120 |
+
|
121 |
+
except Exception as e:
|
122 |
+
execution_time = time.time() - start_time
|
123 |
+
tb_str = traceback.format_exc()
|
124 |
+
print(f"SIMULATOR EXCEPTION: {e}\n{tb_str}")
|
125 |
+
return ExecutionResult(
|
126 |
+
success=False,
|
127 |
+
error=f"Simulated Exception: {type(e).__name__} - {str(e)}",
|
128 |
+
execution_time=execution_time,
|
129 |
+
passed_tests=passed_tests, # Could be some if error happened mid-tests
|
130 |
+
total_tests=total_tests
|
131 |
+
)
|