-
Notifications
You must be signed in to change notification settings - Fork 892
Expand file tree
/
Copy path__init__.py
More file actions
129 lines (106 loc) · 4.08 KB
/
__init__.py
File metadata and controls
129 lines (106 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import json
import logging
from dataclasses import dataclass
from typing import Optional, Union
from httpx import HTTPTransport, AsyncHTTPTransport
from e2b.api.client.client import AuthenticatedClient
from e2b.connection_config import ConnectionConfig
from e2b.api.metadata import default_headers
from e2b.exceptions import (
AuthenticationException,
SandboxException,
RateLimitException,
)
from e2b.api.client.types import Response
logger = logging.getLogger(__name__)
@dataclass
class SandboxCreateResponse:
sandbox_id: str
envd_version: str
def handle_api_exception(e: Response):
try:
body = json.loads(e.content) if e.content else {}
except json.JSONDecodeError:
body = {}
if e.status_code == 429:
return RateLimitException(
f"{e.status_code}: Rate limit exceeded, please try again later."
)
if "message" in body:
return SandboxException(f"{e.status_code}: {body['message']}")
return SandboxException(f"{e.status_code}: {e.content}")
class ApiClient(AuthenticatedClient):
"""
The client for interacting with the E2B API.
"""
def __init__(
self,
config: ConnectionConfig,
require_api_key: bool = True,
require_access_token: bool = False,
transport: Optional[Union[HTTPTransport, AsyncHTTPTransport]] = None,
*args,
**kwargs,
):
if require_api_key and require_access_token:
raise AuthenticationException(
"Only one of api_key or access_token can be required, not both",
)
if not require_api_key and not require_access_token:
raise AuthenticationException(
"Either api_key or access_token is required",
)
token = None
if require_api_key:
if config.api_key is None:
raise AuthenticationException(
"API key is required, please visit the Team tab at https://e2b.dev/dashboard to get your API key. "
"You can either set the environment variable `E2B_API_KEY` "
'or you can pass it directly to the sandbox like Sandbox(api_key="e2b_...")',
)
token = config.api_key
if require_access_token:
if config.access_token is None:
raise AuthenticationException(
"Access token is required, please visit the Personal tab at https://e2b.dev/dashboard to get your access token. "
"You can set the environment variable `E2B_ACCESS_TOKEN` or pass the `access_token` in options.",
)
token = config.access_token
auth_header_name = "X-API-KEY" if require_api_key else "Authorization"
prefix = "" if require_api_key else "Bearer"
headers = {
**default_headers,
**(config.headers or {}),
}
super().__init__(
base_url=config.api_url,
httpx_args={
"event_hooks": {
"request": [self._log_request],
"response": [self._log_response],
},
"transport": transport,
},
headers=headers,
token=token,
auth_header_name=auth_header_name,
prefix=prefix,
*args,
**kwargs,
)
def _log_request(self, request):
logger.info(f"Request {request.method} {request.url}")
def _log_response(self, response: Response):
if response.status_code >= 400:
logger.error(f"Response {response.status_code}")
else:
logger.info(f"Response {response.status_code}")
# We need to override the logging hooks for the async usage
class AsyncApiClient(ApiClient):
async def _log_request(self, request):
logger.info(f"Request {request.method} {request.url}")
async def _log_response(self, response: Response):
if response.status_code >= 400:
logger.error(f"Response {response.status_code}")
else:
logger.info(f"Response {response.status_code}")