trismik 0.9.1__py3-none-any.whl → 0.9.5__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.
- trismik/__init__.py +10 -21
- trismik/_mapper.py +327 -47
- trismik/_utils.py +92 -15
- trismik/adaptive_test.py +671 -0
- trismik/client_async.py +250 -184
- trismik/exceptions.py +57 -6
- trismik/settings.py +15 -0
- trismik/types.py +246 -88
- trismik-0.9.5.dist-info/METADATA +174 -0
- trismik-0.9.5.dist-info/RECORD +12 -0
- {trismik-0.9.1.dist-info → trismik-0.9.5.dist-info}/WHEEL +1 -1
- trismik/client.py +0 -330
- trismik/runner.py +0 -119
- trismik/runner_async.py +0 -121
- trismik-0.9.1.dist-info/METADATA +0 -54
- trismik-0.9.1.dist-info/RECORD +0 -13
- {trismik-0.9.1.dist-info → trismik-0.9.5.dist-info/licenses}/LICENSE +0 -0
trismik/client_async.py
CHANGED
|
@@ -1,338 +1,404 @@
|
|
|
1
|
-
|
|
1
|
+
"""
|
|
2
|
+
Trismik async client for interacting with the Trismik API.
|
|
3
|
+
|
|
4
|
+
This module provides an asynchronous client for interacting with the Trismik
|
|
5
|
+
API. It uses httpx for making HTTP requests.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import List, Optional
|
|
2
9
|
|
|
3
10
|
import httpx
|
|
4
11
|
|
|
5
|
-
from ._mapper import TrismikResponseMapper
|
|
6
|
-
from ._utils import TrismikUtils
|
|
7
|
-
from .exceptions import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
from trismik._mapper import TrismikResponseMapper
|
|
13
|
+
from trismik._utils import TrismikUtils
|
|
14
|
+
from trismik.exceptions import (
|
|
15
|
+
TrismikApiError,
|
|
16
|
+
TrismikPayloadTooLargeError,
|
|
17
|
+
TrismikValidationError,
|
|
18
|
+
)
|
|
19
|
+
from trismik.settings import client_settings, environment_settings
|
|
20
|
+
from trismik.types import (
|
|
21
|
+
TrismikClassicEvalRequest,
|
|
22
|
+
TrismikClassicEvalResponse,
|
|
23
|
+
TrismikDataset,
|
|
24
|
+
TrismikMeResponse,
|
|
25
|
+
TrismikProject,
|
|
26
|
+
TrismikReplayRequest,
|
|
27
|
+
TrismikReplayResponse,
|
|
28
|
+
TrismikRunMetadata,
|
|
29
|
+
TrismikRunResponse,
|
|
30
|
+
TrismikRunSummary,
|
|
16
31
|
)
|
|
17
32
|
|
|
18
33
|
|
|
19
34
|
class TrismikAsyncClient:
|
|
20
|
-
|
|
35
|
+
"""
|
|
36
|
+
Asynchronous client for the Trismik API.
|
|
37
|
+
|
|
38
|
+
This class provides an asynchronous interface to interact with the Trismik
|
|
39
|
+
API, handling authentication, dataset runs, and responses.
|
|
40
|
+
"""
|
|
21
41
|
|
|
22
42
|
def __init__(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
43
|
+
self,
|
|
44
|
+
service_url: Optional[str] = None,
|
|
45
|
+
api_key: Optional[str] = None,
|
|
46
|
+
http_client: Optional[httpx.AsyncClient] = None,
|
|
27
47
|
) -> None:
|
|
28
48
|
"""
|
|
29
|
-
|
|
49
|
+
Initialize the Trismik async client.
|
|
30
50
|
|
|
31
51
|
Args:
|
|
32
52
|
service_url (Optional[str]): URL of the Trismik service.
|
|
33
53
|
api_key (Optional[str]): API key for the Trismik service.
|
|
34
|
-
http_client (Optional[httpx.
|
|
54
|
+
http_client (Optional[httpx.AsyncClient]): HTTP client to use for
|
|
55
|
+
requests.
|
|
35
56
|
|
|
36
57
|
Raises:
|
|
37
|
-
TrismikError: If service_url or api_key are not provided and not
|
|
58
|
+
TrismikError: If service_url or api_key are not provided and not
|
|
59
|
+
found in environment.
|
|
38
60
|
TrismikApiError: If API request fails.
|
|
39
61
|
"""
|
|
40
62
|
self._service_url = TrismikUtils.option(
|
|
41
|
-
|
|
63
|
+
service_url,
|
|
64
|
+
client_settings["endpoint"],
|
|
65
|
+
environment_settings["trismik_service_url"],
|
|
42
66
|
)
|
|
43
67
|
self._api_key = TrismikUtils.required_option(
|
|
44
|
-
|
|
68
|
+
api_key, "api_key", environment_settings["trismik_api_key"]
|
|
45
69
|
)
|
|
46
|
-
self._http_client = http_client or httpx.AsyncClient(
|
|
47
|
-
base_url=self._service_url)
|
|
48
|
-
|
|
49
|
-
async def authenticate(self) -> TrismikAuth:
|
|
50
|
-
"""
|
|
51
|
-
Authenticates with the Trismik service.
|
|
52
70
|
|
|
53
|
-
|
|
54
|
-
|
|
71
|
+
# Set default headers with API key
|
|
72
|
+
default_headers = {"x-api-key": self._api_key}
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
url = "/client/auth"
|
|
61
|
-
body = {"apiKey": self._api_key}
|
|
62
|
-
response = await self._http_client.post(url, json=body)
|
|
63
|
-
response.raise_for_status()
|
|
64
|
-
json = response.json()
|
|
65
|
-
return TrismikResponseMapper.to_auth(json)
|
|
66
|
-
except httpx.HTTPStatusError as e:
|
|
67
|
-
raise TrismikApiError(
|
|
68
|
-
TrismikUtils.get_error_message(e.response)) from e
|
|
69
|
-
except httpx.HTTPError as e:
|
|
70
|
-
raise TrismikApiError(str(e)) from e
|
|
74
|
+
self._http_client = http_client or httpx.AsyncClient(
|
|
75
|
+
base_url=self._service_url, headers=default_headers
|
|
76
|
+
)
|
|
71
77
|
|
|
72
|
-
|
|
78
|
+
def _handle_http_error(self, e: httpx.HTTPStatusError) -> Exception:
|
|
73
79
|
"""
|
|
74
|
-
|
|
80
|
+
Handle HTTP errors and return appropriate Trismik exceptions.
|
|
75
81
|
|
|
76
82
|
Args:
|
|
77
|
-
|
|
83
|
+
e (httpx.HTTPStatusError): The HTTP status error to handle.
|
|
78
84
|
|
|
79
85
|
Returns:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
Raises:
|
|
83
|
-
TrismikApiError: If API request fails.
|
|
86
|
+
Exception: The appropriate Trismik exception to raise.
|
|
84
87
|
"""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
if e.response.status_code == 413:
|
|
89
|
+
# Handle payload too large error specifically
|
|
90
|
+
try:
|
|
91
|
+
backend_message = e.response.json().get(
|
|
92
|
+
"detail", "Payload too large."
|
|
93
|
+
)
|
|
94
|
+
except Exception:
|
|
95
|
+
backend_message = "Payload too large."
|
|
96
|
+
return TrismikPayloadTooLargeError(backend_message)
|
|
97
|
+
elif e.response.status_code == 422:
|
|
98
|
+
# Handle validation error specifically
|
|
99
|
+
try:
|
|
100
|
+
backend_message = e.response.json().get(
|
|
101
|
+
"detail", "Validation failed."
|
|
102
|
+
)
|
|
103
|
+
except Exception:
|
|
104
|
+
backend_message = "Validation failed."
|
|
105
|
+
return TrismikValidationError(backend_message)
|
|
106
|
+
else:
|
|
107
|
+
return TrismikApiError(TrismikUtils.get_error_message(e.response))
|
|
108
|
+
|
|
109
|
+
async def list_datasets(self) -> List[TrismikDataset]:
|
|
99
110
|
"""
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
Args:
|
|
103
|
-
token (str): Authentication token.
|
|
111
|
+
Get a list of available datasets.
|
|
104
112
|
|
|
105
113
|
Returns:
|
|
106
|
-
List[
|
|
114
|
+
List[TrismikDataset]: List of available datasets.
|
|
107
115
|
|
|
108
116
|
Raises:
|
|
109
117
|
TrismikApiError: If API request fails.
|
|
110
118
|
"""
|
|
111
119
|
try:
|
|
112
|
-
url = "/
|
|
113
|
-
|
|
114
|
-
response = await self._http_client.get(url, headers=headers)
|
|
120
|
+
url = "/datasets"
|
|
121
|
+
response = await self._http_client.get(url)
|
|
115
122
|
response.raise_for_status()
|
|
116
123
|
json = response.json()
|
|
117
|
-
return TrismikResponseMapper.
|
|
124
|
+
return TrismikResponseMapper.to_datasets(json)
|
|
118
125
|
except httpx.HTTPStatusError as e:
|
|
119
126
|
raise TrismikApiError(
|
|
120
|
-
|
|
127
|
+
TrismikUtils.get_error_message(e.response)
|
|
128
|
+
) from e
|
|
121
129
|
except httpx.HTTPError as e:
|
|
122
130
|
raise TrismikApiError(str(e)) from e
|
|
123
131
|
|
|
124
|
-
async def
|
|
132
|
+
async def start_run(
|
|
133
|
+
self,
|
|
134
|
+
dataset_id: str,
|
|
135
|
+
project_id: str,
|
|
136
|
+
experiment: str,
|
|
137
|
+
metadata: Optional[TrismikRunMetadata] = None,
|
|
138
|
+
) -> TrismikRunResponse:
|
|
125
139
|
"""
|
|
126
|
-
|
|
140
|
+
Start a new run for a dataset and get the first item.
|
|
127
141
|
|
|
128
142
|
Args:
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
dataset_id (str): ID of the dataset.
|
|
144
|
+
project_id (str): ID of the project.
|
|
145
|
+
experiment (str): Name of the experiment.
|
|
146
|
+
metadata (Optional[TrismikRunMetadata]): Run metadata.
|
|
131
147
|
|
|
132
148
|
Returns:
|
|
133
|
-
|
|
149
|
+
TrismikRunResponse: Run response.
|
|
134
150
|
|
|
135
151
|
Raises:
|
|
152
|
+
TrismikPayloadTooLargeError: If the request payload exceeds the
|
|
153
|
+
server's size limit.
|
|
136
154
|
TrismikApiError: If API request fails.
|
|
137
155
|
"""
|
|
138
156
|
try:
|
|
139
|
-
url = "/
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
157
|
+
url = "/runs/start"
|
|
158
|
+
body = {
|
|
159
|
+
"datasetId": dataset_id,
|
|
160
|
+
"projectId": project_id,
|
|
161
|
+
"experiment": experiment,
|
|
162
|
+
"metadata": metadata.toDict() if metadata else {},
|
|
163
|
+
}
|
|
164
|
+
response = await self._http_client.post(url, json=body)
|
|
144
165
|
response.raise_for_status()
|
|
145
166
|
json = response.json()
|
|
146
|
-
return TrismikResponseMapper.
|
|
167
|
+
return TrismikResponseMapper.to_run_response(json)
|
|
147
168
|
except httpx.HTTPStatusError as e:
|
|
148
|
-
raise
|
|
149
|
-
TrismikUtils.get_error_message(e.response)) from e
|
|
169
|
+
raise self._handle_http_error(e) from e
|
|
150
170
|
except httpx.HTTPError as e:
|
|
151
171
|
raise TrismikApiError(str(e)) from e
|
|
152
|
-
|
|
153
|
-
async def
|
|
172
|
+
|
|
173
|
+
async def continue_run(
|
|
174
|
+
self, run_id: str, item_choice_id: str
|
|
175
|
+
) -> TrismikRunResponse:
|
|
154
176
|
"""
|
|
155
|
-
|
|
177
|
+
Continue a run: respond to the current item and get the next one.
|
|
156
178
|
|
|
157
179
|
Args:
|
|
158
|
-
|
|
159
|
-
|
|
180
|
+
run_id (str): ID of the run.
|
|
181
|
+
item_choice_id (str): ID of the chosen item response.
|
|
160
182
|
|
|
161
183
|
Returns:
|
|
162
|
-
|
|
184
|
+
TrismikRunResponse: Run response.
|
|
163
185
|
|
|
164
186
|
Raises:
|
|
165
187
|
TrismikApiError: If API request fails.
|
|
166
188
|
"""
|
|
167
189
|
try:
|
|
168
|
-
url = "/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
response = await self._http_client.post(url, headers=headers,
|
|
172
|
-
json=body)
|
|
190
|
+
url = "/runs/continue"
|
|
191
|
+
body = {"itemChoiceId": item_choice_id, "runId": run_id}
|
|
192
|
+
response = await self._http_client.post(url, json=body)
|
|
173
193
|
response.raise_for_status()
|
|
174
194
|
json = response.json()
|
|
175
|
-
return TrismikResponseMapper.
|
|
195
|
+
return TrismikResponseMapper.to_run_response(json)
|
|
176
196
|
except httpx.HTTPStatusError as e:
|
|
177
197
|
raise TrismikApiError(
|
|
178
|
-
|
|
198
|
+
TrismikUtils.get_error_message(e.response)
|
|
199
|
+
) from e
|
|
179
200
|
except httpx.HTTPError as e:
|
|
180
201
|
raise TrismikApiError(str(e)) from e
|
|
181
|
-
|
|
182
|
-
async def
|
|
202
|
+
|
|
203
|
+
async def run_summary(self, run_id: str) -> TrismikRunSummary:
|
|
183
204
|
"""
|
|
184
|
-
|
|
205
|
+
Get run summary including responses, dataset, and state.
|
|
185
206
|
|
|
186
207
|
Args:
|
|
187
|
-
|
|
188
|
-
metadata: object cotaining the metadata to add
|
|
189
|
-
token (str): Authentication token.
|
|
208
|
+
run_id (str): ID of the run.
|
|
190
209
|
|
|
191
210
|
Returns:
|
|
192
|
-
|
|
211
|
+
TrismikRunSummary: Complete run summary with responses,
|
|
212
|
+
dataset, state, and metadata.
|
|
193
213
|
|
|
194
214
|
Raises:
|
|
195
215
|
TrismikApiError: If API request fails.
|
|
196
|
-
"""
|
|
216
|
+
"""
|
|
197
217
|
try:
|
|
198
|
-
url = f"/
|
|
199
|
-
|
|
200
|
-
body = metadata.toDict()
|
|
201
|
-
response = await self._http_client.post(url, headers=headers,
|
|
202
|
-
json=body)
|
|
218
|
+
url = f"/runs/{run_id}"
|
|
219
|
+
response = await self._http_client.get(url)
|
|
203
220
|
response.raise_for_status()
|
|
221
|
+
json = response.json()
|
|
222
|
+
return TrismikResponseMapper.to_run_summary(json)
|
|
204
223
|
except httpx.HTTPStatusError as e:
|
|
205
224
|
raise TrismikApiError(
|
|
206
|
-
|
|
225
|
+
TrismikUtils.get_error_message(e.response)
|
|
226
|
+
) from e
|
|
207
227
|
except httpx.HTTPError as e:
|
|
208
228
|
raise TrismikApiError(str(e)) from e
|
|
209
229
|
|
|
210
|
-
async def
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
async def submit_replay(
|
|
231
|
+
self,
|
|
232
|
+
run_id: str,
|
|
233
|
+
replay_request: TrismikReplayRequest,
|
|
234
|
+
metadata: Optional[TrismikRunMetadata] = None,
|
|
235
|
+
) -> TrismikReplayResponse:
|
|
215
236
|
"""
|
|
216
|
-
|
|
237
|
+
Submit a replay of a run with specific responses.
|
|
217
238
|
|
|
218
239
|
Args:
|
|
219
|
-
|
|
220
|
-
|
|
240
|
+
run_id (str): ID of the run to replay.
|
|
241
|
+
replay_request (TrismikReplayRequest): Request containing responses
|
|
242
|
+
to submit.
|
|
243
|
+
metadata (Optional[TrismikRunMetadata]): Run metadata.
|
|
221
244
|
|
|
222
245
|
Returns:
|
|
223
|
-
|
|
246
|
+
TrismikReplayResponse: Response from the replay endpoint.
|
|
224
247
|
|
|
225
248
|
Raises:
|
|
249
|
+
TrismikPayloadTooLargeError: If the request payload exceeds the
|
|
250
|
+
server's size limit.
|
|
251
|
+
TrismikValidationError: If the request fails validation (e.g.,
|
|
252
|
+
duplicate item IDs, unknown item IDs).
|
|
226
253
|
TrismikApiError: If API request fails.
|
|
227
254
|
"""
|
|
228
255
|
try:
|
|
229
|
-
url = f"{
|
|
230
|
-
|
|
231
|
-
|
|
256
|
+
url = f"runs/{run_id}/replay"
|
|
257
|
+
|
|
258
|
+
# Convert TrismikReplayRequestItem objects to dictionaries
|
|
259
|
+
responses_dict = [
|
|
260
|
+
{"itemId": item.itemId, "itemChoiceId": item.itemChoiceId}
|
|
261
|
+
for item in replay_request.responses
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
body = {
|
|
265
|
+
"responses": responses_dict,
|
|
266
|
+
"metadata": metadata.toDict() if metadata else {},
|
|
267
|
+
}
|
|
268
|
+
response = await self._http_client.post(url, json=body)
|
|
232
269
|
response.raise_for_status()
|
|
233
270
|
json = response.json()
|
|
234
|
-
return TrismikResponseMapper.
|
|
271
|
+
return TrismikResponseMapper.to_replay_response(json)
|
|
235
272
|
except httpx.HTTPStatusError as e:
|
|
236
|
-
raise
|
|
237
|
-
TrismikUtils.get_error_message(e.response)) from e
|
|
273
|
+
raise self._handle_http_error(e) from e
|
|
238
274
|
except httpx.HTTPError as e:
|
|
239
275
|
raise TrismikApiError(str(e)) from e
|
|
240
276
|
|
|
241
|
-
async def
|
|
242
|
-
self,
|
|
243
|
-
session_url: str,
|
|
244
|
-
value: Any,
|
|
245
|
-
token: str
|
|
246
|
-
) -> TrismikItem | None:
|
|
277
|
+
async def me(self) -> TrismikMeResponse:
|
|
247
278
|
"""
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
Args:
|
|
251
|
-
session_url (str): URL of the session.
|
|
252
|
-
value (Any): Response value.
|
|
253
|
-
token (str): Authentication token.
|
|
279
|
+
Get current user information.
|
|
254
280
|
|
|
255
281
|
Returns:
|
|
256
|
-
|
|
282
|
+
TrismikMeResponse: User information including validity and payload.
|
|
257
283
|
|
|
258
284
|
Raises:
|
|
259
285
|
TrismikApiError: If API request fails.
|
|
260
286
|
"""
|
|
261
287
|
try:
|
|
262
|
-
url =
|
|
263
|
-
|
|
264
|
-
headers = {"Authorization": f"Bearer {token}"}
|
|
265
|
-
response = await self._http_client.post(
|
|
266
|
-
url, headers=headers, json=body
|
|
267
|
-
)
|
|
288
|
+
url = "../admin/api-keys/me"
|
|
289
|
+
response = await self._http_client.get(url)
|
|
268
290
|
response.raise_for_status()
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
else:
|
|
272
|
-
json = response.json()
|
|
273
|
-
return TrismikResponseMapper.to_item(json)
|
|
291
|
+
json = response.json()
|
|
292
|
+
return TrismikResponseMapper.to_me_response(json)
|
|
274
293
|
except httpx.HTTPStatusError as e:
|
|
275
294
|
raise TrismikApiError(
|
|
276
|
-
|
|
295
|
+
TrismikUtils.get_error_message(e.response)
|
|
296
|
+
) from e
|
|
277
297
|
except httpx.HTTPError as e:
|
|
278
298
|
raise TrismikApiError(str(e)) from e
|
|
279
299
|
|
|
280
|
-
async def
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
) -> List[TrismikResult]:
|
|
300
|
+
async def submit_classic_eval(
|
|
301
|
+
self, classic_eval_request: TrismikClassicEvalRequest
|
|
302
|
+
) -> TrismikClassicEvalResponse:
|
|
284
303
|
"""
|
|
285
|
-
|
|
304
|
+
Submit a classic evaluation run with pre-computed results.
|
|
286
305
|
|
|
287
306
|
Args:
|
|
288
|
-
|
|
289
|
-
|
|
307
|
+
classic_eval_request (TrismikClassicEvalRequest): Request containing
|
|
308
|
+
project info, dataset, model outputs, and metrics.
|
|
290
309
|
|
|
291
310
|
Returns:
|
|
292
|
-
|
|
311
|
+
TrismikClassicEvalResponse: Response from the classic evaluation
|
|
312
|
+
endpoint.
|
|
293
313
|
|
|
294
314
|
Raises:
|
|
315
|
+
TrismikPayloadTooLargeError: If the request payload exceeds the
|
|
316
|
+
server's size limit.
|
|
317
|
+
TrismikValidationError: If the request fails validation.
|
|
295
318
|
TrismikApiError: If API request fails.
|
|
296
319
|
"""
|
|
297
320
|
try:
|
|
298
|
-
url =
|
|
299
|
-
|
|
300
|
-
|
|
321
|
+
url = "/runs/classic"
|
|
322
|
+
|
|
323
|
+
# Convert request object to dictionary
|
|
324
|
+
items_dict = [
|
|
325
|
+
{
|
|
326
|
+
"datasetItemId": item.datasetItemId,
|
|
327
|
+
"modelInput": item.modelInput,
|
|
328
|
+
"modelOutput": item.modelOutput,
|
|
329
|
+
"goldOutput": item.goldOutput,
|
|
330
|
+
"metrics": item.metrics,
|
|
331
|
+
}
|
|
332
|
+
for item in classic_eval_request.items
|
|
333
|
+
]
|
|
334
|
+
|
|
335
|
+
metrics_dict = [
|
|
336
|
+
{
|
|
337
|
+
"metricId": metric.metricId,
|
|
338
|
+
"valueType": TrismikUtils.metric_value_to_type(
|
|
339
|
+
metric.value
|
|
340
|
+
),
|
|
341
|
+
"value": metric.value,
|
|
342
|
+
}
|
|
343
|
+
for metric in classic_eval_request.metrics
|
|
344
|
+
]
|
|
345
|
+
|
|
346
|
+
body = {
|
|
347
|
+
"projectId": classic_eval_request.projectId,
|
|
348
|
+
"experimentName": classic_eval_request.experimentName,
|
|
349
|
+
"datasetId": classic_eval_request.datasetId,
|
|
350
|
+
"modelName": classic_eval_request.modelName,
|
|
351
|
+
"hyperparameters": classic_eval_request.hyperparameters,
|
|
352
|
+
"items": items_dict,
|
|
353
|
+
"metrics": metrics_dict,
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
response = await self._http_client.post(url, json=body)
|
|
301
357
|
response.raise_for_status()
|
|
302
358
|
json = response.json()
|
|
303
|
-
return TrismikResponseMapper.
|
|
359
|
+
return TrismikResponseMapper.to_classic_eval_response(json)
|
|
304
360
|
except httpx.HTTPStatusError as e:
|
|
305
|
-
raise
|
|
306
|
-
TrismikUtils.get_error_message(e.response)) from e
|
|
361
|
+
raise self._handle_http_error(e) from e
|
|
307
362
|
except httpx.HTTPError as e:
|
|
308
363
|
raise TrismikApiError(str(e)) from e
|
|
309
364
|
|
|
310
|
-
async def
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
365
|
+
async def create_project(
|
|
366
|
+
self,
|
|
367
|
+
name: str,
|
|
368
|
+
organization_id: str,
|
|
369
|
+
description: Optional[str] = None,
|
|
370
|
+
) -> TrismikProject:
|
|
314
371
|
"""
|
|
315
|
-
|
|
372
|
+
Create a new project.
|
|
316
373
|
|
|
317
374
|
Args:
|
|
318
|
-
|
|
319
|
-
|
|
375
|
+
name (str): Name of the project.
|
|
376
|
+
organization_id (str): ID of the organization to create the
|
|
377
|
+
project in.
|
|
378
|
+
description (Optional[str]): Optional description of the project.
|
|
320
379
|
|
|
321
380
|
Returns:
|
|
322
|
-
|
|
381
|
+
TrismikProject: Created project information.
|
|
323
382
|
|
|
324
383
|
Raises:
|
|
384
|
+
TrismikValidationError: If the request fails validation.
|
|
325
385
|
TrismikApiError: If API request fails.
|
|
326
386
|
"""
|
|
327
387
|
try:
|
|
328
|
-
url =
|
|
329
|
-
|
|
330
|
-
|
|
388
|
+
url = "../admin/public/projects"
|
|
389
|
+
|
|
390
|
+
body = {"name": name}
|
|
391
|
+
if description is not None:
|
|
392
|
+
body["description"] = description
|
|
393
|
+
|
|
394
|
+
headers = {"x-organization-id": organization_id}
|
|
395
|
+
response = await self._http_client.post(
|
|
396
|
+
url, json=body, headers=headers
|
|
397
|
+
)
|
|
331
398
|
response.raise_for_status()
|
|
332
399
|
json = response.json()
|
|
333
|
-
return TrismikResponseMapper.
|
|
400
|
+
return TrismikResponseMapper.to_project(json)
|
|
334
401
|
except httpx.HTTPStatusError as e:
|
|
335
|
-
raise
|
|
336
|
-
TrismikUtils.get_error_message(e.response)) from e
|
|
402
|
+
raise self._handle_http_error(e) from e
|
|
337
403
|
except httpx.HTTPError as e:
|
|
338
404
|
raise TrismikApiError(str(e)) from e
|
trismik/exceptions.py
CHANGED
|
@@ -1,13 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Exception classes for the Trismik client.
|
|
3
|
+
|
|
4
|
+
This module defines custom exceptions used throughout the Trismik client
|
|
5
|
+
library.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
1
9
|
class TrismikError(Exception):
|
|
10
|
+
"""Base class for all exceptions raised by the Trismik package."""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TrismikApiError(TrismikError):
|
|
2
14
|
"""
|
|
3
|
-
|
|
4
|
-
|
|
15
|
+
Exception raised when an error occurs during API interaction.
|
|
16
|
+
|
|
17
|
+
This exception is raised when there is an error during API communication.
|
|
5
18
|
"""
|
|
6
|
-
pass
|
|
7
19
|
|
|
8
20
|
|
|
9
|
-
class TrismikApiError
|
|
21
|
+
class TrismikPayloadTooLargeError(TrismikApiError):
|
|
22
|
+
"""
|
|
23
|
+
Exception raised when the request payload exceeds the server's size limit.
|
|
24
|
+
|
|
25
|
+
This exception is raised when a 413 "Content Too Large" error is received
|
|
26
|
+
from the API, indicating that the request payload (typically metadata)
|
|
27
|
+
exceeds the server's size limit.
|
|
10
28
|
"""
|
|
11
|
-
|
|
29
|
+
|
|
30
|
+
def __init__(self, message: str):
|
|
31
|
+
"""
|
|
32
|
+
Initialize the TrismikPayloadTooLargeError.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
message (str): The error message from the server.
|
|
36
|
+
"""
|
|
37
|
+
super().__init__(message)
|
|
38
|
+
|
|
39
|
+
def __str__(self) -> str:
|
|
40
|
+
"""Return a human-readable string representation of the exception."""
|
|
41
|
+
return f"Payload too large: {self.args[0]}"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class TrismikValidationError(TrismikApiError):
|
|
12
45
|
"""
|
|
13
|
-
|
|
46
|
+
Exception raised when the request fails validation.
|
|
47
|
+
|
|
48
|
+
This exception is raised when a 422 "Unprocessable Entity" error is received
|
|
49
|
+
from the API, indicating that the request failed validation (e.g., duplicate
|
|
50
|
+
item IDs, unknown item IDs in replay requests).
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, message: str):
|
|
54
|
+
"""
|
|
55
|
+
Initialize the TrismikValidationError.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
message (str): The error message from the server.
|
|
59
|
+
"""
|
|
60
|
+
super().__init__(message)
|
|
61
|
+
|
|
62
|
+
def __str__(self) -> str:
|
|
63
|
+
"""Return a human-readable string representation of the exception."""
|
|
64
|
+
return f"Validation error: {self.args[0]}"
|