fleet-python 0.2.77__tar.gz → 0.2.79__tar.gz

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.
Files changed (92) hide show
  1. {fleet_python-0.2.77/fleet_python.egg-info → fleet_python-0.2.79}/PKG-INFO +1 -1
  2. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/__init__.py +1 -1
  3. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/__init__.py +1 -1
  4. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/base.py +1 -1
  5. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/client.py +19 -1
  6. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/resources/sqlite.py +71 -0
  7. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/base.py +1 -1
  8. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/client.py +19 -1
  9. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/resources/sqlite.py +71 -0
  10. {fleet_python-0.2.77 → fleet_python-0.2.79/fleet_python.egg-info}/PKG-INFO +1 -1
  11. {fleet_python-0.2.77 → fleet_python-0.2.79}/pyproject.toml +1 -1
  12. {fleet_python-0.2.77 → fleet_python-0.2.79}/LICENSE +0 -0
  13. {fleet_python-0.2.77 → fleet_python-0.2.79}/README.md +0 -0
  14. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/diff_example.py +0 -0
  15. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/dsl_example.py +0 -0
  16. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example.py +0 -0
  17. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/exampleResume.py +0 -0
  18. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_account.py +0 -0
  19. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_action_log.py +0 -0
  20. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_client.py +0 -0
  21. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_mcp_anthropic.py +0 -0
  22. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_mcp_openai.py +0 -0
  23. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_sync.py +0 -0
  24. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_task.py +0 -0
  25. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_tasks.py +0 -0
  26. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/example_verifier.py +0 -0
  27. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/export_tasks.py +0 -0
  28. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/fetch_tasks.py +0 -0
  29. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/gemini_example.py +0 -0
  30. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/import_tasks.py +0 -0
  31. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/iterate_verifiers.py +0 -0
  32. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/json_tasks_example.py +0 -0
  33. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/nova_act_example.py +0 -0
  34. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/openai_example.py +0 -0
  35. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/openai_simple_example.py +0 -0
  36. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/query_builder_example.py +0 -0
  37. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/quickstart.py +0 -0
  38. {fleet_python-0.2.77 → fleet_python-0.2.79}/examples/test_cdp_logging.py +0 -0
  39. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/env/__init__.py +0 -0
  40. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/env/client.py +0 -0
  41. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/exceptions.py +0 -0
  42. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/global_client.py +0 -0
  43. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/instance/__init__.py +0 -0
  44. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/instance/base.py +0 -0
  45. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/instance/client.py +0 -0
  46. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/models.py +0 -0
  47. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/resources/__init__.py +0 -0
  48. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/resources/base.py +0 -0
  49. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/resources/browser.py +0 -0
  50. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/resources/mcp.py +0 -0
  51. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/tasks.py +0 -0
  52. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/verifiers/__init__.py +0 -0
  53. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/verifiers/bundler.py +0 -0
  54. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/_async/verifiers/verifier.py +0 -0
  55. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/config.py +0 -0
  56. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/env/__init__.py +0 -0
  57. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/env/client.py +0 -0
  58. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/exceptions.py +0 -0
  59. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/global_client.py +0 -0
  60. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/instance/__init__.py +0 -0
  61. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/instance/base.py +0 -0
  62. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/instance/client.py +0 -0
  63. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/instance/models.py +0 -0
  64. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/models.py +0 -0
  65. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/resources/__init__.py +0 -0
  66. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/resources/base.py +0 -0
  67. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/resources/browser.py +0 -0
  68. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/resources/mcp.py +0 -0
  69. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/tasks.py +0 -0
  70. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/types.py +0 -0
  71. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/__init__.py +0 -0
  72. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/bundler.py +0 -0
  73. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/code.py +0 -0
  74. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/db.py +0 -0
  75. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/decorator.py +0 -0
  76. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/parse.py +0 -0
  77. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/sql_differ.py +0 -0
  78. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet/verifiers/verifier.py +0 -0
  79. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet_python.egg-info/SOURCES.txt +0 -0
  80. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet_python.egg-info/dependency_links.txt +0 -0
  81. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet_python.egg-info/requires.txt +0 -0
  82. {fleet_python-0.2.77 → fleet_python-0.2.79}/fleet_python.egg-info/top_level.txt +0 -0
  83. {fleet_python-0.2.77 → fleet_python-0.2.79}/scripts/fix_sync_imports.py +0 -0
  84. {fleet_python-0.2.77 → fleet_python-0.2.79}/scripts/unasync.py +0 -0
  85. {fleet_python-0.2.77 → fleet_python-0.2.79}/setup.cfg +0 -0
  86. {fleet_python-0.2.77 → fleet_python-0.2.79}/tests/__init__.py +0 -0
  87. {fleet_python-0.2.77 → fleet_python-0.2.79}/tests/test_app_method.py +0 -0
  88. {fleet_python-0.2.77 → fleet_python-0.2.79}/tests/test_expect_only.py +0 -0
  89. {fleet_python-0.2.77 → fleet_python-0.2.79}/tests/test_instance_dispatch.py +0 -0
  90. {fleet_python-0.2.77 → fleet_python-0.2.79}/tests/test_sqlite_resource_dual_mode.py +0 -0
  91. {fleet_python-0.2.77 → fleet_python-0.2.79}/tests/test_sqlite_shared_memory_behavior.py +0 -0
  92. {fleet_python-0.2.77 → fleet_python-0.2.79}/tests/test_verifier_from_string.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.77
3
+ Version: 0.2.79
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -73,7 +73,7 @@ from . import env
73
73
  from . import global_client as _global_client
74
74
  from ._async import global_client as _async_global_client
75
75
 
76
- __version__ = "0.2.74"
76
+ __version__ = "0.2.79"
77
77
 
78
78
  __all__ = [
79
79
  # Core classes
@@ -44,7 +44,7 @@ from ..types import VerifierFunction
44
44
  from .. import env
45
45
  from . import global_client as _async_global_client
46
46
 
47
- __version__ = "0.2.74"
47
+ __version__ = "0.2.79"
48
48
 
49
49
  __all__ = [
50
50
  # Core classes
@@ -26,7 +26,7 @@ from .exceptions import (
26
26
  try:
27
27
  from .. import __version__
28
28
  except ImportError:
29
- __version__ = "0.2.74"
29
+ __version__ = "0.2.79"
30
30
 
31
31
  logger = logging.getLogger(__name__)
32
32
 
@@ -795,6 +795,21 @@ class AsyncFleet:
795
795
  if not is_embedded_error:
796
796
  verifier_func = embedded_code
797
797
 
798
+ # Extract verifier metadata
799
+ verifier_id = task_response.verifier_id
800
+ if not verifier_id and task_response.verifier:
801
+ verifier_id = task_response.verifier.verifier_id
802
+
803
+ verifier_sha = None
804
+ if task_response.verifier:
805
+ verifier_sha = task_response.verifier.sha256
806
+
807
+ # Extract verifier_runtime_version from metadata if present
808
+ verifier_runtime_version = None
809
+ metadata = task_response.metadata or {}
810
+ if isinstance(metadata, dict):
811
+ verifier_runtime_version = metadata.get("verifier_runtime_version")
812
+
798
813
  task = Task(
799
814
  key=task_response.key,
800
815
  prompt=task_response.prompt,
@@ -806,7 +821,10 @@ class AsyncFleet:
806
821
  env_variables=task_response.env_variables or {},
807
822
  verifier_func=verifier_func, # Set verifier code
808
823
  verifier=verifier, # Use created verifier or None
809
- metadata=task_response.metadata or {},
824
+ verifier_id=verifier_id, # Set verifier_id
825
+ verifier_sha=verifier_sha, # Set verifier_sha
826
+ verifier_runtime_version=verifier_runtime_version, # Set verifier_runtime_version
827
+ metadata=metadata,
810
828
  output_json_schema=getattr(task_response, "output_json_schema", None), # Get output_json_schema if available
811
829
  )
812
830
  tasks.append(task)
@@ -1427,6 +1427,77 @@ class AsyncSnapshotDiff:
1427
1427
  diff, allowed_changes
1428
1428
  )
1429
1429
 
1430
+ async def _ensure_all_fetched(self):
1431
+ """Fetch ALL data from ALL tables upfront (non-lazy loading).
1432
+
1433
+ This is the old approach before lazy loading was introduced.
1434
+ Used by expect_only_v1 for simpler, non-optimized diffing.
1435
+ """
1436
+ # Get all tables from before snapshot
1437
+ tables_response = await self.before.resource.query(
1438
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
1439
+ )
1440
+
1441
+ if tables_response.rows:
1442
+ before_tables = [row[0] for row in tables_response.rows]
1443
+ for table in before_tables:
1444
+ await self.before._ensure_table_data(table)
1445
+
1446
+ # Also fetch from after snapshot
1447
+ tables_response = await self.after.resource.query(
1448
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
1449
+ )
1450
+
1451
+ if tables_response.rows:
1452
+ after_tables = [row[0] for row in tables_response.rows]
1453
+ for table in after_tables:
1454
+ await self.after._ensure_table_data(table)
1455
+
1456
+ async def expect_only_v1(self, allowed_changes: List[Dict[str, Any]]):
1457
+ """Ensure only specified changes occurred using the original (non-optimized) approach.
1458
+
1459
+ This version attempts to use the /api/v1/env/diff/structured endpoint if available,
1460
+ falling back to local diff computation if the endpoint is not available.
1461
+
1462
+ Use this when you want the simpler, more predictable behavior of the original
1463
+ implementation without any query optimizations.
1464
+ """
1465
+ # Try to use the structured diff endpoint if we have an HTTP client
1466
+ resource = self.after.resource
1467
+ if resource.client is not None and resource._mode == "http":
1468
+ api_diff = None
1469
+ try:
1470
+ payload = {}
1471
+ if self.ignore_config:
1472
+ payload["ignore_config"] = {
1473
+ "tables": list(self.ignore_config.tables),
1474
+ "fields": list(self.ignore_config.fields),
1475
+ "table_fields": {
1476
+ table: list(fields) for table, fields in self.ignore_config.table_fields.items()
1477
+ }
1478
+ }
1479
+ response = await resource.client.request(
1480
+ "POST",
1481
+ "/diff/structured",
1482
+ json=payload,
1483
+ )
1484
+ result = response.json()
1485
+ if result.get("success") and "diff" in result:
1486
+ api_diff = result["diff"]
1487
+ except Exception as e:
1488
+ # Fall back to local diff if API call fails
1489
+ print(f"Warning: Failed to fetch structured diff from API: {e}")
1490
+ print("Falling back to local diff computation...")
1491
+
1492
+ # Validate outside try block so AssertionError propagates
1493
+ if api_diff is not None:
1494
+ return await self._validate_diff_against_allowed_changes(api_diff, allowed_changes)
1495
+
1496
+ # Fall back to local diff computation
1497
+ await self._ensure_all_fetched()
1498
+ diff = await self._collect()
1499
+ return await self._validate_diff_against_allowed_changes(diff, allowed_changes)
1500
+
1430
1501
 
1431
1502
  class AsyncQueryBuilder:
1432
1503
  """Async query builder that translates DSL to SQL and executes through the API."""
@@ -26,7 +26,7 @@ from .exceptions import (
26
26
  try:
27
27
  from . import __version__
28
28
  except ImportError:
29
- __version__ = "0.2.74"
29
+ __version__ = "0.2.79"
30
30
 
31
31
  logger = logging.getLogger(__name__)
32
32
 
@@ -811,6 +811,21 @@ class Fleet:
811
811
  if not is_embedded_error:
812
812
  verifier_func = embedded_code
813
813
 
814
+ # Extract verifier metadata
815
+ verifier_id = task_response.verifier_id
816
+ if not verifier_id and task_response.verifier:
817
+ verifier_id = task_response.verifier.verifier_id
818
+
819
+ verifier_sha = None
820
+ if task_response.verifier:
821
+ verifier_sha = task_response.verifier.sha256
822
+
823
+ # Extract verifier_runtime_version from metadata if present
824
+ verifier_runtime_version = None
825
+ metadata = task_response.metadata or {}
826
+ if isinstance(metadata, dict):
827
+ verifier_runtime_version = metadata.get("verifier_runtime_version")
828
+
814
829
  task = Task(
815
830
  key=task_response.key,
816
831
  prompt=task_response.prompt,
@@ -822,7 +837,10 @@ class Fleet:
822
837
  env_variables=task_response.env_variables or {},
823
838
  verifier_func=verifier_func, # Set verifier code
824
839
  verifier=verifier, # Use created verifier or None
825
- metadata=task_response.metadata or {},
840
+ verifier_id=verifier_id, # Set verifier_id
841
+ verifier_sha=verifier_sha, # Set verifier_sha
842
+ verifier_runtime_version=verifier_runtime_version, # Set verifier_runtime_version
843
+ metadata=metadata,
826
844
  output_json_schema=getattr(task_response, "output_json_schema", None), # Get output_json_schema if available
827
845
  )
828
846
  tasks.append(task)
@@ -1447,6 +1447,77 @@ class SyncSnapshotDiff:
1447
1447
  diff = self._collect()
1448
1448
  return self._validate_diff_against_allowed_changes_v2(diff, allowed_changes)
1449
1449
 
1450
+ def _ensure_all_fetched(self):
1451
+ """Fetch ALL data from ALL tables upfront (non-lazy loading).
1452
+
1453
+ This is the old approach before lazy loading was introduced.
1454
+ Used by expect_only_v1 for simpler, non-optimized diffing.
1455
+ """
1456
+ # Get all tables
1457
+ tables_response = self.before.resource.query(
1458
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
1459
+ )
1460
+
1461
+ if tables_response.rows:
1462
+ before_tables = [row[0] for row in tables_response.rows]
1463
+ for table in before_tables:
1464
+ self.before._ensure_table_data(table)
1465
+
1466
+ # Also fetch from after snapshot
1467
+ tables_response = self.after.resource.query(
1468
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
1469
+ )
1470
+
1471
+ if tables_response.rows:
1472
+ after_tables = [row[0] for row in tables_response.rows]
1473
+ for table in after_tables:
1474
+ self.after._ensure_table_data(table)
1475
+
1476
+ def expect_only_v1(self, allowed_changes: List[Dict[str, Any]]):
1477
+ """Ensure only specified changes occurred using the original (non-optimized) approach.
1478
+
1479
+ This version attempts to use the /api/v1/env/diff/structured endpoint if available,
1480
+ falling back to local diff computation if the endpoint is not available.
1481
+
1482
+ Use this when you want the simpler, more predictable behavior of the original
1483
+ implementation without any query optimizations.
1484
+ """
1485
+ # Try to use the structured diff endpoint if we have an HTTP client
1486
+ resource = self.after.resource
1487
+ if resource.client is not None and resource._mode == "http":
1488
+ api_diff = None
1489
+ try:
1490
+ payload = {}
1491
+ if self.ignore_config:
1492
+ payload["ignore_config"] = {
1493
+ "tables": list(self.ignore_config.tables),
1494
+ "fields": list(self.ignore_config.fields),
1495
+ "table_fields": {
1496
+ table: list(fields) for table, fields in self.ignore_config.table_fields.items()
1497
+ }
1498
+ }
1499
+ response = resource.client.request(
1500
+ "POST",
1501
+ "/diff/structured",
1502
+ json=payload,
1503
+ )
1504
+ result = response.json()
1505
+ if result.get("success") and "diff" in result:
1506
+ api_diff = result["diff"]
1507
+ except Exception as e:
1508
+ # Fall back to local diff if API call fails
1509
+ print(f"Warning: Failed to fetch structured diff from API: {e}")
1510
+ print("Falling back to local diff computation...")
1511
+
1512
+ # Validate outside try block so AssertionError propagates
1513
+ if api_diff is not None:
1514
+ return self._validate_diff_against_allowed_changes(api_diff, allowed_changes)
1515
+
1516
+ # Fall back to local diff computation
1517
+ self._ensure_all_fetched()
1518
+ diff = self._collect()
1519
+ return self._validate_diff_against_allowed_changes(diff, allowed_changes)
1520
+
1450
1521
 
1451
1522
  class SyncQueryBuilder:
1452
1523
  """Async query builder that translates DSL to SQL and executes through the API."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.77
3
+ Version: 0.2.79
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "fleet-python"
7
7
 
8
- version = "0.2.77"
8
+ version = "0.2.79"
9
9
  description = "Python SDK for Fleet environments"
10
10
  authors = [
11
11
  {name = "Fleet AI", email = "nic@fleet.so"},
File without changes
File without changes
File without changes