fleet-python 0.2.52__py3-none-any.whl → 0.2.54__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.

@@ -0,0 +1,16 @@
1
+ import asyncio
2
+ import fleet
3
+ from dotenv import load_dotenv
4
+
5
+ load_dotenv()
6
+
7
+
8
+ async def main():
9
+ print(f"Importing tasks... {(await fleet.env.account_async()).team_name}")
10
+ await fleet._async.import_tasks(
11
+ "6bb6c6b6-36a8-4407-ba66-6908e42069c8.json", project_key="amazon"
12
+ )
13
+
14
+
15
+ if __name__ == "__main__":
16
+ asyncio.run(main())
fleet/__init__.py CHANGED
@@ -51,10 +51,17 @@ from ._async.tasks import (
51
51
  Task,
52
52
  load_tasks as load_tasks_async,
53
53
  load_tasks_from_file as load_tasks_from_file_async,
54
+ import_task as import_task_async,
55
+ import_tasks as import_tasks_async,
54
56
  )
55
57
 
56
- # Import sync load_tasks function
57
- from .tasks import load_tasks, load_tasks_from_file
58
+ # Import sync task functions
59
+ from .tasks import (
60
+ load_tasks,
61
+ load_tasks_from_file,
62
+ import_task,
63
+ import_tasks,
64
+ )
58
65
 
59
66
  # Import shared types
60
67
  from .types import VerifierFunction
@@ -104,6 +111,12 @@ __all__ = [
104
111
  # Module-level functions (async is default)
105
112
  "load_tasks",
106
113
  "load_tasks_async",
114
+ "load_tasks_from_file",
115
+ "load_tasks_from_file_async",
116
+ "import_task",
117
+ "import_task_async",
118
+ "import_tasks",
119
+ "import_tasks_async",
107
120
  # Version
108
121
  "__version__",
109
122
  ]
fleet/_async/__init__.py CHANGED
@@ -86,6 +86,7 @@ __all__ = [
86
86
  "load_task_from_string",
87
87
  "load_task_from_json",
88
88
  "export_tasks",
89
+ "import_task",
89
90
  "import_tasks",
90
91
  "account",
91
92
  # Version
@@ -193,13 +194,33 @@ async def export_tasks(
193
194
  return await _async_global_client.get_client().export_tasks(env_key, filename)
194
195
 
195
196
 
196
- async def import_tasks(filename: str):
197
+ async def import_task(task, project_key: Optional[str] = None):
198
+ """Import a single task.
199
+
200
+ Args:
201
+ task: Task object to import
202
+ project_key: Optional project key to associate with the task
203
+
204
+ Example:
205
+ task = fleet.Task(key="my-task", prompt="Do something", env_id="my-env")
206
+ await fleet.import_task(task)
207
+ await fleet.import_task(task, project_key="my-project")
208
+ """
209
+ return await _async_global_client.get_client().import_single_task(task, project_key)
210
+
211
+
212
+ async def import_tasks(filename: str, project_key: Optional[str] = None):
197
213
  """Import tasks from a JSON file.
198
214
 
215
+ Args:
216
+ filename: Path to the JSON file of Task objects to import
217
+ project_key: Optional project key to associate with the tasks
218
+
199
219
  Example:
200
220
  await fleet.import_tasks("tasks.json")
221
+ await fleet.import_tasks("tasks.json", project_key="my-project")
201
222
  """
202
- return await _async_global_client.get_client().import_tasks(filename)
223
+ return await _async_global_client.get_client().import_tasks(filename, project_key)
203
224
 
204
225
 
205
226
  async def account() -> AccountResponse:
fleet/_async/client.py CHANGED
@@ -328,7 +328,9 @@ class AsyncFleet:
328
328
  task_json = json.loads(task_string)
329
329
  return await self.load_task_from_json(task_json)
330
330
 
331
- async def load_task_from_json(self, task_json: Dict) -> Task:
331
+ async def load_task_from_json(
332
+ self, task_json: Dict, raise_on_verifier_error: bool = False
333
+ ) -> Task:
332
334
  verifier = None
333
335
  verifier_code = task_json.get("verifier_func") or task_json.get("verifier_code")
334
336
 
@@ -356,9 +358,11 @@ class AsyncFleet:
356
358
  verifier_sha=task_json.get("verifier_sha", ""),
357
359
  )
358
360
  except Exception as e:
359
- logger.warning(
360
- f"Failed to create verifier {task_json.get('key', task_json.get('id'))}: {e}"
361
- )
361
+ error_msg = f"Failed to create verifier {task_json.get('key', task_json.get('id'))}: {e}"
362
+ if raise_on_verifier_error:
363
+ raise ValueError(error_msg) from e
364
+ else:
365
+ logger.warning(error_msg)
362
366
 
363
367
  task = Task(
364
368
  key=task_json.get("key", task_json.get("id")),
@@ -560,40 +564,71 @@ class AsyncFleet:
560
564
  logger.info("No tasks found to export")
561
565
  return None
562
566
 
563
- async def import_single_task(self, task: Task):
567
+ async def import_single_task(self, task: Task, project_key: Optional[str] = None):
564
568
  """Import a single task.
565
569
 
566
570
  Args:
567
571
  task: Task object to import
572
+ project_key: Optional project key to associate with the task
568
573
 
569
574
  Returns:
570
575
  Response from the API, or None if the import failed
571
576
  """
572
577
  try:
578
+ # Validate that verifier_func exists
579
+ if not task.verifier_func:
580
+ raise ValueError(
581
+ f"Task {task.key} is missing verifier_func. "
582
+ "All tasks must have a verifier_func to be imported."
583
+ )
584
+
585
+ params = {}
586
+ if project_key:
587
+ params["project_key"] = project_key
573
588
  response = await self.client.request(
574
- "POST", "/v1/tasks", json=task.model_dump()
589
+ "POST", "/v1/tasks", json=task.model_dump(), params=params
575
590
  )
576
591
  return response
577
592
  except Exception as e:
578
593
  logger.error(f"Failed to import task {task.key}: {e}")
579
594
  return None
580
595
 
581
- async def import_tasks(self, filename: str):
596
+ async def import_tasks(self, filename: str, project_key: Optional[str] = None):
582
597
  """Import tasks from a JSON file.
583
598
 
584
599
  Args:
585
600
  filename: Path to the JSON file of Task objects to import
601
+ project_key: Optional project key to associate with the tasks
586
602
 
587
603
  Returns:
588
604
  List[Task] containing imported Task objects
605
+
606
+ Raises:
607
+ ValueError: If any task is missing verifier_func or has invalid verifier code
589
608
  """
590
609
  with open(filename, "r", encoding="utf-8") as f:
591
610
  tasks_data = json.load(f)
592
611
 
593
- # Create tasks from the loaded data
612
+ # Create tasks from the loaded data using load_task_from_json
613
+ # This will validate and create verifiers properly
594
614
  tasks = []
595
615
  for task_data in tasks_data:
596
- task = Task(**task_data)
616
+ # Validate that verifier_func exists
617
+ verifier_code = task_data.get("verifier_func") or task_data.get(
618
+ "verifier_code"
619
+ )
620
+ if not verifier_code:
621
+ task_key = task_data.get("key", task_data.get("id", "unknown"))
622
+ raise ValueError(
623
+ f"Task {task_key} is missing verifier_func. "
624
+ "All tasks must have a verifier_func to be imported."
625
+ )
626
+
627
+ # Use load_task_from_json to properly create and validate the task
628
+ # Pass raise_on_verifier_error=True to fail fast on invalid verifier code
629
+ task = await self.load_task_from_json(
630
+ task_data, raise_on_verifier_error=True
631
+ )
597
632
  tasks.append(task)
598
633
 
599
634
  # Use semaphore to limit concurrency to 20
@@ -601,7 +636,7 @@ class AsyncFleet:
601
636
 
602
637
  async def import_with_semaphore(task):
603
638
  async with semaphore:
604
- return await self.import_single_task(task)
639
+ return await self.import_single_task(task, project_key)
605
640
 
606
641
  # Use asyncio.gather to parallelize the imports
607
642
  responses = await asyncio.gather(
fleet/_async/tasks.py CHANGED
@@ -332,3 +332,44 @@ async def update_task(
332
332
  return await client.update_task(
333
333
  task_key=task_key, prompt=prompt, verifier_code=verifier_code
334
334
  )
335
+
336
+
337
+ async def import_task(task: Task, project_key: Optional[str] = None):
338
+ """Convenience function to import a single task.
339
+
340
+ Args:
341
+ task: Task object to import
342
+ project_key: Optional project key to associate with the task
343
+
344
+ Returns:
345
+ Response from the API, or None if the import failed
346
+
347
+ Examples:
348
+ task = fleet.Task(key="my-task", prompt="Do something", env_id="my-env")
349
+ response = await fleet.import_task(task)
350
+ response = await fleet.import_task(task, project_key="my-project")
351
+ """
352
+ from .global_client import get_client
353
+
354
+ client = get_client()
355
+ return await client.import_single_task(task, project_key=project_key)
356
+
357
+
358
+ async def import_tasks(filename: str, project_key: Optional[str] = None):
359
+ """Convenience function to import tasks from a JSON file.
360
+
361
+ Args:
362
+ filename: Path to the JSON file of Task objects to import
363
+ project_key: Optional project key to associate with the tasks
364
+
365
+ Returns:
366
+ List of responses from the API for successfully imported tasks
367
+
368
+ Examples:
369
+ responses = await fleet.import_tasks("tasks.json")
370
+ responses = await fleet.import_tasks("tasks.json", project_key="my-project")
371
+ """
372
+ from .global_client import get_client
373
+
374
+ client = get_client()
375
+ return await client.import_tasks(filename, project_key=project_key)
fleet/client.py CHANGED
@@ -326,7 +326,9 @@ class Fleet:
326
326
  task_json = json.loads(task_string)
327
327
  return self.load_task_from_json(task_json)
328
328
 
329
- def load_task_from_json(self, task_json: Dict) -> Task:
329
+ def load_task_from_json(
330
+ self, task_json: Dict, raise_on_verifier_error: bool = False
331
+ ) -> Task:
330
332
  verifier = None
331
333
  verifier_code = task_json.get("verifier_func") or task_json.get("verifier_code")
332
334
 
@@ -354,9 +356,11 @@ class Fleet:
354
356
  verifier_sha=task_json.get("verifier_sha", ""),
355
357
  )
356
358
  except Exception as e:
357
- logger.warning(
358
- f"Failed to create verifier {task_json.get('key', task_json.get('id'))}: {e}"
359
- )
359
+ error_msg = f"Failed to create verifier {task_json.get('key', task_json.get('id'))}: {e}"
360
+ if raise_on_verifier_error:
361
+ raise ValueError(error_msg) from e
362
+ else:
363
+ logger.warning(error_msg)
360
364
 
361
365
  task = Task(
362
366
  key=task_json.get("key", task_json.get("id")),
@@ -566,43 +570,76 @@ class Fleet:
566
570
  logger.info("No tasks found to export")
567
571
  return None
568
572
 
569
- def import_single_task(self, task: Task):
573
+ def import_single_task(self, task: Task, project_key: Optional[str] = None):
570
574
  """Import a single task.
571
575
 
572
576
  Args:
573
577
  task: Task object to import
578
+ project_key: Optional project key to associate with the task
574
579
 
575
580
  Returns:
576
581
  Response from the API, or None if the import failed
577
582
  """
578
583
  try:
579
- response = self.client.request("POST", "/v1/tasks", json=task.model_dump())
584
+ # Validate that verifier_func exists
585
+ if not task.verifier_func:
586
+ raise ValueError(
587
+ f"Task {task.key} is missing verifier_func. "
588
+ "All tasks must have a verifier_func to be imported."
589
+ )
590
+
591
+ params = {}
592
+ if project_key:
593
+ params["project_key"] = project_key
594
+ response = self.client.request(
595
+ "POST", "/v1/tasks", json=task.model_dump(), params=params
596
+ )
580
597
  return response
581
598
  except Exception as e:
582
599
  logger.error(f"Failed to import task {task.key}: {e}")
583
600
  return None
584
601
 
585
- def import_tasks(self, filename: str):
602
+ def import_tasks(self, filename: str, project_key: Optional[str] = None):
586
603
  """Import tasks from a JSON file.
587
604
 
588
605
  Args:
589
606
  filename: Path to the JSON file of Task objects to import
607
+ project_key: Optional project key to associate with the tasks
590
608
 
591
609
  Returns:
592
610
  List[Task] containing imported Task objects
611
+
612
+ Raises:
613
+ ValueError: If any task is missing verifier_func or has invalid verifier code
593
614
  """
594
615
  with open(filename, "r", encoding="utf-8") as f:
595
616
  tasks_data = json.load(f)
596
617
 
597
- # Create tasks from the loaded data
618
+ # Create tasks from the loaded data using load_task_from_json
619
+ # This will validate and create verifiers properly
598
620
  tasks = []
599
621
  for task_data in tasks_data:
600
- task = Task(**task_data)
622
+ # Validate that verifier_func exists
623
+ verifier_code = task_data.get("verifier_func") or task_data.get(
624
+ "verifier_code"
625
+ )
626
+ if not verifier_code:
627
+ task_key = task_data.get("key", task_data.get("id", "unknown"))
628
+ raise ValueError(
629
+ f"Task {task_key} is missing verifier_func. "
630
+ "All tasks must have a verifier_func to be imported."
631
+ )
632
+
633
+ # Use load_task_from_json to properly create and validate the task
634
+ # Pass raise_on_verifier_error=True to fail fast on invalid verifier code
635
+ task = self.load_task_from_json(task_data, raise_on_verifier_error=True)
601
636
  tasks.append(task)
602
637
 
603
638
  # Use ThreadPoolExecutor to parallelize the imports with max 20 workers
604
639
  with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
605
- responses = list(executor.map(self.import_single_task, tasks))
640
+ responses = list(
641
+ executor.map(lambda t: self.import_single_task(t, project_key), tasks)
642
+ )
606
643
 
607
644
  # Filter out None values (failed imports)
608
645
  return [r for r in responses if r is not None]
fleet/tasks.py CHANGED
@@ -335,3 +335,44 @@ def update_task(
335
335
  return client.update_task(
336
336
  task_key=task_key, prompt=prompt, verifier_code=verifier_code
337
337
  )
338
+
339
+
340
+ def import_task(task: Task, project_key: Optional[str] = None):
341
+ """Convenience function to import a single task.
342
+
343
+ Args:
344
+ task: Task object to import
345
+ project_key: Optional project key to associate with the task
346
+
347
+ Returns:
348
+ Response from the API, or None if the import failed
349
+
350
+ Examples:
351
+ task = fleet.Task(key="my-task", prompt="Do something", env_id="my-env")
352
+ response = fleet.import_task(task)
353
+ response = fleet.import_task(task, project_key="my-project")
354
+ """
355
+ from .global_client import get_client
356
+
357
+ client = get_client()
358
+ return client.import_single_task(task, project_key=project_key)
359
+
360
+
361
+ def import_tasks(filename: str, project_key: Optional[str] = None):
362
+ """Convenience function to import tasks from a JSON file.
363
+
364
+ Args:
365
+ filename: Path to the JSON file of Task objects to import
366
+ project_key: Optional project key to associate with the tasks
367
+
368
+ Returns:
369
+ List of responses from the API for successfully imported tasks
370
+
371
+ Examples:
372
+ responses = fleet.import_tasks("tasks.json")
373
+ responses = fleet.import_tasks("tasks.json", project_key="my-project")
374
+ """
375
+ from .global_client import get_client
376
+
377
+ client = get_client()
378
+ return client.import_tasks(filename, project_key=project_key)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.52
3
+ Version: 0.2.54
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -12,6 +12,7 @@ examples/example_task.py,sha256=dhG6STAkNsTdHs9cO1RFH9WfuvRmq5bRC211hTeFrk8,7088
12
12
  examples/example_tasks.py,sha256=xTL8UWVAuolSX6swskfrAcmDrLIzn45dJ7YPWCwoEBU,514
13
13
  examples/example_verifier.py,sha256=0vwNITIG3m4CkSPwIxNXcGx9TqrxEsCGqK2A8keKZMM,2392
14
14
  examples/gemini_example.py,sha256=qj9WDazQTYNiRHNeUg9Tjkp33lJMwbx8gDfpFe1sDQo,16180
15
+ examples/import_tasks.py,sha256=InZdnnL8KfTy8JkuZPlsgFvdU7h2LrdpQNa2XA9VR88,343
15
16
  examples/json_tasks_example.py,sha256=CYPESGGtOo0fmsDdLidujTfsE4QlJHw7rOhyVqPJ_Ls,5329
16
17
  examples/nova_act_example.py,sha256=rH23Lp74Okf0rn8ynMdWjK2aviEf5NLPH4k_53Pyxho,831
17
18
  examples/openai_example.py,sha256=dEWERrTEP5xBiGkLkQjBQGd2NqoxX6gcW6XteBPsWFQ,8231
@@ -19,22 +20,22 @@ examples/openai_simple_example.py,sha256=HmiufucrAZne7tHq9uoEsDWlEhjNC265bQAyIGB
19
20
  examples/query_builder_example.py,sha256=-cOMfWGNifYfYEt_Ds73XpwATZvFDL6F4KTkVxdMjzg,3951
20
21
  examples/quickstart.py,sha256=1VT39IRRhemsJgxi0O0gprdpcw7HB4pYO97GAYagIcg,3788
21
22
  examples/test_cdp_logging.py,sha256=AkCwQCgOTQEI8w3v0knWK_4eXMph7L9x07wj9yIYM10,2836
22
- fleet/__init__.py,sha256=Mkdeh45N47lnSv73Eehj92cGU-AImUitvDWJLFhEp0Y,3844
23
+ fleet/__init__.py,sha256=fwIcuaJPPdLMdKPsazfz4EAPeJchl9MBN4nxs0YlOjw,4117
23
24
  fleet/base.py,sha256=bc-340sTpq_DJs7yQ9d2pDWnmJFmA1SwDB9Lagvqtb4,9182
24
- fleet/client.py,sha256=eLo_yie4xUAV2SgeyNIIY-CUhdhp0K5zHr-XEQUw-S8,27444
25
+ fleet/client.py,sha256=qG2nowkeDqitqDhAbYwoGtnXkau3nTwmkUGzN0iPgOk,29201
25
26
  fleet/config.py,sha256=uY02ZKxVoXqVDta-0IMWaYJeE1CTXF_fA9NI6QUutmU,319
26
27
  fleet/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
27
28
  fleet/global_client.py,sha256=frrDAFNM2ywN0JHLtlm9qbE1dQpnQJsavJpb7xSR_bU,1072
28
29
  fleet/models.py,sha256=d9eish0KO3t4VCNu8h8Q_6K1Xj-crYo5Fejtle0Ur28,13056
29
- fleet/tasks.py,sha256=uR94wq7SG4ymJYLq24F2iYn0el58C2Czb2oK-8rIs8s,12344
30
+ fleet/tasks.py,sha256=uzGKwbLDKlNpuPjUTeF7N2FG_tez3JwiyHYLYt5rBSI,13660
30
31
  fleet/types.py,sha256=L4Y82xICf1tzyCLqhLYUgEoaIIS5h9T05TyFNHSWs3s,652
31
- fleet/_async/__init__.py,sha256=7C_JaEHoqZ4cddsCmlJ4z-UaU6Kr2CBZSgwx5B6fqnc,6765
32
+ fleet/_async/__init__.py,sha256=ruGtdMl9BRQRsJygNszPT89ZbMy6AYv1mmeYoB--r60,7557
32
33
  fleet/_async/base.py,sha256=oisVTQsx0M_yTmyQJc3oij63uKZ97MHz-xYFsWXxQE8,9202
33
- fleet/_async/client.py,sha256=UIF0t-GgLdJeZLJqzsE9gVuzEesj7O8wWPVgjF45tso,27917
34
+ fleet/_async/client.py,sha256=SbateFBfFDRju-gHtFr8TQdR0thBNA0rWt0RuUse9s0,29637
34
35
  fleet/_async/exceptions.py,sha256=fUmPwWhnT8SR97lYsRq0kLHQHKtSh2eJS0VQ2caSzEI,5055
35
36
  fleet/_async/global_client.py,sha256=4WskpLHbsDEgWW7hXMD09W-brkp4euy8w2ZJ88594rQ,1103
36
37
  fleet/_async/models.py,sha256=GX-sRciZDenW2O7Qx9w_ftOkJyE4ph1-92WMq6lynHE,12856
37
- fleet/_async/tasks.py,sha256=hrtvKlqepQOFnlJv6h5S06UWNWtn2hQlgSp3eYj5m30,12226
38
+ fleet/_async/tasks.py,sha256=t51pK4gBZZOmtJs35wjEorxKIgDeIvPxwCtGRs00Tpg,13590
38
39
  fleet/_async/env/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
40
  fleet/_async/env/client.py,sha256=C5WG5Ir_McXaFPZNdkQjj0w4V7xMIcw3QyVP5g-3kVk,1237
40
41
  fleet/_async/instance/__init__.py,sha256=PtmJq8J8bh0SOQ2V55QURz5GJfobozwtQoqhaOk3_tI,515
@@ -67,10 +68,10 @@ fleet/verifiers/decorator.py,sha256=nAP3O8szXu7md_kpwpz91hGSUNEVLYjwZQZTkQlV1DM,
67
68
  fleet/verifiers/parse.py,sha256=qz9AfJrTbjlg-LU-lE8Ciqi7Yt2a8-cs17FdpjTLhMk,8550
68
69
  fleet/verifiers/sql_differ.py,sha256=TqTLWyK3uOyLbitT6HYzYEzuSFC39wcyhgk3rcm__k8,6525
69
70
  fleet/verifiers/verifier.py,sha256=_lcxXVm8e0xRrK2gNJy9up7pW1zOkPRY5n5lQ85S8jg,14197
70
- fleet_python-0.2.52.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
71
+ fleet_python-0.2.54.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
71
72
  scripts/fix_sync_imports.py,sha256=X9fWLTpiPGkSHsjyQUDepOJkxOqw1DPj7nd8wFlFqLQ,8368
72
73
  scripts/unasync.py,sha256=vWVQxRWX8SRZO5cmzEhpvnG_REhCWXpidIGIpWmEcvI,696
73
- fleet_python-0.2.52.dist-info/METADATA,sha256=5XJkEis8IQs2W8ITyyU7a1LmZ3XqzrweVTFHCltP7zw,3304
74
- fleet_python-0.2.52.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
75
- fleet_python-0.2.52.dist-info/top_level.txt,sha256=_3DSmTohvSDf3AIP_BYfGzhwO1ECFwuzg83X-wHCx3Y,23
76
- fleet_python-0.2.52.dist-info/RECORD,,
74
+ fleet_python-0.2.54.dist-info/METADATA,sha256=tkesOoS66aveH_fYtJvJoYi2ErjrkiApcXbx1bUh1Eo,3304
75
+ fleet_python-0.2.54.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
76
+ fleet_python-0.2.54.dist-info/top_level.txt,sha256=_3DSmTohvSDf3AIP_BYfGzhwO1ECFwuzg83X-wHCx3Y,23
77
+ fleet_python-0.2.54.dist-info/RECORD,,