|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
Local Python Executor. |
|
|
|
|
|
This module provides functionality for executing Python code locally by wrapping |
|
|
the smolagents LocalPythonExecutor. |
|
|
""" |
|
|
|
|
|
from smolagents import LocalPythonExecutor |
|
|
|
|
|
from core.env_server.types import CodeExecResult |
|
|
|
|
|
|
|
|
class PyExecutor: |
|
|
""" |
|
|
Wrapper around smolagents LocalPythonExecutor for executing Python code. |
|
|
|
|
|
This class provides a simple interface to execute Python code in a subprocess |
|
|
and capture the results including stdout, stderr, and exit code. |
|
|
|
|
|
Args: |
|
|
additional_imports: List of additional module imports to authorize. |
|
|
For example: ["numpy", "pandas", "matplotlib"] |
|
|
These will be added to the base authorized imports. |
|
|
|
|
|
Example: |
|
|
>>> # Basic usage with default imports |
|
|
>>> executor = PyExecutor() |
|
|
>>> result = executor.run("print('Hello, World!')") |
|
|
>>> print(result.stdout) # "Hello, World!\n" |
|
|
>>> print(result.exit_code) # 0 |
|
|
>>> |
|
|
>>> # Usage with additional imports |
|
|
>>> executor = PyExecutor(additional_imports=["numpy", "pandas"]) |
|
|
>>> result = executor.run("import numpy as np\\nprint(np.array([1, 2, 3]))") |
|
|
>>> print(result.stdout) # "[1 2 3]\n" |
|
|
""" |
|
|
|
|
|
def __init__(self, additional_imports: list[str] | None = None): |
|
|
""" |
|
|
Initialize the PyExecutor with a LocalPythonExecutor instance. |
|
|
|
|
|
Args: |
|
|
additional_imports: List of additional module names to authorize for import. |
|
|
Defaults to an empty list if not provided. |
|
|
""" |
|
|
if additional_imports is None: |
|
|
additional_imports = [] |
|
|
self._executor = LocalPythonExecutor( |
|
|
additional_authorized_imports=additional_imports |
|
|
) |
|
|
|
|
|
self._executor.send_tools({}) |
|
|
|
|
|
def run(self, code: str) -> CodeExecResult: |
|
|
""" |
|
|
Execute Python code and return the result. |
|
|
|
|
|
Args: |
|
|
code: Python code string to execute |
|
|
|
|
|
Returns: |
|
|
CodeExecResult containing stdout, stderr, and exit_code |
|
|
|
|
|
Example: |
|
|
>>> executor = PyExecutor() |
|
|
>>> result = executor.run("x = 5 + 3\\nprint(x)") |
|
|
>>> print(result.stdout) # "8\n" |
|
|
>>> print(result.exit_code) # 0 |
|
|
>>> |
|
|
>>> # Error handling |
|
|
>>> result = executor.run("1 / 0") |
|
|
>>> print(result.exit_code) # 1 |
|
|
>>> print(result.stderr) # Contains error message |
|
|
""" |
|
|
try: |
|
|
|
|
|
|
|
|
exec_result = self._executor(code) |
|
|
|
|
|
|
|
|
|
|
|
stdout = exec_result.logs |
|
|
stderr = "" |
|
|
exit_code = 0 |
|
|
|
|
|
return CodeExecResult( |
|
|
stdout=stdout, |
|
|
stderr=stderr, |
|
|
exit_code=exit_code, |
|
|
) |
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
|
|
|
return CodeExecResult( |
|
|
stdout="", |
|
|
stderr=str(e), |
|
|
exit_code=1, |
|
|
) |
|
|
|