e2b-code-interpreter 2.8.0__tar.gz → 2.8.1__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: e2b-code-interpreter
3
- Version: 2.8.0
3
+ Version: 2.8.1
4
4
  Summary: E2B Code Interpreter - Stateful code execution
5
5
  Home-page: https://e2b.dev/
6
6
  License: MIT
@@ -29,6 +29,7 @@ from e2b_code_interpreter.models import (
29
29
  from e2b_code_interpreter.exceptions import (
30
30
  format_execution_timeout_error,
31
31
  format_request_timeout_error,
32
+ format_sandbox_killed_error,
32
33
  )
33
34
 
34
35
  logger = logging.getLogger(__name__)
@@ -83,6 +84,23 @@ class AsyncSandbox(BaseAsyncSandbox):
83
84
  transport=get_transport(self.connection_config, http2=False),
84
85
  )
85
86
 
87
+ async def _handle_connection_error(self, err: Exception) -> None:
88
+ """
89
+ Raises a descriptive exception if the connection error was caused by
90
+ the sandbox being killed mid-request. If the sandbox is still running
91
+ (or its state can't be determined), returns so the caller can re-raise
92
+ the original error.
93
+ """
94
+ try:
95
+ running = await self.is_running()
96
+ except Exception:
97
+ # The state check itself failed, so we can't tell whether the
98
+ # sandbox was killed — let the caller re-raise the original error
99
+ # instead of wrongly claiming the sandbox is gone.
100
+ return
101
+ if not running:
102
+ raise format_sandbox_killed_error() from err
103
+
86
104
  @overload
87
105
  async def run_code(
88
106
  self,
@@ -217,6 +235,9 @@ class AsyncSandbox(BaseAsyncSandbox):
217
235
  raise format_execution_timeout_error()
218
236
  except httpx.TimeoutException:
219
237
  raise format_request_timeout_error()
238
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
239
+ await self._handle_connection_error(err)
240
+ raise
220
241
 
221
242
  async def create_code_context(
222
243
  self,
@@ -263,6 +284,9 @@ class AsyncSandbox(BaseAsyncSandbox):
263
284
  return Context.from_json(data)
264
285
  except httpx.TimeoutException:
265
286
  raise format_request_timeout_error()
287
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
288
+ await self._handle_connection_error(err)
289
+ raise
266
290
 
267
291
  async def remove_code_context(
268
292
  self,
@@ -295,6 +319,9 @@ class AsyncSandbox(BaseAsyncSandbox):
295
319
  raise err
296
320
  except httpx.TimeoutException:
297
321
  raise format_request_timeout_error()
322
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
323
+ await self._handle_connection_error(err)
324
+ raise
298
325
 
299
326
  async def list_code_contexts(self) -> List[Context]:
300
327
  """
@@ -323,6 +350,9 @@ class AsyncSandbox(BaseAsyncSandbox):
323
350
  return [Context.from_json(context_data) for context_data in data]
324
351
  except httpx.TimeoutException:
325
352
  raise format_request_timeout_error()
353
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
354
+ await self._handle_connection_error(err)
355
+ raise
326
356
 
327
357
  async def restart_code_context(
328
358
  self,
@@ -354,3 +384,6 @@ class AsyncSandbox(BaseAsyncSandbox):
354
384
  raise err
355
385
  except httpx.TimeoutException:
356
386
  raise format_request_timeout_error()
387
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
388
+ await self._handle_connection_error(err)
389
+ raise
@@ -25,6 +25,7 @@ from e2b_code_interpreter.models import (
25
25
  from e2b_code_interpreter.exceptions import (
26
26
  format_execution_timeout_error,
27
27
  format_request_timeout_error,
28
+ format_sandbox_killed_error,
28
29
  )
29
30
 
30
31
  logger = logging.getLogger(__name__)
@@ -77,6 +78,23 @@ class Sandbox(BaseSandbox):
77
78
  # cancelled reliably.
78
79
  return Client(transport=get_transport(self.connection_config, http2=False))
79
80
 
81
+ def _handle_connection_error(self, err: Exception) -> None:
82
+ """
83
+ Raises a descriptive exception if the connection error was caused by
84
+ the sandbox being killed mid-request. If the sandbox is still running
85
+ (or its state can't be determined), returns so the caller can re-raise
86
+ the original error.
87
+ """
88
+ try:
89
+ running = self.is_running()
90
+ except Exception:
91
+ # The state check itself failed, so we can't tell whether the
92
+ # sandbox was killed — let the caller re-raise the original error
93
+ # instead of wrongly claiming the sandbox is gone.
94
+ return
95
+ if not running:
96
+ raise format_sandbox_killed_error() from err
97
+
80
98
  @overload
81
99
  def run_code(
82
100
  self,
@@ -210,6 +228,9 @@ class Sandbox(BaseSandbox):
210
228
  raise format_execution_timeout_error()
211
229
  except httpx.TimeoutException:
212
230
  raise format_request_timeout_error()
231
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
232
+ self._handle_connection_error(err)
233
+ raise
213
234
 
214
235
  def create_code_context(
215
236
  self,
@@ -256,6 +277,9 @@ class Sandbox(BaseSandbox):
256
277
  return Context.from_json(data)
257
278
  except httpx.TimeoutException:
258
279
  raise format_request_timeout_error()
280
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
281
+ self._handle_connection_error(err)
282
+ raise
259
283
 
260
284
  def remove_code_context(
261
285
  self,
@@ -288,6 +312,9 @@ class Sandbox(BaseSandbox):
288
312
  raise err
289
313
  except httpx.TimeoutException:
290
314
  raise format_request_timeout_error()
315
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
316
+ self._handle_connection_error(err)
317
+ raise
291
318
 
292
319
  def list_code_contexts(self) -> List[Context]:
293
320
  """
@@ -316,6 +343,9 @@ class Sandbox(BaseSandbox):
316
343
  return [Context.from_json(context_data) for context_data in data]
317
344
  except httpx.TimeoutException:
318
345
  raise format_request_timeout_error()
346
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
347
+ self._handle_connection_error(err)
348
+ raise
319
349
 
320
350
  def restart_code_context(
321
351
  self,
@@ -348,3 +378,6 @@ class Sandbox(BaseSandbox):
348
378
  raise err
349
379
  except httpx.TimeoutException:
350
380
  raise format_request_timeout_error()
381
+ except (httpx.ReadError, httpx.RemoteProtocolError) as err:
382
+ self._handle_connection_error(err)
383
+ raise
@@ -11,3 +11,10 @@ def format_execution_timeout_error() -> Exception:
11
11
  return TimeoutException(
12
12
  "Execution timed out — the 'timeout' option can be used to increase this timeout",
13
13
  )
14
+
15
+
16
+ def format_sandbox_killed_error() -> Exception:
17
+ return TimeoutException(
18
+ "The sandbox was killed while the request was in progress. This can happen when the sandbox times out or is killed manually. "
19
+ "You can modify the sandbox timeout by passing 'timeout' when starting the sandbox or calling '.set_timeout' on the sandbox with the desired timeout",
20
+ )
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "e2b-code-interpreter"
3
- version = "2.8.0"
3
+ version = "2.8.1"
4
4
  description = "E2B Code Interpreter - Stateful code execution"
5
5
  authors = ["e2b <hello@e2b.dev>"]
6
6
  license = "MIT"