Spaces:
Running
Running
File size: 3,937 Bytes
2ce1061 8485798 2ce1061 2785b89 2ce1061 2785b89 8485798 2785b89 2ce1061 8485798 2ce1061 8485798 2ce1061 8485798 2ce1061 2785b89 8485798 2785b89 ceba2ab 2ce1061 ceba2ab 2ce1061 2785b89 8485798 2785b89 2ce1061 8485798 2785b89 8485798 2ce1061 2785b89 2ce1061 8485798 2ce1061 8485798 ceba2ab 2ce1061 8485798 ceba2ab 2ce1061 8485798 ceba2ab 2ce1061 29c44a0 2ce1061 8485798 2ce1061 8485798 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # server/graders/grader_easy.py
# Grades easy and medium tasks: runs code against test cases.
# Reward is proportional to tests passed (0.33, 0.67, 1.0).
import traceback
import signal
from typing import Tuple, List
def _timeout_handler(signum, frame):
raise TimeoutError("Code timed out — likely infinite loop. Check for missing visited set in graph traversal.")
def _run_code_safely(code: str, func_name: str, test_input):
"""Run submitted code safely with 5s timeout. Returns (result, error)."""
namespace = {}
try:
exec(compile(code, "<submitted>", "exec"), namespace)
except SyntaxError as e:
return None, f"SyntaxError: {e}"
except Exception as e:
return None, f"CompileError: {e}"
func = namespace.get(func_name)
if func is None:
funcs = [v for v in namespace.values() if callable(v) and not str(v.__name__).startswith("_")]
if not funcs:
return None, "No callable function found in submitted code."
func = funcs[0]
try:
try:
signal.signal(signal.SIGALRM, _timeout_handler)
signal.alarm(5)
except (AttributeError, OSError):
pass # Windows has no SIGALRM
if isinstance(test_input, list) and len(test_input) > 0 and isinstance(test_input[0], list):
result = func(*test_input)
elif isinstance(test_input, list):
try:
result = func(test_input)
except TypeError:
result = func(*test_input)
else:
result = func(test_input)
try:
signal.alarm(0)
except (AttributeError, OSError):
pass
return result, None
except TimeoutError as e:
return None, str(e)
except Exception as e:
try:
signal.alarm(0)
except (AttributeError, OSError):
pass
return None, f"RuntimeError: {traceback.format_exc(limit=2)}"
def _extract_func_name(code: str) -> str:
for line in code.splitlines():
line = line.strip()
if line.startswith("def "):
return line.split("(")[0].replace("def ", "").strip()
return "unknown"
def grade_easy(fixed_code: str, task: dict) -> Tuple[float, int, int, str, List[dict]]:
"""
Grade submission against test cases.
Returns: (reward, passed, total, feedback, results)
"""
test_cases = task["test_cases"]
total = len(test_cases)
passed = 0
results = []
func_name = _extract_func_name(fixed_code)
feedback_lines = []
for i, tc in enumerate(test_cases):
inp = tc["input"]
expected = tc["expected"]
got, error = _run_code_safely(fixed_code, func_name, inp)
if error:
results.append({"test_id": i+1, "passed": False, "expected": str(expected), "got": f"ERROR"})
feedback_lines.append(f"Test {i+1}: ❌ Error\n Input : {inp!r}\n Expected : {expected!r}\n Error : {error}")
elif got == expected:
passed += 1
results.append({"test_id": i+1, "passed": True, "expected": str(expected), "got": str(got)})
feedback_lines.append(f"Test {i+1}: ✅ Passed\n Input : {inp!r}\n Expected : {expected!r}\n Got : {got!r}")
else:
results.append({"test_id": i+1, "passed": False, "expected": str(expected), "got": str(got)})
feedback_lines.append(f"Test {i+1}: ❌ Failed\n Input : {inp!r}\n Expected : {expected!r}\n Got : {got!r}")
reward = passed / total
# ensure strict (0,1) range
if reward <= 0:
reward = 0.01
elif reward >= 1:
reward = 0.99
reward = round(reward, 2)
feedback = "\n".join(feedback_lines)
feedback += "\n🎉 All tests passed! Full reward." if passed == total else f"\n{passed}/{total} tests passed."
return reward, passed, total, feedback, results
|