codeapi-client 0.4.1__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.
- codeapi/__init__.py +17 -0
- codeapi/client/__init__.py +37 -0
- codeapi/client/_async/__init__.py +357 -0
- codeapi/client/_async/_app.py +369 -0
- codeapi/client/_async/_cli.py +334 -0
- codeapi/client/_async/_code.py +211 -0
- codeapi/client/_async/_jobs.py +512 -0
- codeapi/client/_async/_mcp.py +445 -0
- codeapi/client/_async/_web.py +343 -0
- codeapi/client/_base.py +118 -0
- codeapi/client/_sync/__init__.py +347 -0
- codeapi/client/_sync/_app.py +367 -0
- codeapi/client/_sync/_cli.py +332 -0
- codeapi/client/_sync/_code.py +203 -0
- codeapi/client/_sync/_jobs.py +497 -0
- codeapi/client/_sync/_mcp.py +442 -0
- codeapi/client/_sync/_web.py +341 -0
- codeapi/client/_utils.py +61 -0
- codeapi/client/py.typed +0 -0
- codeapi/types/__init__.py +77 -0
- codeapi/types/_api.py +30 -0
- codeapi/types/_base.py +21 -0
- codeapi/types/_code.py +31 -0
- codeapi/types/_enums.py +150 -0
- codeapi/types/_env.py +65 -0
- codeapi/types/_exc.py +35 -0
- codeapi/types/_job.py +67 -0
- codeapi/types/_json.py +67 -0
- codeapi/types/_stream.py +36 -0
- codeapi/types/_swarm.py +85 -0
- codeapi/types/_time.py +46 -0
- codeapi/types/_zips.py +466 -0
- codeapi/types/py.typed +0 -0
- codeapi_client-0.4.1.dist-info/METADATA +14 -0
- codeapi_client-0.4.1.dist-info/RECORD +36 -0
- codeapi_client-0.4.1.dist-info/WHEEL +4 -0
codeapi/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
def __get_version():
|
|
2
|
+
import importlib.metadata
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
return importlib.metadata.version(__name__)
|
|
6
|
+
except Exception:
|
|
7
|
+
return None
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__version__ = __get_version()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
del __get_version
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
print("Hello from CodeAPI!")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from typing import TypeAlias
|
|
2
|
+
|
|
3
|
+
from codeapi.types import CodeAPIError, CodeAPIException
|
|
4
|
+
|
|
5
|
+
from ._async import AsyncClient
|
|
6
|
+
from ._sync import Client
|
|
7
|
+
|
|
8
|
+
AsyncCodeAPI: TypeAlias = AsyncClient
|
|
9
|
+
CodeAPI: TypeAlias = Client
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def __get_version():
|
|
13
|
+
import importlib.metadata
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
return importlib.metadata.version(__name__)
|
|
17
|
+
except Exception:
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
__version__ = __get_version()
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"CodeAPIError",
|
|
25
|
+
"CodeAPIException",
|
|
26
|
+
"AsyncClient",
|
|
27
|
+
"AsyncCodeAPI",
|
|
28
|
+
"Client",
|
|
29
|
+
"CodeAPI",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
for __name in __all__:
|
|
34
|
+
if not __name.startswith("__") and hasattr(locals()[__name], "__module__"):
|
|
35
|
+
setattr(locals()[__name], "__module__", __name__)
|
|
36
|
+
|
|
37
|
+
del __get_version
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import AsyncGenerator
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from codeapi.client._base import ClientBase
|
|
8
|
+
from codeapi.types import (
|
|
9
|
+
CodeInfo,
|
|
10
|
+
CodeType,
|
|
11
|
+
CodeZip,
|
|
12
|
+
Job,
|
|
13
|
+
JobResult,
|
|
14
|
+
JobStage,
|
|
15
|
+
JobStatus,
|
|
16
|
+
JsonData,
|
|
17
|
+
ServerStatus,
|
|
18
|
+
ServicesHealth,
|
|
19
|
+
StreamOutput,
|
|
20
|
+
TokenRequest,
|
|
21
|
+
TokenResponse,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from ._app import AsyncAppClient
|
|
25
|
+
from ._cli import AsyncCliClient
|
|
26
|
+
from ._code import AsyncCodeClient
|
|
27
|
+
from ._jobs import AsyncJobsClient
|
|
28
|
+
from ._mcp import AsyncMcpClient
|
|
29
|
+
from ._web import AsyncWebClient
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AsyncClient(ClientBase):
|
|
33
|
+
"""Async CodeAPI Client"""
|
|
34
|
+
|
|
35
|
+
def __init__(self, base_url: str, api_key: str = ""):
|
|
36
|
+
"""Initializes the async CodeAPI Client.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
base_url (str): The base URL of the CodeAPI.
|
|
40
|
+
api_key (str): The CodeAPI key.
|
|
41
|
+
"""
|
|
42
|
+
super().__init__(base_url=base_url, api_key=api_key)
|
|
43
|
+
|
|
44
|
+
self.code = AsyncCodeClient(self)
|
|
45
|
+
self.jobs = AsyncJobsClient(self)
|
|
46
|
+
self.mcp = AsyncMcpClient(self)
|
|
47
|
+
self.cli = AsyncCliClient(self)
|
|
48
|
+
self.app = AsyncAppClient(self)
|
|
49
|
+
self.web = AsyncWebClient(self)
|
|
50
|
+
|
|
51
|
+
async def is_healthy(self) -> bool:
|
|
52
|
+
"""Checks if the server is healthy.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
bool: True if the server is healthy, False otherwise.
|
|
56
|
+
"""
|
|
57
|
+
url = f"{self.base_url}/server/status"
|
|
58
|
+
async with httpx.AsyncClient() as client:
|
|
59
|
+
try:
|
|
60
|
+
response = await client.get(url, headers=self.api_key_header)
|
|
61
|
+
response.raise_for_status()
|
|
62
|
+
return ServerStatus(**response.json()).is_healthy
|
|
63
|
+
except httpx.HTTPStatusError:
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
async def get_services_health(self) -> ServicesHealth:
|
|
67
|
+
"""Gets the health of services.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
ServicesHealth: The health of services.
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
HTTPException: If the request fails.
|
|
74
|
+
"""
|
|
75
|
+
url = f"{self.base_url}/services/health"
|
|
76
|
+
async with httpx.AsyncClient() as client:
|
|
77
|
+
try:
|
|
78
|
+
response = await client.get(url, headers=self.api_key_header)
|
|
79
|
+
response.raise_for_status()
|
|
80
|
+
return ServicesHealth(**response.json())
|
|
81
|
+
except httpx.HTTPStatusError as e:
|
|
82
|
+
raise self._get_http_exception(httpx_error=e)
|
|
83
|
+
|
|
84
|
+
async def generate_token(
|
|
85
|
+
self, user: str, ulid: str | None = None, ttl: int = -1
|
|
86
|
+
) -> str:
|
|
87
|
+
"""Generates a new API token
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
user (str): The unique identifier of the user.
|
|
91
|
+
ulid (str | None, optional): The ULID for the token.
|
|
92
|
+
ttl (int, optional): Time-to-live for the token in seconds.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
str: The generated API token.
|
|
96
|
+
"""
|
|
97
|
+
url = f"{self.base_url}/api/token"
|
|
98
|
+
async with httpx.AsyncClient() as client:
|
|
99
|
+
try:
|
|
100
|
+
token_request = TokenRequest(user=user, ulid=ulid, ttl=ttl)
|
|
101
|
+
response = await client.post(
|
|
102
|
+
url,
|
|
103
|
+
headers=self.api_key_header,
|
|
104
|
+
json=token_request.model_dump(),
|
|
105
|
+
)
|
|
106
|
+
response.raise_for_status()
|
|
107
|
+
token_response = TokenResponse(**response.json())
|
|
108
|
+
return token_response.token
|
|
109
|
+
except httpx.HTTPStatusError as e:
|
|
110
|
+
raise self._get_http_exception(httpx_error=e)
|
|
111
|
+
|
|
112
|
+
async def clear_db(self) -> None:
|
|
113
|
+
"""Clears the database.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
HTTPException: If the request fails.
|
|
117
|
+
"""
|
|
118
|
+
url = f"{self.base_url}/db/clear"
|
|
119
|
+
async with httpx.AsyncClient() as client:
|
|
120
|
+
try:
|
|
121
|
+
response = await client.post(url, headers=self.api_key_header)
|
|
122
|
+
response.raise_for_status()
|
|
123
|
+
except httpx.HTTPStatusError as e:
|
|
124
|
+
raise self._get_http_exception(httpx_error=e)
|
|
125
|
+
|
|
126
|
+
async def get_job(self, job_id: str) -> Job:
|
|
127
|
+
"""Gets a job.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
job_id (str): The ID of the job.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Job: The job.
|
|
134
|
+
"""
|
|
135
|
+
return await self.jobs.get(job_id)
|
|
136
|
+
|
|
137
|
+
async def list_jobs(
|
|
138
|
+
self, job_type=None, job_status=None, job_stage=None
|
|
139
|
+
) -> list[Job]:
|
|
140
|
+
"""Gets a list of jobs.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
job_type: Filter by job type.
|
|
144
|
+
job_status: Filter by job status.
|
|
145
|
+
job_stage: Filter by job stage.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
list[Job]: List of jobs.
|
|
149
|
+
"""
|
|
150
|
+
return await self.jobs.list(
|
|
151
|
+
job_type=job_type, job_status=job_status, job_stage=job_stage
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
async def get_job_status(self, job_id: str) -> JobStatus:
|
|
155
|
+
"""Gets the status of a job.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
job_id (str): The ID of the job.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
JobStatus: The status of the job.
|
|
162
|
+
"""
|
|
163
|
+
return await self.jobs.get_status(job_id)
|
|
164
|
+
|
|
165
|
+
async def get_job_stage(self, job_id: str) -> JobStage:
|
|
166
|
+
"""Gets the stage of a job.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
job_id (str): The ID of the job.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
JobStatus: The status of the job.
|
|
173
|
+
"""
|
|
174
|
+
return await self.jobs.get_stage(job_id)
|
|
175
|
+
|
|
176
|
+
async def get_job_error(self, job_id: str) -> str | None:
|
|
177
|
+
"""Gets the error message of a job.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
job_id (str): The ID of the job.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
str | None: The error message of the job, or None if no error.
|
|
184
|
+
"""
|
|
185
|
+
return await self.jobs.get_error(job_id)
|
|
186
|
+
|
|
187
|
+
async def get_job_code_id(self, job_id: str) -> str | None:
|
|
188
|
+
"""Gets the code ID associated with a job.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
job_id (str): The ID of the job.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
str | None: The code ID associated with the job, or None if no code ID.
|
|
195
|
+
"""
|
|
196
|
+
return await self.jobs.get_code_id(job_id)
|
|
197
|
+
|
|
198
|
+
async def get_job_result(
|
|
199
|
+
self, job_id: str, zip_path: str | None = None
|
|
200
|
+
) -> JobResult:
|
|
201
|
+
"""Gets the result of a job.
|
|
202
|
+
|
|
203
|
+
Args:
|
|
204
|
+
job_id (str): The ID of the job.
|
|
205
|
+
zip_path: The path to save the result zip file.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
JobResult: The job result.
|
|
209
|
+
"""
|
|
210
|
+
return await self.jobs.get_result(job_id, zip_path)
|
|
211
|
+
|
|
212
|
+
async def terminate_job(self, job_id: str) -> None:
|
|
213
|
+
"""Terminates a job.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
job_id (str): The ID of the job.
|
|
217
|
+
"""
|
|
218
|
+
return await self.jobs.terminate(job_id)
|
|
219
|
+
|
|
220
|
+
async def stream_job_output(
|
|
221
|
+
self, job_id: str, read_timeout: int = 60
|
|
222
|
+
) -> AsyncGenerator[StreamOutput, None]:
|
|
223
|
+
"""Stream output of a job.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
job_id (str): The ID of the job.
|
|
227
|
+
read_timeout: Read timeout for the stream.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
AsyncGenerator[StreamOutput, None]: Stream output generator.
|
|
231
|
+
"""
|
|
232
|
+
return self.jobs.stream_output(job_id, read_timeout)
|
|
233
|
+
|
|
234
|
+
async def await_job_stage(
|
|
235
|
+
self,
|
|
236
|
+
job_id: str,
|
|
237
|
+
stage: JobStage = JobStage.POST_RUNNING,
|
|
238
|
+
timeout: int | None = None,
|
|
239
|
+
) -> Job:
|
|
240
|
+
"""Waits for a job to reach a specific stage.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
job_id (str): The ID of the job.
|
|
244
|
+
stage: The stage to wait for.
|
|
245
|
+
timeout: Maximum time to wait in seconds.
|
|
246
|
+
|
|
247
|
+
Returns:
|
|
248
|
+
Job: The final job object.
|
|
249
|
+
"""
|
|
250
|
+
return await self.jobs.await_stage(job_id, timeout, stage)
|
|
251
|
+
|
|
252
|
+
async def upload_code(
|
|
253
|
+
self,
|
|
254
|
+
code_zip: CodeZip,
|
|
255
|
+
code_name: str,
|
|
256
|
+
code_type: CodeType,
|
|
257
|
+
metadata: JsonData | dict | None = None,
|
|
258
|
+
) -> str:
|
|
259
|
+
"""Upload code.
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
code_zip (CodeZip): The code zip.
|
|
263
|
+
code_name (str): The name of the code.
|
|
264
|
+
code_type (CodeType): The type of the code.
|
|
265
|
+
metadata (JsonData | dict | None): The JSON metadata of the code.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
str: The code ID.
|
|
269
|
+
"""
|
|
270
|
+
return await self.code.upload(code_zip, code_name, code_type, metadata)
|
|
271
|
+
|
|
272
|
+
async def download_code(self, code_id: str, zip_path: str | None = None) -> CodeZip:
|
|
273
|
+
"""Download code.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
code_id (str): The code ID.
|
|
277
|
+
zip_path: The path to save the code zip file to.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
CodeZip: The downloaded code zip.
|
|
281
|
+
"""
|
|
282
|
+
return await self.code.download(code_id, zip_path)
|
|
283
|
+
|
|
284
|
+
async def get_code_info(self, code_id: str) -> CodeInfo:
|
|
285
|
+
"""Gets the code info.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
code_id (str): The code ID.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
CodeInfo: The code info.
|
|
292
|
+
"""
|
|
293
|
+
return await self.code.get_info(code_id)
|
|
294
|
+
|
|
295
|
+
async def list_code_info(self, code_type: CodeType | None = None) -> list[CodeInfo]:
|
|
296
|
+
"""Gets list of code infos.
|
|
297
|
+
|
|
298
|
+
Args:
|
|
299
|
+
code_type: The type of code to list.
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
list[CodeInfo]: The list of code infos.
|
|
303
|
+
"""
|
|
304
|
+
return await self.code.list_info(code_type)
|
|
305
|
+
|
|
306
|
+
async def delete_code(self, code_id: str) -> str:
|
|
307
|
+
"""Deletes code by code_id.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
code_id (str): The code ID.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
str: Confirmation message.
|
|
314
|
+
"""
|
|
315
|
+
return await self.code.delete(code_id)
|
|
316
|
+
|
|
317
|
+
async def get_code_metadata(self, code_id: str) -> JsonData:
|
|
318
|
+
"""Gets code metadata.
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
code_id (str): The ID of the code.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
JsonData: The metadata.
|
|
325
|
+
"""
|
|
326
|
+
return await self.code.get_metadata(code_id)
|
|
327
|
+
|
|
328
|
+
async def ingest_code(
|
|
329
|
+
self,
|
|
330
|
+
code_zip: CodeZip,
|
|
331
|
+
code_name: str,
|
|
332
|
+
code_type: CodeType,
|
|
333
|
+
metadata: JsonData | dict | None = None,
|
|
334
|
+
build_pexenv: bool = False,
|
|
335
|
+
pexenv_python: str | None = None,
|
|
336
|
+
) -> Job:
|
|
337
|
+
"""Starts a code ingestion job.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
code_zip: The code zip.
|
|
341
|
+
code_name (str): The name of the code.
|
|
342
|
+
code_type: The type of the code.
|
|
343
|
+
metadata: The JSON metadata of the code.
|
|
344
|
+
build_pexenv (bool): Whether to build the pex venv.
|
|
345
|
+
pexenv_python: Python interpreter for the pex venv.
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
Job: The code ingestion job.
|
|
349
|
+
"""
|
|
350
|
+
return await self.code.ingest(
|
|
351
|
+
code_zip, code_name, code_type, metadata, build_pexenv, pexenv_python
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
__all__ = [
|
|
356
|
+
"AsyncClient",
|
|
357
|
+
]
|