scalebox-sdk 0.1.4__py3-none-any.whl → 0.1.25__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scalebox/__init__.py +1 -1
- scalebox/api/__init__.py +128 -128
- scalebox/api/client/__init__.py +8 -8
- scalebox/api/client/api/sandboxes/get_sandboxes.py +5 -3
- scalebox/api/client/api/sandboxes/get_sandboxes_sandbox_id_metrics.py +2 -2
- scalebox/api/client/api/sandboxes/post_sandboxes.py +2 -2
- scalebox/api/client/client.py +288 -288
- scalebox/api/client/models/listed_sandbox.py +11 -9
- scalebox/api/client/models/new_sandbox.py +1 -1
- scalebox/api/client/models/sandbox.py +125 -125
- scalebox/api/client/models/sandbox_state.py +1 -0
- scalebox/api/client/types.py +46 -46
- scalebox/code_interpreter/code_interpreter_async.py +370 -369
- scalebox/code_interpreter/code_interpreter_sync.py +318 -317
- scalebox/connection_config.py +92 -92
- scalebox/csx_desktop/main.py +12 -12
- scalebox/generated/api_pb2_connect.py +17 -66
- scalebox/sandbox_async/commands/command.py +307 -307
- scalebox/sandbox_async/commands/command_handle.py +187 -187
- scalebox/sandbox_async/commands/pty.py +187 -187
- scalebox/sandbox_async/filesystem/filesystem.py +557 -557
- scalebox/sandbox_async/filesystem/watch_handle.py +61 -61
- scalebox/sandbox_async/main.py +647 -646
- scalebox/sandbox_async/sandbox_api.py +365 -365
- scalebox/sandbox_async/utils.py +7 -7
- scalebox/sandbox_sync/__init__.py +2 -2
- scalebox/sandbox_sync/commands/command.py +300 -300
- scalebox/sandbox_sync/commands/command_handle.py +150 -150
- scalebox/sandbox_sync/commands/pty.py +181 -181
- scalebox/sandbox_sync/filesystem/filesystem.py +543 -543
- scalebox/sandbox_sync/filesystem/watch_handle.py +66 -66
- scalebox/sandbox_sync/main.py +789 -790
- scalebox/sandbox_sync/sandbox_api.py +356 -356
- scalebox/test/CODE_INTERPRETER_TESTS_READY.md +256 -256
- scalebox/test/README.md +164 -164
- scalebox/test/aclient.py +72 -72
- scalebox/test/code_interpreter_centext.py +21 -21
- scalebox/test/code_interpreter_centext_sync.py +21 -21
- scalebox/test/code_interpreter_test.py +1 -1
- scalebox/test/code_interpreter_test_sync.py +1 -1
- scalebox/test/run_all_validation_tests.py +334 -334
- scalebox/test/test_basic.py +78 -78
- scalebox/test/test_code_interpreter_async_comprehensive.py +2653 -2653
- scalebox/test/{test_code_interpreter_e2bsync_comprehensive.py → test_code_interpreter_execcode.py} +328 -392
- scalebox/test/test_code_interpreter_sync_comprehensive.py +3416 -3412
- scalebox/test/test_csx_desktop_examples.py +130 -0
- scalebox/test/test_sandbox_async_comprehensive.py +736 -738
- scalebox/test/test_sandbox_stress_and_edge_cases.py +778 -778
- scalebox/test/test_sandbox_sync_comprehensive.py +779 -770
- scalebox/test/test_sandbox_usage_examples.py +987 -987
- scalebox/test/testacreate.py +24 -24
- scalebox/test/testagetinfo.py +18 -18
- scalebox/test/testcodeinterpreter_async.py +508 -508
- scalebox/test/testcodeinterpreter_sync.py +239 -239
- scalebox/test/testcomputeuse.py +2 -2
- scalebox/test/testnovnc.py +12 -12
- scalebox/test/testsandbox_api.py +15 -0
- scalebox/test/testsandbox_async.py +202 -118
- scalebox/test/testsandbox_sync.py +71 -38
- scalebox/version.py +2 -2
- {scalebox_sdk-0.1.4.dist-info → scalebox_sdk-0.1.25.dist-info}/METADATA +104 -103
- {scalebox_sdk-0.1.4.dist-info → scalebox_sdk-0.1.25.dist-info}/RECORD +66 -66
- scalebox/test/test_code_interpreter_e2basync_comprehensive.py +0 -2655
- scalebox/test/test_e2b_first.py +0 -11
- {scalebox_sdk-0.1.4.dist-info → scalebox_sdk-0.1.25.dist-info}/WHEEL +0 -0
- {scalebox_sdk-0.1.4.dist-info → scalebox_sdk-0.1.25.dist-info}/entry_points.txt +0 -0
- {scalebox_sdk-0.1.4.dist-info → scalebox_sdk-0.1.25.dist-info}/licenses/LICENSE +0 -0
- {scalebox_sdk-0.1.4.dist-info → scalebox_sdk-0.1.25.dist-info}/top_level.txt +0 -0
|
@@ -1,317 +1,318 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import socket
|
|
3
|
-
import time
|
|
4
|
-
from typing import Dict, Iterator, Literal, Optional, Union, overload
|
|
5
|
-
|
|
6
|
-
import urllib3
|
|
7
|
-
from httpx import Timeout
|
|
8
|
-
from urllib3 import Retry
|
|
9
|
-
|
|
10
|
-
from ..exceptions import InvalidArgumentException
|
|
11
|
-
from ..generated import api_pb2, api_pb2_connect
|
|
12
|
-
from ..sandbox_sync.main import Sandbox as BaseSandbox
|
|
13
|
-
from .constants import DEFAULT_TEMPLATE, DEFAULT_TIMEOUT, JUPYTER_PORT
|
|
14
|
-
from .exceptions import format_execution_timeout_error, format_request_timeout_error
|
|
15
|
-
from .models import (
|
|
16
|
-
Context,
|
|
17
|
-
Execution,
|
|
18
|
-
ExecutionError,
|
|
19
|
-
OutputHandler,
|
|
20
|
-
OutputMessage,
|
|
21
|
-
Result,
|
|
22
|
-
parse_output,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
logger = logging.getLogger(__name__)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class Sandbox(BaseSandbox):
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
The sandbox allows you to:
|
|
33
|
-
- Access Linux OS
|
|
34
|
-
- Create, list, and delete files and directories
|
|
35
|
-
- Run commands
|
|
36
|
-
- Run isolated code
|
|
37
|
-
- Access the internet
|
|
38
|
-
|
|
39
|
-
Check docs
|
|
40
|
-
|
|
41
|
-
Use the `Sandbox()` to create a new sandbox.
|
|
42
|
-
|
|
43
|
-
Example:
|
|
44
|
-
```python
|
|
45
|
-
from scalebox.code_interpreter import Sandbox
|
|
46
|
-
|
|
47
|
-
sandbox = Sandbox()
|
|
48
|
-
```
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
default_template = DEFAULT_TEMPLATE
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def _jupyter_url(self) -> str:
|
|
55
|
-
return f"{'http' if self.connection_config.debug else 'https'}://{self.get_host(JUPYTER_PORT)}"
|
|
56
|
-
|
|
57
|
-
@overload
|
|
58
|
-
def run_code(
|
|
59
|
-
self,
|
|
60
|
-
code: str,
|
|
61
|
-
language: Union[Literal["python"], None] = "python",
|
|
62
|
-
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
63
|
-
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
64
|
-
on_result: Optional[OutputHandler[Result]] = None,
|
|
65
|
-
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
66
|
-
envs: Optional[Dict[str, str]] = None,
|
|
67
|
-
timeout: Optional[float] = None,
|
|
68
|
-
request_timeout: Optional[float] = None,
|
|
69
|
-
) -> Execution:
|
|
70
|
-
"""
|
|
71
|
-
Runs the code as Python.
|
|
72
|
-
|
|
73
|
-
Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
|
|
74
|
-
|
|
75
|
-
You can reference previously defined variables, imports, and functions in the code.
|
|
76
|
-
|
|
77
|
-
:param code: Code to execute
|
|
78
|
-
:param language: Language to use for code execution. If not defined, the default Python context is used.
|
|
79
|
-
:param on_stdout: Callback for stdout messages
|
|
80
|
-
:param on_stderr: Callback for stderr messages
|
|
81
|
-
:param on_result: Callback for the `Result` object
|
|
82
|
-
:param on_error: Callback for the `ExecutionError` object
|
|
83
|
-
:param envs: Custom environment variables
|
|
84
|
-
:param timeout: Timeout for the code execution in **seconds**
|
|
85
|
-
:param request_timeout: Timeout for the request in **seconds**
|
|
86
|
-
|
|
87
|
-
:return: `Execution` result object
|
|
88
|
-
"""
|
|
89
|
-
...
|
|
90
|
-
|
|
91
|
-
@overload
|
|
92
|
-
def run_code(
|
|
93
|
-
self,
|
|
94
|
-
code: str,
|
|
95
|
-
language: Optional[str] = "python",
|
|
96
|
-
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
97
|
-
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
98
|
-
on_result: Optional[OutputHandler[Result]] = None,
|
|
99
|
-
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
100
|
-
envs: Optional[Dict[str, str]] = None,
|
|
101
|
-
timeout: Optional[float] = None,
|
|
102
|
-
request_timeout: Optional[float] = None,
|
|
103
|
-
) -> Execution:
|
|
104
|
-
"""
|
|
105
|
-
Runs the code for the specified language.
|
|
106
|
-
|
|
107
|
-
Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
|
|
108
|
-
If no language is specified, Python is used.
|
|
109
|
-
|
|
110
|
-
You can reference previously defined variables, imports, and functions in the code.
|
|
111
|
-
|
|
112
|
-
:param code: Code to execute
|
|
113
|
-
:param language: Language to use for code execution. If not defined, the default Python context is used.
|
|
114
|
-
:param on_stdout: Callback for stdout messages
|
|
115
|
-
:param on_stderr: Callback for stderr messages
|
|
116
|
-
:param on_result: Callback for the `Result` object
|
|
117
|
-
:param on_error: Callback for the `ExecutionError` object
|
|
118
|
-
:param envs: Custom environment variables
|
|
119
|
-
:param timeout: Timeout for the code execution in **seconds**
|
|
120
|
-
:param request_timeout: Timeout for the request in **seconds**
|
|
121
|
-
|
|
122
|
-
:return: `Execution` result object
|
|
123
|
-
"""
|
|
124
|
-
...
|
|
125
|
-
|
|
126
|
-
@overload
|
|
127
|
-
def run_code(
|
|
128
|
-
self,
|
|
129
|
-
code: str,
|
|
130
|
-
context: Optional[Context] = None,
|
|
131
|
-
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
132
|
-
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
133
|
-
on_result: Optional[OutputHandler[Result]] = None,
|
|
134
|
-
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
135
|
-
envs: Optional[Dict[str, str]] = None,
|
|
136
|
-
timeout: Optional[float] = None,
|
|
137
|
-
request_timeout: Optional[float] = None,
|
|
138
|
-
) -> Execution:
|
|
139
|
-
"""
|
|
140
|
-
Runs the code in the specified context, if not specified, the default context is used.
|
|
141
|
-
|
|
142
|
-
Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
|
|
143
|
-
|
|
144
|
-
You can reference previously defined variables, imports, and functions in the code.
|
|
145
|
-
|
|
146
|
-
:param code: Code to execute
|
|
147
|
-
:param context: Concrete context to run the code in. If not specified, the default context for the language is used. It's mutually exclusive with the language.
|
|
148
|
-
:param on_stdout: Callback for stdout messages
|
|
149
|
-
:param on_stderr: Callback for stderr messages
|
|
150
|
-
:param on_result: Callback for the `Result` object
|
|
151
|
-
:param on_error: Callback for the `ExecutionError` object
|
|
152
|
-
:param envs: Custom environment variables
|
|
153
|
-
:param timeout: Timeout for the code execution in **seconds**
|
|
154
|
-
:param request_timeout: Timeout for the request in **seconds**
|
|
155
|
-
|
|
156
|
-
:return: `Execution` result object
|
|
157
|
-
"""
|
|
158
|
-
...
|
|
159
|
-
|
|
160
|
-
def run_code(
|
|
161
|
-
self,
|
|
162
|
-
code: str,
|
|
163
|
-
language: Optional[str] = None,
|
|
164
|
-
context: Optional[Context] = None,
|
|
165
|
-
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
166
|
-
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
167
|
-
on_result: Optional[OutputHandler[Result]] = None,
|
|
168
|
-
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
169
|
-
envs: Optional[Dict[str, str]] = None,
|
|
170
|
-
timeout: Optional[float] = None,
|
|
171
|
-
request_timeout: Optional[float] = None,
|
|
172
|
-
) -> Execution:
|
|
173
|
-
logger.debug(f"Executing code {code}")
|
|
174
|
-
|
|
175
|
-
if language and context:
|
|
176
|
-
raise InvalidArgumentException(
|
|
177
|
-
"You can provide context or language, but not both at the same time."
|
|
178
|
-
)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
#
|
|
215
|
-
#
|
|
216
|
-
parse_output
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
raise
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
:param
|
|
249
|
-
:param
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
#
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
"
|
|
281
|
-
"
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
raise
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
1
|
+
import logging
|
|
2
|
+
import socket
|
|
3
|
+
import time
|
|
4
|
+
from typing import Dict, Iterator, Literal, Optional, Union, overload
|
|
5
|
+
|
|
6
|
+
import urllib3
|
|
7
|
+
from httpx import Timeout
|
|
8
|
+
from urllib3 import Retry
|
|
9
|
+
|
|
10
|
+
from ..exceptions import InvalidArgumentException
|
|
11
|
+
from ..generated import api_pb2, api_pb2_connect
|
|
12
|
+
from ..sandbox_sync.main import Sandbox as BaseSandbox
|
|
13
|
+
from .constants import DEFAULT_TEMPLATE, DEFAULT_TIMEOUT, JUPYTER_PORT
|
|
14
|
+
from .exceptions import format_execution_timeout_error, format_request_timeout_error
|
|
15
|
+
from .models import (
|
|
16
|
+
Context,
|
|
17
|
+
Execution,
|
|
18
|
+
ExecutionError,
|
|
19
|
+
OutputHandler,
|
|
20
|
+
OutputMessage,
|
|
21
|
+
Result,
|
|
22
|
+
parse_output,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Sandbox(BaseSandbox):
|
|
29
|
+
"""
|
|
30
|
+
Scalebox cloud sandbox is a secure and isolated cloud environment.
|
|
31
|
+
|
|
32
|
+
The sandbox allows you to:
|
|
33
|
+
- Access Linux OS
|
|
34
|
+
- Create, list, and delete files and directories
|
|
35
|
+
- Run commands
|
|
36
|
+
- Run isolated code
|
|
37
|
+
- Access the internet
|
|
38
|
+
|
|
39
|
+
Check docs for more information.
|
|
40
|
+
|
|
41
|
+
Use the `Sandbox()` to create a new sandbox.
|
|
42
|
+
|
|
43
|
+
Example:
|
|
44
|
+
```python
|
|
45
|
+
from scalebox.code_interpreter import Sandbox
|
|
46
|
+
|
|
47
|
+
sandbox = Sandbox()
|
|
48
|
+
```
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
default_template = DEFAULT_TEMPLATE
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def _jupyter_url(self) -> str:
|
|
55
|
+
return f"{'http' if self.connection_config.debug else 'https'}://{self.get_host(JUPYTER_PORT)}"
|
|
56
|
+
|
|
57
|
+
@overload
|
|
58
|
+
def run_code(
|
|
59
|
+
self,
|
|
60
|
+
code: str,
|
|
61
|
+
language: Union[Literal["python"], None] = "python",
|
|
62
|
+
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
63
|
+
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
64
|
+
on_result: Optional[OutputHandler[Result]] = None,
|
|
65
|
+
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
66
|
+
envs: Optional[Dict[str, str]] = None,
|
|
67
|
+
timeout: Optional[float] = None,
|
|
68
|
+
request_timeout: Optional[float] = None,
|
|
69
|
+
) -> Execution:
|
|
70
|
+
"""
|
|
71
|
+
Runs the code as Python.
|
|
72
|
+
|
|
73
|
+
Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
|
|
74
|
+
|
|
75
|
+
You can reference previously defined variables, imports, and functions in the code.
|
|
76
|
+
|
|
77
|
+
:param code: Code to execute
|
|
78
|
+
:param language: Language to use for code execution. If not defined, the default Python context is used.
|
|
79
|
+
:param on_stdout: Callback for stdout messages
|
|
80
|
+
:param on_stderr: Callback for stderr messages
|
|
81
|
+
:param on_result: Callback for the `Result` object
|
|
82
|
+
:param on_error: Callback for the `ExecutionError` object
|
|
83
|
+
:param envs: Custom environment variables
|
|
84
|
+
:param timeout: Timeout for the code execution in **seconds**
|
|
85
|
+
:param request_timeout: Timeout for the request in **seconds**
|
|
86
|
+
|
|
87
|
+
:return: `Execution` result object
|
|
88
|
+
"""
|
|
89
|
+
...
|
|
90
|
+
|
|
91
|
+
@overload
|
|
92
|
+
def run_code(
|
|
93
|
+
self,
|
|
94
|
+
code: str,
|
|
95
|
+
language: Optional[str] = "python",
|
|
96
|
+
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
97
|
+
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
98
|
+
on_result: Optional[OutputHandler[Result]] = None,
|
|
99
|
+
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
100
|
+
envs: Optional[Dict[str, str]] = None,
|
|
101
|
+
timeout: Optional[float] = None,
|
|
102
|
+
request_timeout: Optional[float] = None,
|
|
103
|
+
) -> Execution:
|
|
104
|
+
"""
|
|
105
|
+
Runs the code for the specified language.
|
|
106
|
+
|
|
107
|
+
Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
|
|
108
|
+
If no language is specified, Python is used.
|
|
109
|
+
|
|
110
|
+
You can reference previously defined variables, imports, and functions in the code.
|
|
111
|
+
|
|
112
|
+
:param code: Code to execute
|
|
113
|
+
:param language: Language to use for code execution. If not defined, the default Python context is used.
|
|
114
|
+
:param on_stdout: Callback for stdout messages
|
|
115
|
+
:param on_stderr: Callback for stderr messages
|
|
116
|
+
:param on_result: Callback for the `Result` object
|
|
117
|
+
:param on_error: Callback for the `ExecutionError` object
|
|
118
|
+
:param envs: Custom environment variables
|
|
119
|
+
:param timeout: Timeout for the code execution in **seconds**
|
|
120
|
+
:param request_timeout: Timeout for the request in **seconds**
|
|
121
|
+
|
|
122
|
+
:return: `Execution` result object
|
|
123
|
+
"""
|
|
124
|
+
...
|
|
125
|
+
|
|
126
|
+
@overload
|
|
127
|
+
def run_code(
|
|
128
|
+
self,
|
|
129
|
+
code: str,
|
|
130
|
+
context: Optional[Context] = None,
|
|
131
|
+
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
132
|
+
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
133
|
+
on_result: Optional[OutputHandler[Result]] = None,
|
|
134
|
+
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
135
|
+
envs: Optional[Dict[str, str]] = None,
|
|
136
|
+
timeout: Optional[float] = None,
|
|
137
|
+
request_timeout: Optional[float] = None,
|
|
138
|
+
) -> Execution:
|
|
139
|
+
"""
|
|
140
|
+
Runs the code in the specified context, if not specified, the default context is used.
|
|
141
|
+
|
|
142
|
+
Specify the `language` or `context` option to run the code as a different language or in a different `Context`.
|
|
143
|
+
|
|
144
|
+
You can reference previously defined variables, imports, and functions in the code.
|
|
145
|
+
|
|
146
|
+
:param code: Code to execute
|
|
147
|
+
:param context: Concrete context to run the code in. If not specified, the default context for the language is used. It's mutually exclusive with the language.
|
|
148
|
+
:param on_stdout: Callback for stdout messages
|
|
149
|
+
:param on_stderr: Callback for stderr messages
|
|
150
|
+
:param on_result: Callback for the `Result` object
|
|
151
|
+
:param on_error: Callback for the `ExecutionError` object
|
|
152
|
+
:param envs: Custom environment variables
|
|
153
|
+
:param timeout: Timeout for the code execution in **seconds**
|
|
154
|
+
:param request_timeout: Timeout for the request in **seconds**
|
|
155
|
+
|
|
156
|
+
:return: `Execution` result object
|
|
157
|
+
"""
|
|
158
|
+
...
|
|
159
|
+
|
|
160
|
+
def run_code(
|
|
161
|
+
self,
|
|
162
|
+
code: str,
|
|
163
|
+
language: Optional[str] = None,
|
|
164
|
+
context: Optional[Context] = None,
|
|
165
|
+
on_stdout: Optional[OutputHandler[OutputMessage]] = None,
|
|
166
|
+
on_stderr: Optional[OutputHandler[OutputMessage]] = None,
|
|
167
|
+
on_result: Optional[OutputHandler[Result]] = None,
|
|
168
|
+
on_error: Optional[OutputHandler[ExecutionError]] = None,
|
|
169
|
+
envs: Optional[Dict[str, str]] = None,
|
|
170
|
+
timeout: Optional[float] = None,
|
|
171
|
+
request_timeout: Optional[float] = None,
|
|
172
|
+
) -> Execution:
|
|
173
|
+
logger.debug(f"Executing code {code}")
|
|
174
|
+
|
|
175
|
+
if language and context:
|
|
176
|
+
raise InvalidArgumentException(
|
|
177
|
+
"You can provide context or language, but not both at the same time."
|
|
178
|
+
)
|
|
179
|
+
if language is None and context is None:
|
|
180
|
+
language = "python"
|
|
181
|
+
timeout = None if timeout == 0 else (timeout or DEFAULT_TIMEOUT)
|
|
182
|
+
request_timeout = request_timeout or self._connection_config.request_timeout
|
|
183
|
+
context_id = context.id if context else None
|
|
184
|
+
client = api_pb2_connect.ExecutionServiceClient(
|
|
185
|
+
base_url=self.envd_api_url,
|
|
186
|
+
http_client=self._urllib3_pool,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Create execution request
|
|
190
|
+
execute_request = api_pb2.ExecuteRequest(
|
|
191
|
+
code=code,
|
|
192
|
+
context_id=context_id or "",
|
|
193
|
+
language=language or "",
|
|
194
|
+
env_vars=envs,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
# Calculate deadline for gRPC call
|
|
199
|
+
deadline = time.time() + request_timeout + (timeout or 0)
|
|
200
|
+
|
|
201
|
+
# Execute code via gRPC
|
|
202
|
+
execution = Execution()
|
|
203
|
+
# headers = {
|
|
204
|
+
# "Authorization": "Bearer root",
|
|
205
|
+
# }
|
|
206
|
+
response_stream = client.execute(
|
|
207
|
+
execute_request,
|
|
208
|
+
timeout_seconds=deadline - time.time(),
|
|
209
|
+
extra_headers=self.connection_config.headers,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# Process stream responses
|
|
213
|
+
for response in response_stream:
|
|
214
|
+
# Convert gRPC response to the format expected by parse_output
|
|
215
|
+
# This assumes parse_output can handle gRPC response format
|
|
216
|
+
# You might need to adjust parse_output or convert the response here
|
|
217
|
+
parse_output(
|
|
218
|
+
execution,
|
|
219
|
+
response,
|
|
220
|
+
on_stdout=on_stdout,
|
|
221
|
+
on_stderr=on_stderr,
|
|
222
|
+
on_result=on_result,
|
|
223
|
+
on_error=on_error,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
return execution
|
|
227
|
+
|
|
228
|
+
except Exception as e:
|
|
229
|
+
# Handle different types of timeout exceptions
|
|
230
|
+
if "timeout" in str(e).lower() or "deadline" in str(e).lower():
|
|
231
|
+
if "execution" in str(e).lower():
|
|
232
|
+
raise format_execution_timeout_error()
|
|
233
|
+
else:
|
|
234
|
+
raise format_request_timeout_error()
|
|
235
|
+
else:
|
|
236
|
+
# Re-raise other exceptions
|
|
237
|
+
raise e
|
|
238
|
+
|
|
239
|
+
def create_code_context(
|
|
240
|
+
self,
|
|
241
|
+
cwd: Optional[str] = None,
|
|
242
|
+
language: Optional[str] = None,
|
|
243
|
+
request_timeout: Optional[float] = None,
|
|
244
|
+
) -> Context:
|
|
245
|
+
"""
|
|
246
|
+
Creates a new context to run code in.
|
|
247
|
+
|
|
248
|
+
:param cwd: Set the current working directory for the context, defaults to `/home/user`
|
|
249
|
+
:param language: Language of the context. If not specified, defaults to Python
|
|
250
|
+
:param request_timeout: Timeout for the request in **milliseconds**
|
|
251
|
+
|
|
252
|
+
:return: Context object
|
|
253
|
+
"""
|
|
254
|
+
logger.debug(f"Creating new {language} context")
|
|
255
|
+
|
|
256
|
+
# Create context request
|
|
257
|
+
create_context_request = api_pb2.CreateContextRequest(
|
|
258
|
+
language=language or "python3",
|
|
259
|
+
cwd=cwd or "",
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
try:
|
|
263
|
+
client = api_pb2_connect.ContextServiceClient(
|
|
264
|
+
base_url=self.envd_api_url,
|
|
265
|
+
http_client=self._urllib3_pool,
|
|
266
|
+
)
|
|
267
|
+
# headers = {
|
|
268
|
+
# "Authorization": "Bearer root",
|
|
269
|
+
# }
|
|
270
|
+
# Create context via gRPC
|
|
271
|
+
response = client.create_context(
|
|
272
|
+
create_context_request,
|
|
273
|
+
timeout_seconds=request_timeout
|
|
274
|
+
or self._connection_config.request_timeout,
|
|
275
|
+
extra_headers=self.connection_config.headers,
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
return Context.from_json(
|
|
279
|
+
{
|
|
280
|
+
"id": response.id,
|
|
281
|
+
"language": response.language,
|
|
282
|
+
"cwd": response.cwd,
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
except Exception as e:
|
|
287
|
+
# Handle timeout exceptions
|
|
288
|
+
if "timeout" in str(e).lower() or "deadline" in str(e).lower():
|
|
289
|
+
raise format_request_timeout_error()
|
|
290
|
+
else:
|
|
291
|
+
# Re-raise other exceptions
|
|
292
|
+
raise e
|
|
293
|
+
|
|
294
|
+
def destroy_context(self, context: Context) -> None:
|
|
295
|
+
"""
|
|
296
|
+
Destroys a context.
|
|
297
|
+
|
|
298
|
+
:param context: Context to destroy
|
|
299
|
+
"""
|
|
300
|
+
logger.debug(f"Destroying context {context.id}")
|
|
301
|
+
|
|
302
|
+
# Create destroy context request
|
|
303
|
+
destroy_context_request = api_pb2.DestroyContextRequest(
|
|
304
|
+
context_id=context.id,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
try:
|
|
308
|
+
client = api_pb2_connect.ContextServiceClient(
|
|
309
|
+
base_url=self.envd_api_url,
|
|
310
|
+
http_client=self._urllib3_pool,
|
|
311
|
+
)
|
|
312
|
+
# headers = {
|
|
313
|
+
# "Authorization": "Bearer root",
|
|
314
|
+
# }
|
|
315
|
+
client.destroy_context(destroy_context_request,extra_headers=self.connection_config.headers)
|
|
316
|
+
|
|
317
|
+
except Exception as e:
|
|
318
|
+
logger.warning(f"Failed to destroy context {context.id}: {e}")
|