fleet-python 0.2.42__py3-none-any.whl → 0.2.43__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.
Potentially problematic release.
This version of fleet-python might be problematic. Click here for more details.
- fleet/_async/client.py +118 -54
- fleet/_async/env/client.py +9 -2
- fleet/_async/tasks.py +30 -41
- fleet/client.py +120 -48
- fleet/env/client.py +9 -2
- fleet/models.py +3 -1
- fleet/tasks.py +45 -46
- {fleet_python-0.2.42.dist-info → fleet_python-0.2.43.dist-info}/METADATA +1 -1
- {fleet_python-0.2.42.dist-info → fleet_python-0.2.43.dist-info}/RECORD +12 -12
- {fleet_python-0.2.42.dist-info → fleet_python-0.2.43.dist-info}/WHEEL +0 -0
- {fleet_python-0.2.42.dist-info → fleet_python-0.2.43.dist-info}/licenses/LICENSE +0 -0
- {fleet_python-0.2.42.dist-info → fleet_python-0.2.43.dist-info}/top_level.txt +0 -0
fleet/_async/client.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
"""Fleet API Client for making HTTP requests to Fleet services."""
|
|
16
16
|
|
|
17
|
+
import asyncio
|
|
17
18
|
import base64
|
|
18
19
|
import cloudpickle
|
|
19
20
|
import httpx
|
|
@@ -206,24 +207,39 @@ class AsyncFleet:
|
|
|
206
207
|
async def make(
|
|
207
208
|
self,
|
|
208
209
|
env_key: str,
|
|
210
|
+
data_key: Optional[str] = None,
|
|
209
211
|
region: Optional[str] = None,
|
|
210
212
|
env_variables: Optional[Dict[str, Any]] = None,
|
|
211
213
|
) -> AsyncEnv:
|
|
212
214
|
if ":" in env_key:
|
|
213
|
-
env_key_part,
|
|
215
|
+
env_key_part, env_version = env_key.split(":", 1)
|
|
214
216
|
if (
|
|
215
|
-
not
|
|
216
|
-
and len(
|
|
217
|
-
and
|
|
217
|
+
not env_version.startswith("v")
|
|
218
|
+
and len(env_version) != 0
|
|
219
|
+
and env_version[0].isdigit()
|
|
218
220
|
):
|
|
219
|
-
|
|
221
|
+
env_version = f"v{env_version}"
|
|
220
222
|
else:
|
|
221
223
|
env_key_part = env_key
|
|
222
|
-
|
|
224
|
+
env_version = None
|
|
225
|
+
|
|
226
|
+
if data_key is not None and ":" in data_key:
|
|
227
|
+
data_key_part, data_version = data_key.split(":", 1)
|
|
228
|
+
if (
|
|
229
|
+
not data_version.startswith("v")
|
|
230
|
+
and len(data_version) != 0
|
|
231
|
+
and data_version[0].isdigit()
|
|
232
|
+
):
|
|
233
|
+
data_version = f"v{data_version}"
|
|
234
|
+
else:
|
|
235
|
+
data_key_part = data_key
|
|
236
|
+
data_version = None
|
|
223
237
|
|
|
224
238
|
request = InstanceRequest(
|
|
225
239
|
env_key=env_key_part,
|
|
226
|
-
|
|
240
|
+
env_version=env_version,
|
|
241
|
+
data_key=data_key_part,
|
|
242
|
+
data_version=data_version,
|
|
227
243
|
region=region,
|
|
228
244
|
env_variables=env_variables,
|
|
229
245
|
created_from="sdk",
|
|
@@ -286,7 +302,7 @@ class AsyncFleet:
|
|
|
286
302
|
with open(filename, "r", encoding="utf-8") as f:
|
|
287
303
|
tasks_data = f.read()
|
|
288
304
|
|
|
289
|
-
return self.load_task_array_from_string(tasks_data)
|
|
305
|
+
return await self.load_task_array_from_string(tasks_data)
|
|
290
306
|
|
|
291
307
|
async def load_task_array_from_string(
|
|
292
308
|
self, serialized_tasks: List[Dict]
|
|
@@ -295,18 +311,19 @@ class AsyncFleet:
|
|
|
295
311
|
|
|
296
312
|
json_tasks = json.loads(serialized_tasks)
|
|
297
313
|
for json_task in json_tasks:
|
|
298
|
-
parsed_task = self.load_task_from_json(json_task)
|
|
314
|
+
parsed_task = await self.load_task_from_json(json_task)
|
|
299
315
|
tasks.append(parsed_task)
|
|
300
316
|
return tasks
|
|
301
317
|
|
|
302
318
|
async def load_task_from_string(self, task_string: str) -> Task:
|
|
303
319
|
task_json = json.loads(task_string)
|
|
304
|
-
return self.load_task_from_json(task_json)
|
|
320
|
+
return await self.load_task_from_json(task_json)
|
|
305
321
|
|
|
306
322
|
async def load_task_from_json(self, task_json: Dict) -> Task:
|
|
323
|
+
verifier = None
|
|
307
324
|
try:
|
|
308
325
|
if "verifier_id" in task_json and task_json["verifier_id"]:
|
|
309
|
-
verifier = self._create_verifier_from_data(
|
|
326
|
+
verifier = await self._create_verifier_from_data(
|
|
310
327
|
verifier_id=task_json["verifier_id"],
|
|
311
328
|
verifier_key=task_json["key"],
|
|
312
329
|
verifier_code=task_json["verifier_func"],
|
|
@@ -357,48 +374,99 @@ class AsyncFleet:
|
|
|
357
374
|
response = await self.client.request("GET", "/v1/tasks", params=params)
|
|
358
375
|
task_list_response = TaskListResponse(**response.json())
|
|
359
376
|
|
|
360
|
-
#
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
verifier = None
|
|
365
|
-
verifier_func = task_response.verifier_func
|
|
377
|
+
# Prepare verifier loading coroutines with concurrency limit
|
|
378
|
+
verifier_coroutines = []
|
|
379
|
+
task_responses_with_indices = []
|
|
380
|
+
semaphore = asyncio.Semaphore(10) # Limit to 10 concurrent operations
|
|
366
381
|
|
|
382
|
+
for idx, task_response in enumerate(task_list_response.tasks):
|
|
367
383
|
if task_response.verifier:
|
|
368
384
|
embedded_code = task_response.verifier.code or ""
|
|
369
385
|
is_embedded_error = embedded_code.strip().startswith(
|
|
370
386
|
"<error loading code:"
|
|
371
387
|
)
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
388
|
+
|
|
389
|
+
async def create_verifier_with_fallback(tr, emb_code, is_error):
|
|
390
|
+
"""Create verifier with fallback logic."""
|
|
391
|
+
async with semaphore: # Acquire semaphore before operation
|
|
392
|
+
if not is_error:
|
|
393
|
+
# Try to create from embedded data
|
|
394
|
+
try:
|
|
395
|
+
return await self._create_verifier_from_data(
|
|
396
|
+
verifier_id=tr.verifier.verifier_id,
|
|
397
|
+
verifier_key=tr.verifier.key,
|
|
398
|
+
verifier_code=emb_code,
|
|
399
|
+
verifier_sha=tr.verifier.sha256,
|
|
400
|
+
)
|
|
401
|
+
except Exception as e:
|
|
402
|
+
logger.warning(
|
|
403
|
+
f"Failed to create verifier {tr.verifier.key}: {e}"
|
|
404
|
+
)
|
|
405
|
+
return None
|
|
406
|
+
else:
|
|
407
|
+
# Fallback: try fetching by ID
|
|
408
|
+
try:
|
|
409
|
+
logger.warning(
|
|
410
|
+
f"Embedded verifier code missing for {tr.verifier.key} (NoSuchKey). "
|
|
411
|
+
f"Attempting to refetch by id {tr.verifier.verifier_id}"
|
|
412
|
+
)
|
|
413
|
+
return await self._load_verifier(
|
|
414
|
+
tr.verifier.verifier_id
|
|
415
|
+
)
|
|
416
|
+
except Exception as e:
|
|
417
|
+
logger.warning(
|
|
418
|
+
f"Refetch by verifier id failed for {tr.verifier.key}: {e}. "
|
|
419
|
+
"Leaving verifier unset."
|
|
420
|
+
)
|
|
421
|
+
return None
|
|
422
|
+
|
|
423
|
+
# Add the coroutine for parallel execution
|
|
424
|
+
verifier_coroutines.append(
|
|
425
|
+
create_verifier_with_fallback(
|
|
426
|
+
task_response, embedded_code, is_embedded_error
|
|
427
|
+
)
|
|
428
|
+
)
|
|
429
|
+
task_responses_with_indices.append((idx, task_response))
|
|
430
|
+
else:
|
|
431
|
+
# No verifier needed
|
|
432
|
+
verifier_coroutines.append(None)
|
|
433
|
+
task_responses_with_indices.append((idx, task_response))
|
|
434
|
+
|
|
435
|
+
# Execute all verifier loading in parallel
|
|
436
|
+
if verifier_coroutines:
|
|
437
|
+
verifier_results = await asyncio.gather(
|
|
438
|
+
*[
|
|
439
|
+
coro if coro is not None else asyncio.sleep(0)
|
|
440
|
+
for coro in verifier_coroutines
|
|
441
|
+
],
|
|
442
|
+
return_exceptions=True,
|
|
443
|
+
)
|
|
444
|
+
else:
|
|
445
|
+
verifier_results = []
|
|
446
|
+
|
|
447
|
+
# Build tasks with results
|
|
448
|
+
tasks = []
|
|
449
|
+
for (idx, task_response), verifier_result in zip(
|
|
450
|
+
task_responses_with_indices, verifier_results
|
|
451
|
+
):
|
|
452
|
+
# Handle verifier result
|
|
453
|
+
verifier = None
|
|
454
|
+
verifier_func = task_response.verifier_func
|
|
455
|
+
|
|
456
|
+
if task_response.verifier:
|
|
457
|
+
# Process verifier result
|
|
458
|
+
if isinstance(verifier_result, Exception):
|
|
459
|
+
logger.warning(
|
|
460
|
+
f"Verifier loading failed for {task_response.key}: {verifier_result}"
|
|
461
|
+
)
|
|
462
|
+
elif verifier_result is not None:
|
|
463
|
+
verifier = verifier_result
|
|
464
|
+
embedded_code = task_response.verifier.code or ""
|
|
465
|
+
is_embedded_error = embedded_code.strip().startswith(
|
|
466
|
+
"<error loading code:"
|
|
467
|
+
)
|
|
468
|
+
if not is_embedded_error:
|
|
469
|
+
verifier_func = embedded_code
|
|
402
470
|
|
|
403
471
|
task = Task(
|
|
404
472
|
key=task_response.key,
|
|
@@ -507,7 +575,7 @@ class AsyncFleet:
|
|
|
507
575
|
self,
|
|
508
576
|
task_key: str,
|
|
509
577
|
prompt: Optional[str] = None,
|
|
510
|
-
verifier_code: Optional[str] = None
|
|
578
|
+
verifier_code: Optional[str] = None,
|
|
511
579
|
) -> TaskResponse:
|
|
512
580
|
"""Update an existing task.
|
|
513
581
|
|
|
@@ -519,10 +587,7 @@ class AsyncFleet:
|
|
|
519
587
|
Returns:
|
|
520
588
|
TaskResponse containing the updated task details
|
|
521
589
|
"""
|
|
522
|
-
payload = TaskUpdateRequest(
|
|
523
|
-
prompt=prompt,
|
|
524
|
-
verifier_code=verifier_code
|
|
525
|
-
)
|
|
590
|
+
payload = TaskUpdateRequest(prompt=prompt, verifier_code=verifier_code)
|
|
526
591
|
response = await self.client.request(
|
|
527
592
|
"PUT", f"/v1/tasks/{task_key}", json=payload.model_dump(exclude_none=True)
|
|
528
593
|
)
|
|
@@ -542,8 +607,7 @@ class AsyncFleet:
|
|
|
542
607
|
Returns:
|
|
543
608
|
AsyncVerifierFunction created from the verifier code
|
|
544
609
|
"""
|
|
545
|
-
from
|
|
546
|
-
from .verifiers.verifier import AsyncVerifierFunction
|
|
610
|
+
from .tasks import verifier_from_string
|
|
547
611
|
|
|
548
612
|
# Use verifier_from_string to create the verifier
|
|
549
613
|
verifier_func = verifier_from_string(
|
fleet/_async/env/client.py
CHANGED
|
@@ -3,8 +3,15 @@ from ...models import Environment as EnvironmentModel, AccountResponse
|
|
|
3
3
|
from typing import List, Optional, Dict, Any
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
async def make_async(
|
|
7
|
-
|
|
6
|
+
async def make_async(
|
|
7
|
+
env_key: str,
|
|
8
|
+
data_key: Optional[str] = None,
|
|
9
|
+
region: Optional[str] = None,
|
|
10
|
+
env_variables: Optional[Dict[str, Any]] = None,
|
|
11
|
+
) -> AsyncEnv:
|
|
12
|
+
return await AsyncFleet().make(
|
|
13
|
+
env_key, data_key=data_key, region=region, env_variables=env_variables
|
|
14
|
+
)
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
async def make_for_task_async(task: Task) -> AsyncEnv:
|
fleet/_async/tasks.py
CHANGED
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import re
|
|
6
5
|
from datetime import datetime
|
|
7
6
|
from typing import Any, Dict, Optional, List
|
|
8
|
-
from uuid import UUID
|
|
9
7
|
|
|
10
8
|
from pydantic import BaseModel, Field, validator
|
|
11
9
|
|
|
@@ -46,7 +44,7 @@ class Task(BaseModel):
|
|
|
46
44
|
@property
|
|
47
45
|
def env_key(self) -> str:
|
|
48
46
|
"""Get the environment key combining env_id and version."""
|
|
49
|
-
if self.version:
|
|
47
|
+
if self.version and self.version != "None":
|
|
50
48
|
return f"{self.env_id}:{self.version}"
|
|
51
49
|
return self.env_id
|
|
52
50
|
|
|
@@ -75,7 +73,7 @@ class Task(BaseModel):
|
|
|
75
73
|
if inspect.iscoroutine(result):
|
|
76
74
|
# Check if we're already in an event loop
|
|
77
75
|
try:
|
|
78
|
-
|
|
76
|
+
asyncio.get_running_loop()
|
|
79
77
|
# We're in an async context, can't use asyncio.run()
|
|
80
78
|
raise RuntimeError(
|
|
81
79
|
"Cannot run async verifier in sync mode while event loop is running. "
|
|
@@ -121,58 +119,57 @@ class Task(BaseModel):
|
|
|
121
119
|
|
|
122
120
|
|
|
123
121
|
def verifier_from_string(
|
|
124
|
-
verifier_func: str,
|
|
125
|
-
|
|
126
|
-
verifier_key: str,
|
|
127
|
-
sha256: str = ""
|
|
128
|
-
) -> 'VerifierFunction':
|
|
122
|
+
verifier_func: str, verifier_id: str, verifier_key: str, sha256: str = ""
|
|
123
|
+
) -> "VerifierFunction":
|
|
129
124
|
"""Create a verifier function from string code.
|
|
130
|
-
|
|
125
|
+
|
|
131
126
|
Args:
|
|
132
127
|
verifier_func: The verifier function code as a string
|
|
133
128
|
verifier_id: Unique identifier for the verifier
|
|
134
129
|
verifier_key: Key/name for the verifier
|
|
135
130
|
sha256: SHA256 hash of the verifier code
|
|
136
|
-
|
|
131
|
+
|
|
137
132
|
Returns:
|
|
138
133
|
VerifierFunction instance that can be used to verify tasks
|
|
139
134
|
"""
|
|
140
135
|
try:
|
|
141
136
|
import inspect
|
|
142
|
-
from .verifiers import
|
|
137
|
+
from .verifiers.verifier import AsyncVerifierFunction
|
|
143
138
|
from fleet.verifiers.code import TASK_SUCCESSFUL_SCORE, TASK_FAILED_SCORE
|
|
144
139
|
from fleet.verifiers.db import IgnoreConfig
|
|
145
|
-
|
|
140
|
+
|
|
146
141
|
# Create a local namespace for executing the code
|
|
147
142
|
local_namespace = {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
143
|
+
"TASK_SUCCESSFUL_SCORE": TASK_SUCCESSFUL_SCORE,
|
|
144
|
+
"TASK_FAILED_SCORE": TASK_FAILED_SCORE,
|
|
145
|
+
"IgnoreConfig": IgnoreConfig,
|
|
146
|
+
"Environment": object, # Add Environment type if needed
|
|
152
147
|
}
|
|
153
|
-
|
|
148
|
+
|
|
154
149
|
# Execute the verifier code in the namespace
|
|
155
150
|
exec(verifier_func, globals(), local_namespace)
|
|
156
|
-
|
|
151
|
+
|
|
157
152
|
# Find the function that was defined
|
|
158
153
|
func_obj = None
|
|
159
154
|
for name, obj in local_namespace.items():
|
|
160
155
|
if inspect.isfunction(obj):
|
|
161
156
|
func_obj = obj
|
|
162
157
|
break
|
|
163
|
-
|
|
158
|
+
|
|
164
159
|
if func_obj is None:
|
|
165
160
|
raise ValueError("No function found in verifier code")
|
|
166
|
-
|
|
167
|
-
# Create an AsyncVerifierFunction instance
|
|
168
|
-
verifier_instance = AsyncVerifierFunction(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
161
|
+
|
|
162
|
+
# Create an AsyncVerifierFunction instance with raw code
|
|
163
|
+
verifier_instance = AsyncVerifierFunction(
|
|
164
|
+
func_obj,
|
|
165
|
+
verifier_key,
|
|
166
|
+
verifier_id=verifier_id,
|
|
167
|
+
sha256=sha256,
|
|
168
|
+
raw_code=verifier_func,
|
|
169
|
+
)
|
|
170
|
+
|
|
174
171
|
return verifier_instance
|
|
175
|
-
|
|
172
|
+
|
|
176
173
|
except Exception as e:
|
|
177
174
|
raise ValueError(f"Failed to create verifier from string: {e}")
|
|
178
175
|
|
|
@@ -181,7 +178,7 @@ async def load_tasks(
|
|
|
181
178
|
env_key: Optional[str] = None,
|
|
182
179
|
keys: Optional[List[str]] = None,
|
|
183
180
|
version: Optional[str] = None,
|
|
184
|
-
team_id: Optional[str] = None
|
|
181
|
+
team_id: Optional[str] = None,
|
|
185
182
|
) -> List[Task]:
|
|
186
183
|
"""Convenience function to load tasks with optional filtering.
|
|
187
184
|
|
|
@@ -201,17 +198,12 @@ async def load_tasks(
|
|
|
201
198
|
|
|
202
199
|
client = get_client()
|
|
203
200
|
return await client.load_tasks(
|
|
204
|
-
env_key=env_key,
|
|
205
|
-
keys=keys,
|
|
206
|
-
version=version,
|
|
207
|
-
team_id=team_id
|
|
201
|
+
env_key=env_key, keys=keys, version=version, team_id=team_id
|
|
208
202
|
)
|
|
209
203
|
|
|
210
204
|
|
|
211
205
|
async def update_task(
|
|
212
|
-
task_key: str,
|
|
213
|
-
prompt: Optional[str] = None,
|
|
214
|
-
verifier_code: Optional[str] = None
|
|
206
|
+
task_key: str, prompt: Optional[str] = None, verifier_code: Optional[str] = None
|
|
215
207
|
):
|
|
216
208
|
"""Convenience function to update an existing task.
|
|
217
209
|
|
|
@@ -228,11 +220,8 @@ async def update_task(
|
|
|
228
220
|
response = await fleet.update_task("my-task", verifier_code="def verify(env): return True")
|
|
229
221
|
"""
|
|
230
222
|
from .global_client import get_client
|
|
231
|
-
from ..models import TaskResponse
|
|
232
223
|
|
|
233
224
|
client = get_client()
|
|
234
225
|
return await client.update_task(
|
|
235
|
-
task_key=task_key,
|
|
236
|
-
prompt=prompt,
|
|
237
|
-
verifier_code=verifier_code
|
|
226
|
+
task_key=task_key, prompt=prompt, verifier_code=verifier_code
|
|
238
227
|
)
|
fleet/client.py
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
import base64
|
|
18
18
|
import cloudpickle
|
|
19
|
+
import concurrent.futures
|
|
19
20
|
import httpx
|
|
20
21
|
import json
|
|
21
22
|
import logging
|
|
@@ -206,24 +207,39 @@ class Fleet:
|
|
|
206
207
|
def make(
|
|
207
208
|
self,
|
|
208
209
|
env_key: str,
|
|
210
|
+
data_key: Optional[str] = None,
|
|
209
211
|
region: Optional[str] = None,
|
|
210
212
|
env_variables: Optional[Dict[str, Any]] = None,
|
|
211
213
|
) -> SyncEnv:
|
|
212
214
|
if ":" in env_key:
|
|
213
|
-
env_key_part,
|
|
215
|
+
env_key_part, env_version = env_key.split(":", 1)
|
|
214
216
|
if (
|
|
215
|
-
not
|
|
216
|
-
and len(
|
|
217
|
-
and
|
|
217
|
+
not env_version.startswith("v")
|
|
218
|
+
and len(env_version) != 0
|
|
219
|
+
and env_version[0].isdigit()
|
|
218
220
|
):
|
|
219
|
-
|
|
221
|
+
env_version = f"v{env_version}"
|
|
220
222
|
else:
|
|
221
223
|
env_key_part = env_key
|
|
222
|
-
|
|
224
|
+
env_version = None
|
|
225
|
+
|
|
226
|
+
if data_key is not None and ":" in data_key:
|
|
227
|
+
data_key_part, data_version = data_key.split(":", 1)
|
|
228
|
+
if (
|
|
229
|
+
not data_version.startswith("v")
|
|
230
|
+
and len(data_version) != 0
|
|
231
|
+
and data_version[0].isdigit()
|
|
232
|
+
):
|
|
233
|
+
data_version = f"v{data_version}"
|
|
234
|
+
else:
|
|
235
|
+
data_key_part = data_key
|
|
236
|
+
data_version = None
|
|
223
237
|
|
|
224
238
|
request = InstanceRequest(
|
|
225
239
|
env_key=env_key_part,
|
|
226
|
-
|
|
240
|
+
env_version=env_version,
|
|
241
|
+
data_key=data_key_part,
|
|
242
|
+
data_version=data_version,
|
|
227
243
|
region=region,
|
|
228
244
|
env_variables=env_variables,
|
|
229
245
|
created_from="sdk",
|
|
@@ -353,48 +369,107 @@ class Fleet:
|
|
|
353
369
|
response = self.client.request("GET", "/v1/tasks", params=params)
|
|
354
370
|
task_list_response = TaskListResponse(**response.json())
|
|
355
371
|
|
|
356
|
-
#
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
# Create verifier function if verifier data is present
|
|
360
|
-
verifier = None
|
|
361
|
-
verifier_func = task_response.verifier_func
|
|
372
|
+
# Prepare verifier loading tasks
|
|
373
|
+
verifier_tasks = []
|
|
374
|
+
task_responses_with_indices = []
|
|
362
375
|
|
|
376
|
+
for idx, task_response in enumerate(task_list_response.tasks):
|
|
363
377
|
if task_response.verifier:
|
|
364
378
|
embedded_code = task_response.verifier.code or ""
|
|
365
379
|
is_embedded_error = embedded_code.strip().startswith(
|
|
366
380
|
"<error loading code:"
|
|
367
381
|
)
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
382
|
+
|
|
383
|
+
def create_verifier_with_fallback(tr, emb_code, is_error):
|
|
384
|
+
"""Create verifier with fallback logic."""
|
|
385
|
+
if not is_error:
|
|
386
|
+
# Try to create from embedded data
|
|
387
|
+
try:
|
|
388
|
+
return self._create_verifier_from_data(
|
|
389
|
+
verifier_id=tr.verifier.verifier_id,
|
|
390
|
+
verifier_key=tr.verifier.key,
|
|
391
|
+
verifier_code=emb_code,
|
|
392
|
+
verifier_sha=tr.verifier.sha256,
|
|
393
|
+
)
|
|
394
|
+
except Exception as e:
|
|
395
|
+
logger.warning(
|
|
396
|
+
f"Failed to create verifier {tr.verifier.key}: {e}"
|
|
397
|
+
)
|
|
398
|
+
return None
|
|
399
|
+
else:
|
|
400
|
+
# Fallback: try fetching by ID
|
|
401
|
+
try:
|
|
402
|
+
logger.warning(
|
|
403
|
+
f"Embedded verifier code missing for {tr.verifier.key} (NoSuchKey). "
|
|
404
|
+
f"Attempting to refetch by id {tr.verifier.verifier_id}"
|
|
405
|
+
)
|
|
406
|
+
return self._load_verifier(tr.verifier.verifier_id)
|
|
407
|
+
except Exception as e:
|
|
408
|
+
logger.warning(
|
|
409
|
+
f"Refetch by verifier id failed for {tr.verifier.key}: {e}. "
|
|
410
|
+
"Leaving verifier unset."
|
|
411
|
+
)
|
|
412
|
+
return None
|
|
413
|
+
|
|
414
|
+
# Add the task for parallel execution
|
|
415
|
+
verifier_tasks.append(
|
|
416
|
+
(
|
|
417
|
+
create_verifier_with_fallback,
|
|
418
|
+
task_response,
|
|
419
|
+
embedded_code,
|
|
420
|
+
is_embedded_error,
|
|
421
|
+
)
|
|
422
|
+
)
|
|
423
|
+
task_responses_with_indices.append((idx, task_response))
|
|
424
|
+
else:
|
|
425
|
+
# No verifier needed
|
|
426
|
+
verifier_tasks.append(None)
|
|
427
|
+
task_responses_with_indices.append((idx, task_response))
|
|
428
|
+
|
|
429
|
+
# Execute all verifier loading in parallel using ThreadPoolExecutor
|
|
430
|
+
verifier_results = []
|
|
431
|
+
if verifier_tasks:
|
|
432
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
|
433
|
+
futures = []
|
|
434
|
+
for task in verifier_tasks:
|
|
435
|
+
if task is not None:
|
|
436
|
+
func, tr, emb_code, is_error = task
|
|
437
|
+
future = executor.submit(func, tr, emb_code, is_error)
|
|
438
|
+
futures.append(future)
|
|
439
|
+
else:
|
|
440
|
+
futures.append(None)
|
|
441
|
+
|
|
442
|
+
# Collect results
|
|
443
|
+
for future in futures:
|
|
444
|
+
if future is None:
|
|
445
|
+
verifier_results.append(None)
|
|
446
|
+
else:
|
|
447
|
+
try:
|
|
448
|
+
result = future.result()
|
|
449
|
+
verifier_results.append(result)
|
|
450
|
+
except Exception as e:
|
|
451
|
+
logger.warning(f"Verifier loading failed: {e}")
|
|
452
|
+
verifier_results.append(None)
|
|
453
|
+
|
|
454
|
+
# Build tasks with results
|
|
455
|
+
tasks = []
|
|
456
|
+
for (idx, task_response), verifier_result in zip(
|
|
457
|
+
task_responses_with_indices, verifier_results
|
|
458
|
+
):
|
|
459
|
+
# Handle verifier result
|
|
460
|
+
verifier = None
|
|
461
|
+
verifier_func = task_response.verifier_func
|
|
462
|
+
|
|
463
|
+
if task_response.verifier:
|
|
464
|
+
# Process verifier result
|
|
465
|
+
if verifier_result is not None:
|
|
466
|
+
verifier = verifier_result
|
|
467
|
+
embedded_code = task_response.verifier.code or ""
|
|
468
|
+
is_embedded_error = embedded_code.strip().startswith(
|
|
469
|
+
"<error loading code:"
|
|
470
|
+
)
|
|
471
|
+
if not is_embedded_error:
|
|
472
|
+
verifier_func = embedded_code
|
|
398
473
|
|
|
399
474
|
task = Task(
|
|
400
475
|
key=task_response.key,
|
|
@@ -503,7 +578,7 @@ class Fleet:
|
|
|
503
578
|
self,
|
|
504
579
|
task_key: str,
|
|
505
580
|
prompt: Optional[str] = None,
|
|
506
|
-
verifier_code: Optional[str] = None
|
|
581
|
+
verifier_code: Optional[str] = None,
|
|
507
582
|
) -> TaskResponse:
|
|
508
583
|
"""Update an existing task.
|
|
509
584
|
|
|
@@ -515,10 +590,7 @@ class Fleet:
|
|
|
515
590
|
Returns:
|
|
516
591
|
TaskResponse containing the updated task details
|
|
517
592
|
"""
|
|
518
|
-
payload = TaskUpdateRequest(
|
|
519
|
-
prompt=prompt,
|
|
520
|
-
verifier_code=verifier_code
|
|
521
|
-
)
|
|
593
|
+
payload = TaskUpdateRequest(prompt=prompt, verifier_code=verifier_code)
|
|
522
594
|
response = self.client.request(
|
|
523
595
|
"PUT", f"/v1/tasks/{task_key}", json=payload.model_dump(exclude_none=True)
|
|
524
596
|
)
|
fleet/env/client.py
CHANGED
|
@@ -3,8 +3,15 @@ from ..models import Environment as EnvironmentModel, AccountResponse
|
|
|
3
3
|
from typing import List, Optional, Dict, Any
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def make(
|
|
7
|
-
|
|
6
|
+
def make(
|
|
7
|
+
env_key: str,
|
|
8
|
+
data_key: Optional[str] = None,
|
|
9
|
+
region: Optional[str] = None,
|
|
10
|
+
env_variables: Optional[Dict[str, Any]] = None,
|
|
11
|
+
) -> SyncEnv:
|
|
12
|
+
return Fleet().make(
|
|
13
|
+
env_key, data_key=data_key, region=region, env_variables=env_variables
|
|
14
|
+
)
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
def make_for_task_async(task: Task) -> SyncEnv:
|
fleet/models.py
CHANGED
|
@@ -55,7 +55,9 @@ class Instance(BaseModel):
|
|
|
55
55
|
|
|
56
56
|
class InstanceRequest(BaseModel):
|
|
57
57
|
env_key: str = Field(..., title="Env Key")
|
|
58
|
-
|
|
58
|
+
env_version: Optional[str] = Field(None, title="Version")
|
|
59
|
+
data_key: Optional[str] = Field(None, title="Data Key")
|
|
60
|
+
data_version: Optional[str] = Field(None, title="Data Version")
|
|
59
61
|
region: Optional[str] = Field("us-west-1", title="Region")
|
|
60
62
|
seed: Optional[int] = Field(None, title="Seed")
|
|
61
63
|
timestamp: Optional[int] = Field(None, title="Timestamp")
|
fleet/tasks.py
CHANGED
|
@@ -47,7 +47,7 @@ class Task(BaseModel):
|
|
|
47
47
|
@property
|
|
48
48
|
def env_key(self) -> str:
|
|
49
49
|
"""Get the environment key combining env_id and version."""
|
|
50
|
-
if self.version:
|
|
50
|
+
if self.version and self.version != "None":
|
|
51
51
|
return f"{self.env_id}:{self.version}"
|
|
52
52
|
return self.env_id
|
|
53
53
|
|
|
@@ -70,7 +70,7 @@ class Task(BaseModel):
|
|
|
70
70
|
import inspect
|
|
71
71
|
|
|
72
72
|
# Check if verifier has remote method (for decorated verifiers)
|
|
73
|
-
if hasattr(self.verifier,
|
|
73
|
+
if hasattr(self.verifier, "remote"):
|
|
74
74
|
result = self.verifier.remote(env, *args, **kwargs)
|
|
75
75
|
else:
|
|
76
76
|
# For verifiers created from string, call directly
|
|
@@ -126,19 +126,16 @@ class Task(BaseModel):
|
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
def verifier_from_string(
|
|
129
|
-
verifier_func: str,
|
|
130
|
-
|
|
131
|
-
verifier_key: str,
|
|
132
|
-
sha256: str = ""
|
|
133
|
-
) -> 'VerifierFunction':
|
|
129
|
+
verifier_func: str, verifier_id: str, verifier_key: str, sha256: str = ""
|
|
130
|
+
) -> "VerifierFunction":
|
|
134
131
|
"""Create a verifier function from string code.
|
|
135
|
-
|
|
132
|
+
|
|
136
133
|
Args:
|
|
137
134
|
verifier_func: The verifier function code as a string
|
|
138
135
|
verifier_id: Unique identifier for the verifier
|
|
139
136
|
verifier_key: Key/name for the verifier
|
|
140
137
|
sha256: SHA256 hash of the verifier code
|
|
141
|
-
|
|
138
|
+
|
|
142
139
|
Returns:
|
|
143
140
|
VerifierFunction instance that can be used to verify tasks
|
|
144
141
|
"""
|
|
@@ -147,63 +144,72 @@ def verifier_from_string(
|
|
|
147
144
|
from .verifiers import verifier, SyncVerifierFunction
|
|
148
145
|
from .verifiers.code import TASK_SUCCESSFUL_SCORE, TASK_FAILED_SCORE
|
|
149
146
|
from .verifiers.db import IgnoreConfig
|
|
150
|
-
|
|
147
|
+
|
|
151
148
|
# Create a globals namespace with all required imports
|
|
152
149
|
exec_globals = globals().copy()
|
|
153
|
-
exec_globals.update(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
150
|
+
exec_globals.update(
|
|
151
|
+
{
|
|
152
|
+
"TASK_SUCCESSFUL_SCORE": TASK_SUCCESSFUL_SCORE,
|
|
153
|
+
"TASK_FAILED_SCORE": TASK_FAILED_SCORE,
|
|
154
|
+
"IgnoreConfig": IgnoreConfig,
|
|
155
|
+
"Environment": object, # Add Environment type if needed
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
|
|
160
159
|
# Create a local namespace for executing the code
|
|
161
160
|
local_namespace = {}
|
|
162
|
-
|
|
161
|
+
|
|
163
162
|
# Execute the verifier code in the namespace
|
|
164
163
|
exec(verifier_func, exec_globals, local_namespace)
|
|
165
|
-
|
|
164
|
+
|
|
166
165
|
# Find the function that was defined
|
|
167
166
|
func_obj = None
|
|
168
167
|
for name, obj in local_namespace.items():
|
|
169
168
|
if inspect.isfunction(obj):
|
|
170
169
|
func_obj = obj
|
|
171
170
|
break
|
|
172
|
-
|
|
171
|
+
|
|
173
172
|
if func_obj is None:
|
|
174
173
|
raise ValueError("No function found in verifier code")
|
|
175
|
-
|
|
174
|
+
|
|
176
175
|
# Create a wrapper function that provides the necessary globals
|
|
177
176
|
def wrapped_verifier(env, *args, **kwargs):
|
|
178
177
|
# Set up globals for the function execution
|
|
179
|
-
func_globals =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
178
|
+
func_globals = (
|
|
179
|
+
func_obj.__globals__.copy() if hasattr(func_obj, "__globals__") else {}
|
|
180
|
+
)
|
|
181
|
+
func_globals.update(
|
|
182
|
+
{
|
|
183
|
+
"TASK_SUCCESSFUL_SCORE": TASK_SUCCESSFUL_SCORE,
|
|
184
|
+
"TASK_FAILED_SCORE": TASK_FAILED_SCORE,
|
|
185
|
+
"IgnoreConfig": IgnoreConfig,
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
|
|
186
189
|
# Create a new function with the updated globals
|
|
187
190
|
import types
|
|
191
|
+
|
|
188
192
|
new_func = types.FunctionType(
|
|
189
193
|
func_obj.__code__,
|
|
190
194
|
func_globals,
|
|
191
195
|
func_obj.__name__,
|
|
192
196
|
func_obj.__defaults__,
|
|
193
|
-
func_obj.__closure__
|
|
197
|
+
func_obj.__closure__,
|
|
194
198
|
)
|
|
195
|
-
|
|
199
|
+
|
|
196
200
|
return new_func(env, *args, **kwargs)
|
|
197
|
-
|
|
201
|
+
|
|
198
202
|
# Create an AsyncVerifierFunction instance with the wrapped function
|
|
199
|
-
verifier_instance = SyncVerifierFunction(
|
|
200
|
-
|
|
203
|
+
verifier_instance = SyncVerifierFunction(
|
|
204
|
+
wrapped_verifier, verifier_key, verifier_id
|
|
205
|
+
)
|
|
206
|
+
|
|
201
207
|
# Store additional metadata
|
|
202
208
|
verifier_instance._verifier_code = verifier_func
|
|
203
209
|
verifier_instance._sha256 = sha256
|
|
204
|
-
|
|
210
|
+
|
|
205
211
|
return verifier_instance
|
|
206
|
-
|
|
212
|
+
|
|
207
213
|
except Exception as e:
|
|
208
214
|
raise ValueError(f"Failed to create verifier from string: {e}")
|
|
209
215
|
|
|
@@ -212,7 +218,7 @@ def load_tasks(
|
|
|
212
218
|
env_key: Optional[str] = None,
|
|
213
219
|
keys: Optional[List[str]] = None,
|
|
214
220
|
version: Optional[str] = None,
|
|
215
|
-
team_id: Optional[str] = None
|
|
221
|
+
team_id: Optional[str] = None,
|
|
216
222
|
) -> List[Task]:
|
|
217
223
|
"""Convenience function to load tasks with optional filtering.
|
|
218
224
|
|
|
@@ -232,17 +238,12 @@ def load_tasks(
|
|
|
232
238
|
|
|
233
239
|
client = get_client()
|
|
234
240
|
return client.load_tasks(
|
|
235
|
-
env_key=env_key,
|
|
236
|
-
keys=keys,
|
|
237
|
-
version=version,
|
|
238
|
-
team_id=team_id
|
|
241
|
+
env_key=env_key, keys=keys, version=version, team_id=team_id
|
|
239
242
|
)
|
|
240
243
|
|
|
241
244
|
|
|
242
245
|
def update_task(
|
|
243
|
-
task_key: str,
|
|
244
|
-
prompt: Optional[str] = None,
|
|
245
|
-
verifier_code: Optional[str] = None
|
|
246
|
+
task_key: str, prompt: Optional[str] = None, verifier_code: Optional[str] = None
|
|
246
247
|
):
|
|
247
248
|
"""Convenience function to update an existing task.
|
|
248
249
|
|
|
@@ -263,7 +264,5 @@ def update_task(
|
|
|
263
264
|
|
|
264
265
|
client = get_client()
|
|
265
266
|
return client.update_task(
|
|
266
|
-
task_key=task_key,
|
|
267
|
-
prompt=prompt,
|
|
268
|
-
verifier_code=verifier_code
|
|
267
|
+
task_key=task_key, prompt=prompt, verifier_code=verifier_code
|
|
269
268
|
)
|
|
@@ -21,22 +21,22 @@ examples/quickstart.py,sha256=1VT39IRRhemsJgxi0O0gprdpcw7HB4pYO97GAYagIcg,3788
|
|
|
21
21
|
examples/test_cdp_logging.py,sha256=AkCwQCgOTQEI8w3v0knWK_4eXMph7L9x07wj9yIYM10,2836
|
|
22
22
|
fleet/__init__.py,sha256=oxI2XvaiRMn15AZpoDHOvX26WlXALHXvqSRP0KkBpAY,3751
|
|
23
23
|
fleet/base.py,sha256=bc-340sTpq_DJs7yQ9d2pDWnmJFmA1SwDB9Lagvqtb4,9182
|
|
24
|
-
fleet/client.py,sha256=
|
|
24
|
+
fleet/client.py,sha256=d-sGsC8a68czfuaSSm8_Vrkzo-lvamDdwWiCYT2QttE,25865
|
|
25
25
|
fleet/config.py,sha256=uY02ZKxVoXqVDta-0IMWaYJeE1CTXF_fA9NI6QUutmU,319
|
|
26
26
|
fleet/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
|
|
27
27
|
fleet/global_client.py,sha256=frrDAFNM2ywN0JHLtlm9qbE1dQpnQJsavJpb7xSR_bU,1072
|
|
28
|
-
fleet/models.py,sha256=
|
|
29
|
-
fleet/tasks.py,sha256=
|
|
28
|
+
fleet/models.py,sha256=WAiRXa68aXSVbCqmQMn36n9cSlls6YsicV6BbyoeiYQ,12750
|
|
29
|
+
fleet/tasks.py,sha256=P-qcbLZLMVGdJ02Rb8Q2kGIINdnZ_CNIu_FeCVcihcg,9573
|
|
30
30
|
fleet/types.py,sha256=L4Y82xICf1tzyCLqhLYUgEoaIIS5h9T05TyFNHSWs3s,652
|
|
31
31
|
fleet/_async/__init__.py,sha256=lrnDD6N9p0Oqpi_djxTnxh8I5F7nA7KNn0khciGmgpg,6747
|
|
32
32
|
fleet/_async/base.py,sha256=oisVTQsx0M_yTmyQJc3oij63uKZ97MHz-xYFsWXxQE8,9202
|
|
33
|
-
fleet/_async/client.py,sha256=
|
|
33
|
+
fleet/_async/client.py,sha256=4nwpX933fIutctwictasU8oJODwP63vRT0FJxd1b_Do,26170
|
|
34
34
|
fleet/_async/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
|
|
35
35
|
fleet/_async/global_client.py,sha256=4WskpLHbsDEgWW7hXMD09W-brkp4euy8w2ZJ88594rQ,1103
|
|
36
36
|
fleet/_async/models.py,sha256=li5Cii7ASUHCFMFeJIMklyicYczqPez768RxO0Q0F2o,12618
|
|
37
|
-
fleet/_async/tasks.py,sha256=
|
|
37
|
+
fleet/_async/tasks.py,sha256=QZFQNW4_Iq2VbGZiPXzKDFXmNrxe4mn-ROGvpGhN7pw,8131
|
|
38
38
|
fleet/_async/env/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
fleet/_async/env/client.py,sha256=
|
|
39
|
+
fleet/_async/env/client.py,sha256=8dS42VvSgdqfuh96l6cyiLZlKElilmfTeRSZ4LZnFuE,1143
|
|
40
40
|
fleet/_async/instance/__init__.py,sha256=PtmJq8J8bh0SOQ2V55QURz5GJfobozwtQoqhaOk3_tI,515
|
|
41
41
|
fleet/_async/instance/base.py,sha256=3qUBuUR8OVS36LzdP6KyZzngtwPKYO09HoY6Ekxp-KA,1625
|
|
42
42
|
fleet/_async/instance/client.py,sha256=z9q_-dIBwPc1X6VlQOi_aV2v6KOKueJGg8NMyP5iFQM,6082
|
|
@@ -49,7 +49,7 @@ fleet/_async/verifiers/__init__.py,sha256=1WTlCNq4tIFbbXaQu5Bf2WppZq0A8suhtZbxMT
|
|
|
49
49
|
fleet/_async/verifiers/bundler.py,sha256=Sq0KkqEhM5Ng2x8R6Z4puXvQ8FMlEO7D3-ldBLktPi4,26205
|
|
50
50
|
fleet/_async/verifiers/verifier.py,sha256=lwVIV5ZpWJhM87tXShtjwN5KP7n5XDcPq0XX7AjV6_E,14343
|
|
51
51
|
fleet/env/__init__.py,sha256=cS9zCYobM5jypppDMZIQMYd6hOg5f4sgqRXEQ67pckk,676
|
|
52
|
-
fleet/env/client.py,sha256=
|
|
52
|
+
fleet/env/client.py,sha256=imF47xJG4JeihcZw4Y-_fXz4XxS-OgIkzUK-TLjpeJY,977
|
|
53
53
|
fleet/instance/__init__.py,sha256=CyWUkbGAK-DBPw4DC4AnCW-MqqheGhZMA5QSRVu-ws4,479
|
|
54
54
|
fleet/instance/base.py,sha256=OYqzBwZFfTX9wlBGSG5gljqj98NbiJeKIfFJ3uj5I4s,1587
|
|
55
55
|
fleet/instance/client.py,sha256=O6B0A2Z0b5SxOLs4TipZ9Ol8yG-b-LG15vVOKMmd6BQ,5908
|
|
@@ -67,10 +67,10 @@ fleet/verifiers/decorator.py,sha256=nAP3O8szXu7md_kpwpz91hGSUNEVLYjwZQZTkQlV1DM,
|
|
|
67
67
|
fleet/verifiers/parse.py,sha256=0bAbj9VvT__yU4ZVREUK-Tn9dukh9LCpmfVsgj1DfP4,8508
|
|
68
68
|
fleet/verifiers/sql_differ.py,sha256=dmiGCFXVMEMbAX519OjhVqgA8ZvhnvdmC1BVpL7QCF0,6490
|
|
69
69
|
fleet/verifiers/verifier.py,sha256=53oBWAf0yy3bZmZx9eH9AWIf65H7OP2UUm0YwWCL6Mc,14286
|
|
70
|
-
fleet_python-0.2.
|
|
70
|
+
fleet_python-0.2.43.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
71
71
|
scripts/fix_sync_imports.py,sha256=X9fWLTpiPGkSHsjyQUDepOJkxOqw1DPj7nd8wFlFqLQ,8368
|
|
72
72
|
scripts/unasync.py,sha256=vWVQxRWX8SRZO5cmzEhpvnG_REhCWXpidIGIpWmEcvI,696
|
|
73
|
-
fleet_python-0.2.
|
|
74
|
-
fleet_python-0.2.
|
|
75
|
-
fleet_python-0.2.
|
|
76
|
-
fleet_python-0.2.
|
|
73
|
+
fleet_python-0.2.43.dist-info/METADATA,sha256=fgD6_tIyLKKOXNT_qoyf98t12w3ITDd1vAyCYFh7_KU,3304
|
|
74
|
+
fleet_python-0.2.43.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
75
|
+
fleet_python-0.2.43.dist-info/top_level.txt,sha256=_3DSmTohvSDf3AIP_BYfGzhwO1ECFwuzg83X-wHCx3Y,23
|
|
76
|
+
fleet_python-0.2.43.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|