Coverage for src / mcp_server_langgraph / execution / sandbox.py: 88%
24 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 00:43 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-03 00:43 +0000
1"""
2Abstract sandbox interface for secure code execution
4Defines the contract for all sandbox implementations (Docker, Kubernetes, Process).
5"""
7import time
8from abc import ABC, abstractmethod
9from dataclasses import dataclass
11from mcp_server_langgraph.execution.resource_limits import ResourceLimits
14class SandboxError(Exception):
15 """Raised when sandbox operations fail"""
18@dataclass
19class ExecutionResult:
20 """
21 Result of code execution in a sandbox.
23 Attributes:
24 success: True if code executed without errors
25 stdout: Standard output from execution
26 stderr: Standard error from execution
27 exit_code: Process exit code (0 = success)
28 execution_time: Time taken in seconds
29 timed_out: True if execution was terminated due to timeout
30 memory_used_mb: Peak memory usage in MB (if available)
31 error_message: Human-readable error message (if failed)
32 """
34 success: bool
35 stdout: str = ""
36 stderr: str = ""
37 exit_code: int = 0
38 execution_time: float = 0.0
39 timed_out: bool = False
40 memory_used_mb: float | None = None
41 error_message: str = ""
43 def __repr__(self) -> str:
44 status = "SUCCESS" if self.success else "FAILED"
45 if self.timed_out:
46 status = "TIMEOUT"
47 return f"ExecutionResult(status={status}, exit_code={self.exit_code}, time={self.execution_time:.2f}s)"
50class Sandbox(ABC):
51 """
52 Abstract base class for code execution sandboxes.
54 All sandbox implementations (Docker, Kubernetes, Process) must inherit from this
55 class and implement the execute() method.
57 Example:
58 >>> sandbox = DockerSandbox(limits=ResourceLimits.testing())
59 >>> result = sandbox.execute("print('Hello, World!')")
60 >>> assert result.success
61 >>> assert "Hello, World!" in result.stdout
62 """
64 def __init__(self, limits: ResourceLimits):
65 """
66 Initialize sandbox with resource limits.
68 Args:
69 limits: Resource limits to enforce (timeout, memory, CPU, etc.)
70 """
71 self.limits = limits
73 @abstractmethod
74 def execute(self, code: str) -> ExecutionResult:
75 """
76 Execute Python code in the sandbox.
78 This method must be implemented by all sandbox subclasses.
80 Args:
81 code: Python source code to execute
83 Returns:
84 ExecutionResult with execution status and outputs
86 Raises:
87 SandboxError: If sandbox setup or execution fails
88 """
90 def _create_success_result(
91 self,
92 stdout: str,
93 stderr: str,
94 execution_time: float,
95 memory_used_mb: float | None = None,
96 ) -> ExecutionResult:
97 """Helper to create successful execution result"""
98 return ExecutionResult(
99 success=True,
100 stdout=stdout,
101 stderr=stderr,
102 exit_code=0,
103 execution_time=execution_time,
104 timed_out=False,
105 memory_used_mb=memory_used_mb,
106 )
108 def _create_failure_result(
109 self,
110 stdout: str,
111 stderr: str,
112 exit_code: int,
113 execution_time: float,
114 timed_out: bool = False,
115 error_message: str = "",
116 ) -> ExecutionResult:
117 """Helper to create failed execution result"""
118 return ExecutionResult(
119 success=False,
120 stdout=stdout,
121 stderr=stderr,
122 exit_code=exit_code,
123 execution_time=execution_time,
124 timed_out=timed_out,
125 error_message=error_message,
126 )
128 def _measure_time(self, start_time: float) -> float:
129 """Helper to measure execution time"""
130 return time.time() - start_time