fleet-python 0.2.62__py3-none-any.whl → 0.2.63__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.
- examples/import_tasks.py +212 -1
- fleet/_async/tasks.py +10 -2
- fleet/tasks.py +10 -2
- {fleet_python-0.2.62.dist-info → fleet_python-0.2.63.dist-info}/METADATA +1 -1
- {fleet_python-0.2.62.dist-info → fleet_python-0.2.63.dist-info}/RECORD +8 -8
- {fleet_python-0.2.62.dist-info → fleet_python-0.2.63.dist-info}/WHEEL +0 -0
- {fleet_python-0.2.62.dist-info → fleet_python-0.2.63.dist-info}/licenses/LICENSE +0 -0
- {fleet_python-0.2.62.dist-info → fleet_python-0.2.63.dist-info}/top_level.txt +0 -0
examples/import_tasks.py
CHANGED
|
@@ -2,12 +2,194 @@ import asyncio
|
|
|
2
2
|
import argparse
|
|
3
3
|
import json
|
|
4
4
|
import sys
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
from typing import Dict, List, Tuple
|
|
5
7
|
import fleet
|
|
8
|
+
from fleet._async.tasks import Task
|
|
6
9
|
from dotenv import load_dotenv
|
|
7
10
|
|
|
8
11
|
load_dotenv()
|
|
9
12
|
|
|
10
13
|
|
|
14
|
+
async def run_verifier_sanity_check(
|
|
15
|
+
tasks: List[Task],
|
|
16
|
+
client: fleet.AsyncFleet,
|
|
17
|
+
) -> Tuple[bool, Dict[str, str]]:
|
|
18
|
+
"""
|
|
19
|
+
Run sanity check by spinning up instances and running verifiers.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
tasks: List of Task objects to verify
|
|
23
|
+
client: AsyncFleet client instance
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Tuple of (all_passed, error_dict) where error_dict maps task_key to error message
|
|
27
|
+
"""
|
|
28
|
+
print("\n" + "=" * 60)
|
|
29
|
+
print("Running verifier sanity check...")
|
|
30
|
+
print("=" * 60)
|
|
31
|
+
|
|
32
|
+
# Group tasks by env_key×env_version×data_key×data_version
|
|
33
|
+
instance_groups = defaultdict(list)
|
|
34
|
+
for task in tasks:
|
|
35
|
+
# Build the instance key
|
|
36
|
+
env_key = task.env_id or ""
|
|
37
|
+
env_version = task.version or ""
|
|
38
|
+
data_key = task.data_id or ""
|
|
39
|
+
data_version = task.data_version or ""
|
|
40
|
+
|
|
41
|
+
instance_key = f"{env_key}×{env_version}×{data_key}×{data_version}"
|
|
42
|
+
instance_groups[instance_key].append(task)
|
|
43
|
+
|
|
44
|
+
print(f"\nFound {len(instance_groups)} unique environment/data combinations:")
|
|
45
|
+
for instance_key, group_tasks in instance_groups.items():
|
|
46
|
+
print(f" {instance_key}: {len(group_tasks)} task(s)")
|
|
47
|
+
|
|
48
|
+
# Create all instances in parallel
|
|
49
|
+
print(f"\nCreating {len(instance_groups)} instance(s) in parallel...")
|
|
50
|
+
instance_map = {}
|
|
51
|
+
|
|
52
|
+
async def create_instance(instance_key: str) -> Tuple[str, object]:
|
|
53
|
+
"""Create a single instance."""
|
|
54
|
+
try:
|
|
55
|
+
env_key, env_version, data_key, data_version = instance_key.split("×")
|
|
56
|
+
|
|
57
|
+
# Build env_key_str and data_key_str
|
|
58
|
+
if env_version:
|
|
59
|
+
env_key_str = f"{env_key}:{env_version}"
|
|
60
|
+
else:
|
|
61
|
+
env_key_str = env_key
|
|
62
|
+
|
|
63
|
+
if data_key and data_version:
|
|
64
|
+
data_key_str = f"{data_key}:{data_version}"
|
|
65
|
+
elif data_key:
|
|
66
|
+
data_key_str = data_key
|
|
67
|
+
else:
|
|
68
|
+
data_key_str = None
|
|
69
|
+
|
|
70
|
+
print(
|
|
71
|
+
f" Creating instance: {env_key_str}"
|
|
72
|
+
+ (f" with data {data_key_str}" if data_key_str else "")
|
|
73
|
+
)
|
|
74
|
+
env = await client.make(env_key=env_key_str, data_key=data_key_str)
|
|
75
|
+
return instance_key, env
|
|
76
|
+
except Exception as e:
|
|
77
|
+
print(f" ✗ Failed to create instance for {instance_key}: {e}")
|
|
78
|
+
return instance_key, None
|
|
79
|
+
|
|
80
|
+
# Create instances concurrently
|
|
81
|
+
instance_results = await asyncio.gather(
|
|
82
|
+
*[create_instance(key) for key in instance_groups.keys()],
|
|
83
|
+
return_exceptions=True,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
for result in instance_results:
|
|
87
|
+
if isinstance(result, Exception):
|
|
88
|
+
print(f" ✗ Exception creating instance: {result}")
|
|
89
|
+
return False, {"__instance_creation__": str(result)}
|
|
90
|
+
instance_key, env = result
|
|
91
|
+
if env is None:
|
|
92
|
+
return False, {instance_key: "Failed to create instance"}
|
|
93
|
+
instance_map[instance_key] = env
|
|
94
|
+
|
|
95
|
+
print(f"✓ Created {len(instance_map)} instance(s)")
|
|
96
|
+
|
|
97
|
+
# Run all verifiers in parallel with concurrency limit
|
|
98
|
+
max_concurrent_verifiers = 5 # Limit concurrent verifier executions
|
|
99
|
+
print(
|
|
100
|
+
f"\nRunning {len(tasks)} verifier(s) in parallel (max {max_concurrent_verifiers} concurrent)..."
|
|
101
|
+
)
|
|
102
|
+
errors = {}
|
|
103
|
+
semaphore = asyncio.Semaphore(max_concurrent_verifiers)
|
|
104
|
+
|
|
105
|
+
async def run_single_verifier(task, instance_key: str) -> Tuple[str, bool, str]:
|
|
106
|
+
"""Run a single verifier and return (task_key, success, error_message)."""
|
|
107
|
+
async with semaphore:
|
|
108
|
+
try:
|
|
109
|
+
env = instance_map[instance_key]
|
|
110
|
+
task_key = task.key
|
|
111
|
+
|
|
112
|
+
# Run the verifier
|
|
113
|
+
if task.verifier is None:
|
|
114
|
+
return task_key, False, "No verifier found"
|
|
115
|
+
|
|
116
|
+
result = await task.verify_async(env)
|
|
117
|
+
|
|
118
|
+
# For sanity check: we expect verifiers to return 0.0 (TASK_FAILED_SCORE)
|
|
119
|
+
# since we're running on fresh instances with no task completion.
|
|
120
|
+
# This confirms the verifier runs without errors.
|
|
121
|
+
if isinstance(result, float):
|
|
122
|
+
if result == 0.0:
|
|
123
|
+
print(f" ✓ {task_key}: {result:.2f} (correctly returns 0.0)")
|
|
124
|
+
return task_key, True, ""
|
|
125
|
+
else:
|
|
126
|
+
print(
|
|
127
|
+
f" ⚠ {task_key}: {result:.2f} (expected 0.0 on fresh instance)"
|
|
128
|
+
)
|
|
129
|
+
return (
|
|
130
|
+
task_key,
|
|
131
|
+
False,
|
|
132
|
+
f"Expected 0.0 but got {result:.2f} on fresh instance",
|
|
133
|
+
)
|
|
134
|
+
else:
|
|
135
|
+
# Non-float result - verifier ran but didn't return expected type
|
|
136
|
+
print(f" ⚠ {task_key}: {result} (expected float 0.0)")
|
|
137
|
+
return (
|
|
138
|
+
task_key,
|
|
139
|
+
False,
|
|
140
|
+
f"Expected float 0.0 but got {type(result).__name__}: {result}",
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
task_key = task.key
|
|
145
|
+
error_msg = f"{type(e).__name__}: {str(e)}"
|
|
146
|
+
print(f" ✗ {task_key}: {error_msg}")
|
|
147
|
+
return task_key, False, error_msg
|
|
148
|
+
|
|
149
|
+
# Run verifiers concurrently with semaphore
|
|
150
|
+
verifier_results = await asyncio.gather(
|
|
151
|
+
*[
|
|
152
|
+
run_single_verifier(task, instance_key)
|
|
153
|
+
for instance_key, group_tasks in instance_groups.items()
|
|
154
|
+
for task in group_tasks
|
|
155
|
+
],
|
|
156
|
+
return_exceptions=True,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Process results
|
|
160
|
+
for result in verifier_results:
|
|
161
|
+
if isinstance(result, Exception):
|
|
162
|
+
print(f" ✗ Exception running verifier: {result}")
|
|
163
|
+
errors["__verifier_exception__"] = str(result)
|
|
164
|
+
else:
|
|
165
|
+
task_key, success, error_msg = result
|
|
166
|
+
if not success:
|
|
167
|
+
errors[task_key] = error_msg
|
|
168
|
+
|
|
169
|
+
# Clean up instances
|
|
170
|
+
print(f"\nCleaning up {len(instance_map)} instance(s)...")
|
|
171
|
+
cleanup_tasks = [env.close() for env in instance_map.values()]
|
|
172
|
+
await asyncio.gather(*cleanup_tasks, return_exceptions=True)
|
|
173
|
+
print("✓ Cleanup complete")
|
|
174
|
+
|
|
175
|
+
# Summary
|
|
176
|
+
passed_count = len(tasks) - len(errors)
|
|
177
|
+
print("\n" + "=" * 60)
|
|
178
|
+
print(f"Sanity check complete: {passed_count}/{len(tasks)} passed")
|
|
179
|
+
|
|
180
|
+
if errors:
|
|
181
|
+
print(f"\n✗ {len(errors)} verifier(s) failed:")
|
|
182
|
+
for task_key, error_msg in list(errors.items())[:10]:
|
|
183
|
+
print(f" - {task_key}: {error_msg}")
|
|
184
|
+
if len(errors) > 10:
|
|
185
|
+
print(f" ... and {len(errors) - 10} more")
|
|
186
|
+
print("\nFix the verifiers and try again.")
|
|
187
|
+
return False, errors
|
|
188
|
+
else:
|
|
189
|
+
print("✓ All verifiers passed!")
|
|
190
|
+
return True, {}
|
|
191
|
+
|
|
192
|
+
|
|
11
193
|
async def main():
|
|
12
194
|
parser = argparse.ArgumentParser(description="Import tasks from a JSON file")
|
|
13
195
|
parser.add_argument("json_file", help="Path to the JSON file containing tasks")
|
|
@@ -23,6 +205,11 @@ async def main():
|
|
|
23
205
|
action="store_true",
|
|
24
206
|
help="Skip confirmation prompt and import automatically",
|
|
25
207
|
)
|
|
208
|
+
parser.add_argument(
|
|
209
|
+
"--skip-sanity-check",
|
|
210
|
+
action="store_true",
|
|
211
|
+
help="Skip the verifier sanity check (not recommended)",
|
|
212
|
+
)
|
|
26
213
|
|
|
27
214
|
args = parser.parse_args()
|
|
28
215
|
|
|
@@ -47,7 +234,7 @@ async def main():
|
|
|
47
234
|
task_keys.append(task_key)
|
|
48
235
|
else:
|
|
49
236
|
task_keys.append("(no key)")
|
|
50
|
-
|
|
237
|
+
|
|
51
238
|
# Check for verifier_func
|
|
52
239
|
verifier_code = task_data.get("verifier_func") or task_data.get("verifier_code")
|
|
53
240
|
if not verifier_code:
|
|
@@ -78,6 +265,30 @@ async def main():
|
|
|
78
265
|
else:
|
|
79
266
|
print("\nProject key: (none)")
|
|
80
267
|
|
|
268
|
+
# Load tasks as Task objects
|
|
269
|
+
client = fleet.AsyncFleet()
|
|
270
|
+
tasks = []
|
|
271
|
+
print("\nLoading tasks...")
|
|
272
|
+
for task_data in tasks_data:
|
|
273
|
+
try:
|
|
274
|
+
task = await client.load_task_from_json(
|
|
275
|
+
task_data, raise_on_verifier_error=True
|
|
276
|
+
)
|
|
277
|
+
tasks.append(task)
|
|
278
|
+
except Exception as e:
|
|
279
|
+
task_key = task_data.get("key") or task_data.get("id", "unknown")
|
|
280
|
+
print(f"✗ Failed to load task {task_key}: {e}")
|
|
281
|
+
sys.exit(1)
|
|
282
|
+
print(f"✓ Loaded {len(tasks)} tasks")
|
|
283
|
+
|
|
284
|
+
# Run sanity check (unless skipped)
|
|
285
|
+
if not args.skip_sanity_check:
|
|
286
|
+
success, errors = await run_verifier_sanity_check(tasks, client)
|
|
287
|
+
if not success:
|
|
288
|
+
sys.exit(1)
|
|
289
|
+
else:
|
|
290
|
+
print("\n⚠️ Skipping sanity check (--skip-sanity-check)")
|
|
291
|
+
|
|
81
292
|
# Confirmation prompt (unless --yes flag is provided)
|
|
82
293
|
if not args.yes:
|
|
83
294
|
print("\n" + "=" * 60)
|
fleet/_async/tasks.py
CHANGED
|
@@ -274,10 +274,18 @@ def verifier_from_string(
|
|
|
274
274
|
"""
|
|
275
275
|
try:
|
|
276
276
|
import inspect
|
|
277
|
+
import re
|
|
277
278
|
from .verifiers.verifier import AsyncVerifierFunction
|
|
278
279
|
from fleet.verifiers.code import TASK_SUCCESSFUL_SCORE, TASK_FAILED_SCORE
|
|
279
280
|
from fleet.verifiers.db import IgnoreConfig
|
|
280
281
|
|
|
282
|
+
# Strip @verifier decorator if present to avoid double-wrapping
|
|
283
|
+
# Remove lines like: @verifier(key="...")
|
|
284
|
+
cleaned_code = re.sub(r'@verifier\([^)]*\)\s*\n', '', verifier_func)
|
|
285
|
+
# Also remove the verifier import if present
|
|
286
|
+
cleaned_code = re.sub(r'from fleet import.*verifier.*\n', '', cleaned_code)
|
|
287
|
+
cleaned_code = re.sub(r'import.*verifier.*\n', '', cleaned_code)
|
|
288
|
+
|
|
281
289
|
# Create a local namespace for executing the code
|
|
282
290
|
local_namespace = {
|
|
283
291
|
"TASK_SUCCESSFUL_SCORE": TASK_SUCCESSFUL_SCORE,
|
|
@@ -286,8 +294,8 @@ def verifier_from_string(
|
|
|
286
294
|
"Environment": object, # Add Environment type if needed
|
|
287
295
|
}
|
|
288
296
|
|
|
289
|
-
# Execute the verifier code in the namespace
|
|
290
|
-
exec(
|
|
297
|
+
# Execute the cleaned verifier code in the namespace
|
|
298
|
+
exec(cleaned_code, globals(), local_namespace)
|
|
291
299
|
|
|
292
300
|
# Find the function that was defined (not imported)
|
|
293
301
|
# Functions defined via exec have co_filename == '<string>'
|
fleet/tasks.py
CHANGED
|
@@ -265,10 +265,18 @@ def verifier_from_string(
|
|
|
265
265
|
"""
|
|
266
266
|
try:
|
|
267
267
|
import inspect
|
|
268
|
+
import re
|
|
268
269
|
from .verifiers import SyncVerifierFunction
|
|
269
270
|
from .verifiers.code import TASK_SUCCESSFUL_SCORE, TASK_FAILED_SCORE
|
|
270
271
|
from .verifiers.db import IgnoreConfig
|
|
271
272
|
|
|
273
|
+
# Strip @verifier decorator if present to avoid double-wrapping
|
|
274
|
+
# Remove lines like: @verifier(key="...")
|
|
275
|
+
cleaned_code = re.sub(r'@verifier\([^)]*\)\s*\n', '', verifier_func)
|
|
276
|
+
# Also remove the verifier import if present
|
|
277
|
+
cleaned_code = re.sub(r'from fleet import.*verifier.*\n', '', cleaned_code)
|
|
278
|
+
cleaned_code = re.sub(r'import.*verifier.*\n', '', cleaned_code)
|
|
279
|
+
|
|
272
280
|
# Create a globals namespace with all required imports
|
|
273
281
|
exec_globals = globals().copy()
|
|
274
282
|
exec_globals.update(
|
|
@@ -283,8 +291,8 @@ def verifier_from_string(
|
|
|
283
291
|
# Create a local namespace for executing the code
|
|
284
292
|
local_namespace = {}
|
|
285
293
|
|
|
286
|
-
# Execute the verifier code in the namespace
|
|
287
|
-
exec(
|
|
294
|
+
# Execute the cleaned verifier code in the namespace
|
|
295
|
+
exec(cleaned_code, exec_globals, local_namespace)
|
|
288
296
|
|
|
289
297
|
# Find the function that was defined (not imported)
|
|
290
298
|
# Functions defined via exec have co_filename == '<string>'
|
|
@@ -13,7 +13,7 @@ examples/example_tasks.py,sha256=xTL8UWVAuolSX6swskfrAcmDrLIzn45dJ7YPWCwoEBU,514
|
|
|
13
13
|
examples/example_verifier.py,sha256=0vwNITIG3m4CkSPwIxNXcGx9TqrxEsCGqK2A8keKZMM,2392
|
|
14
14
|
examples/export_tasks.py,sha256=cJ_8xND7Q3IOM1JfJPR-DH3aLfHo_KmKJeO-1IVUFrQ,3237
|
|
15
15
|
examples/gemini_example.py,sha256=qj9WDazQTYNiRHNeUg9Tjkp33lJMwbx8gDfpFe1sDQo,16180
|
|
16
|
-
examples/import_tasks.py,sha256=
|
|
16
|
+
examples/import_tasks.py,sha256=Duh7T0HUuqsYUZ6LK2AXF3eP0zfSj1izkI5-1p09d9w,11041
|
|
17
17
|
examples/json_tasks_example.py,sha256=CYPESGGtOo0fmsDdLidujTfsE4QlJHw7rOhyVqPJ_Ls,5329
|
|
18
18
|
examples/nova_act_example.py,sha256=rH23Lp74Okf0rn8ynMdWjK2aviEf5NLPH4k_53Pyxho,831
|
|
19
19
|
examples/openai_example.py,sha256=dEWERrTEP5xBiGkLkQjBQGd2NqoxX6gcW6XteBPsWFQ,8231
|
|
@@ -28,7 +28,7 @@ fleet/config.py,sha256=uY02ZKxVoXqVDta-0IMWaYJeE1CTXF_fA9NI6QUutmU,319
|
|
|
28
28
|
fleet/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
|
|
29
29
|
fleet/global_client.py,sha256=frrDAFNM2ywN0JHLtlm9qbE1dQpnQJsavJpb7xSR_bU,1072
|
|
30
30
|
fleet/models.py,sha256=-8WG10SMkXUljRqD_8pfajCr4PS9qYDVLAZ8RxdJMb0,13392
|
|
31
|
-
fleet/tasks.py,sha256=
|
|
31
|
+
fleet/tasks.py,sha256=PJvq9JAduk88oVv3c9e4P7pwIKpO0Zxym4TFJpQbiSc,17349
|
|
32
32
|
fleet/types.py,sha256=L4Y82xICf1tzyCLqhLYUgEoaIIS5h9T05TyFNHSWs3s,652
|
|
33
33
|
fleet/_async/__init__.py,sha256=Wi8Tjj-Lfnxi4cPOkAxh2lynnpEBNni6mI6Iq80uOro,8054
|
|
34
34
|
fleet/_async/base.py,sha256=oisVTQsx0M_yTmyQJc3oij63uKZ97MHz-xYFsWXxQE8,9202
|
|
@@ -36,7 +36,7 @@ fleet/_async/client.py,sha256=Uu9o8LpUce8vOoFxqG0RDe4VtJpu1BJGIFbVecuO71g,32947
|
|
|
36
36
|
fleet/_async/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
|
|
37
37
|
fleet/_async/global_client.py,sha256=4WskpLHbsDEgWW7hXMD09W-brkp4euy8w2ZJ88594rQ,1103
|
|
38
38
|
fleet/_async/models.py,sha256=6x3IPYuWz1v6zWjujqgzK2CpR2HB5Rme4LQFLyvUDXE,13164
|
|
39
|
-
fleet/_async/tasks.py,sha256=
|
|
39
|
+
fleet/_async/tasks.py,sha256=K7xDIPO_ZHga_1ShssIiCuMe8_sx1fWU9a5zQwm_8d0,17377
|
|
40
40
|
fleet/_async/env/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
41
|
fleet/_async/env/client.py,sha256=C5WG5Ir_McXaFPZNdkQjj0w4V7xMIcw3QyVP5g-3kVk,1237
|
|
42
42
|
fleet/_async/instance/__init__.py,sha256=PtmJq8J8bh0SOQ2V55QURz5GJfobozwtQoqhaOk3_tI,515
|
|
@@ -69,12 +69,12 @@ fleet/verifiers/decorator.py,sha256=nAP3O8szXu7md_kpwpz91hGSUNEVLYjwZQZTkQlV1DM,
|
|
|
69
69
|
fleet/verifiers/parse.py,sha256=qz9AfJrTbjlg-LU-lE8Ciqi7Yt2a8-cs17FdpjTLhMk,8550
|
|
70
70
|
fleet/verifiers/sql_differ.py,sha256=TqTLWyK3uOyLbitT6HYzYEzuSFC39wcyhgk3rcm__k8,6525
|
|
71
71
|
fleet/verifiers/verifier.py,sha256=_lcxXVm8e0xRrK2gNJy9up7pW1zOkPRY5n5lQ85S8jg,14197
|
|
72
|
-
fleet_python-0.2.
|
|
72
|
+
fleet_python-0.2.63.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
73
73
|
scripts/fix_sync_imports.py,sha256=X9fWLTpiPGkSHsjyQUDepOJkxOqw1DPj7nd8wFlFqLQ,8368
|
|
74
74
|
scripts/unasync.py,sha256=vWVQxRWX8SRZO5cmzEhpvnG_REhCWXpidIGIpWmEcvI,696
|
|
75
75
|
tests/__init__.py,sha256=Re1SdyxH8NfyL1kjhi7SQkGP1mYeWB-D6UALqdIMd8I,35
|
|
76
76
|
tests/test_verifier_from_string.py,sha256=Lxi3TpFHFb-hG4-UhLKZJkqo84ax9YJY8G6beO-1erM,13581
|
|
77
|
-
fleet_python-0.2.
|
|
78
|
-
fleet_python-0.2.
|
|
79
|
-
fleet_python-0.2.
|
|
80
|
-
fleet_python-0.2.
|
|
77
|
+
fleet_python-0.2.63.dist-info/METADATA,sha256=Qe5K9wBiRkdNI6PUnExcW3zQDG_MjpOvVfnpNAB1gJo,3304
|
|
78
|
+
fleet_python-0.2.63.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
79
|
+
fleet_python-0.2.63.dist-info/top_level.txt,sha256=qb1zIbtEktyhRFZdqVytwg54l64qtoZL0wjHB4bUg3c,29
|
|
80
|
+
fleet_python-0.2.63.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|