Download src/sr_harness/tools/code_executor.py from YuMeow/SRHarness: direct link, hf CLI and curl.
- Browser
- Download file 6.28 kB
-
https://huggingface.co/spaces/YuMeow/SRHarness/resolve/main/src/sr_harness/tools/code_executor.py
- Command line
-
hf download hf://spaces/YuMeow/SRHarness/src/sr_harness/tools/code_executor.py
-
curl -L -o code_executor.py https://huggingface.co/spaces/YuMeow/SRHarness/resolve/main/src/sr_harness/tools/code_executor.py
6.28 kB
| # Copyright (c) 2026-present, Yumeow. Licensed under the MIT License. | |
| """Execute data-only Python programs in an operating-system sandbox.""" | |
| from __future__ import annotations | |
| import io | |
| import json | |
| from typing import Any, Dict | |
| from ..runtime import get_sandbox_runner | |
| from ..utils import bounded_value | |
| from .base_tool import BaseTool, ToolMetadata | |
| class LimitedWriter(io.StringIO): | |
| """String buffer retained for bounded-output shell utilities.""" | |
| SUFFIX = "...[truncated]" | |
| def __init__(self, limit: int): | |
| super().__init__() | |
| self.limit = limit | |
| def write(self, text: str) -> int: | |
| remaining = self.limit - self.tell() - len(self.SUFFIX) | |
| if remaining <= 0: | |
| return len(text) | |
| if len(text) > remaining: | |
| super().write(text[:remaining]) | |
| super().write(self.SUFFIX) | |
| return len(text) | |
| return super().write(text) | |
| class CodeExecutorTool(BaseTool): | |
| """Implementation of the code executor tool.""" | |
| metadata = ToolMetadata(name="code_executor") | |
| DEFAULT_TIMEOUT_SECONDS = 30 | |
| DEFAULT_MEMORY_LIMIT_MB = 1024 | |
| DEFAULT_OUTPUT_LIMIT_BYTES = 64 * 1024 | |
| MAX_TIMEOUT_SECONDS = 120 | |
| MAX_MEMORY_LIMIT_MB = 4096 | |
| MAX_OUTPUT_LIMIT_BYTES = 1024 * 1024 | |
| def execute( | |
| self, | |
| program: str, | |
| timeout_seconds: int = DEFAULT_TIMEOUT_SECONDS, | |
| memory_limit_mb: int = DEFAULT_MEMORY_LIMIT_MB, | |
| output_limit_bytes: int = DEFAULT_OUTPUT_LIMIT_BYTES, | |
| ) -> Dict[str, Any]: | |
| """Execute Python code and return printed output. | |
| 1) Use `import sys, json; data_dict = json.loads(sys.stdin.read())` to | |
| access data mapping variable names to lists. | |
| 2) Use `print()` to produce output. | |
| 3) The code is executed in an operating-system sandbox with resource limits. | |
| 4) Installed scientific Python libraries are available. Files outside the | |
| ephemeral sandbox, networking, and child-process creation are unavailable. | |
| Args: | |
| program: Python code string to execute, starting with `import sys, json; | |
| data_dict = json.loads(sys.stdin.read())` to access input data. | |
| timeout_seconds: Wall-clock timeout in seconds. The effective value is capped. | |
| memory_limit_mb: Address-space memory limit in MB. The effective value is capped. | |
| output_limit_bytes: Limit on the amount of output (in bytes) that can be produced. | |
| """ | |
| timeout_seconds = self.bounded_int( | |
| timeout_seconds, self.DEFAULT_TIMEOUT_SECONDS, 1, self.MAX_TIMEOUT_SECONDS | |
| ) | |
| memory_limit_mb = self.bounded_int( | |
| memory_limit_mb, self.DEFAULT_MEMORY_LIMIT_MB, 64, self.MAX_MEMORY_LIMIT_MB | |
| ) | |
| output_limit_bytes = self.bounded_int( | |
| output_limit_bytes, self.DEFAULT_OUTPUT_LIMIT_BYTES, 1024, self.MAX_OUTPUT_LIMIT_BYTES | |
| ) | |
| stdin_text = json.dumps(self.serialization(self.context.data), ensure_ascii=False) | |
| result = get_sandbox_runner().run( | |
| self.extract_code(program), | |
| stdin=stdin_text, | |
| timeout_seconds=timeout_seconds, | |
| memory_limit_mb=memory_limit_mb, | |
| output_limit_bytes=output_limit_bytes, | |
| interruption_event=getattr(self, "cancel_event", None), | |
| ) | |
| if result.exit_code != 0: | |
| raise RuntimeError(result.stderr or f"Sandboxed program exited with {result.exit_code}") | |
| return { | |
| "stdout": result.stdout, | |
| "stderr": result.stderr, | |
| "duration": result.duration_seconds, | |
| "cpu_seconds": result.cpu_seconds, | |
| "peak_memory_bytes": result.peak_memory_bytes, | |
| "timeout_seconds": timeout_seconds, | |
| "memory_limit_mb": memory_limit_mb, | |
| "output_limit_bytes": output_limit_bytes, | |
| } | |
| def format_result_dict(cls, result: Dict[str, Any]) -> str: | |
| """Format a tool result for the language model. | |
| Args: | |
| result: Result mapping to format or update. | |
| Returns: | |
| str: The operation result. | |
| """ | |
| parts = [] | |
| if result["stdout"]: | |
| parts.append(result["stdout"].rstrip()) | |
| if result["stderr"]: | |
| parts.append(f"Program stderr:\n{result['stderr'].rstrip()}") | |
| if not parts: | |
| parts.append("Program completed successfully and printed no output.") | |
| parts.append(f"(Execution duration: {result['duration']:.3f} seconds.)") | |
| return "\n".join(parts) | |
| def extract_code(cls, code: str) -> str: | |
| """Extract Python source from an optional Markdown fence.""" | |
| raw_code = str(code).strip() | |
| if "```python" in raw_code: | |
| return raw_code.split("```python")[-1].split("```")[0].strip() | |
| if "```" not in raw_code: | |
| return raw_code | |
| parts = raw_code.split("```") | |
| if len(parts) <= 1: | |
| return raw_code | |
| potential_code = parts[1] | |
| if "\n" not in potential_code: | |
| return potential_code.strip() | |
| first_line, rest = potential_code.split("\n", 1) | |
| return rest.strip() if first_line.strip().isalpha() else potential_code.strip() | |
| def serialization(cls, value: Any) -> Any: | |
| """Convert context data to JSON-compatible values.""" | |
| if value is None or isinstance(value, (str, int, float, bool)): | |
| return value | |
| if isinstance(value, dict): | |
| return {str(key): cls.serialization(item) for key, item in value.items()} | |
| if isinstance(value, (list, tuple, set)): | |
| return [cls.serialization(item) for item in value] | |
| if hasattr(value, "tolist"): | |
| return cls.serialization(value.tolist()) | |
| if hasattr(value, "item"): | |
| return cls.serialization(value.item()) | |
| raise TypeError(f"unsupported data type {type(value).__name__}") | |
| def bounded_int(cls, value: Any, default: int, minimum: int, maximum: int) -> int: | |
| """Return a bounded integer tool argument.""" | |
| return bounded_value(value, min=minimum, max=maximum, default=default, converter=int) | |