fleet-python 0.2.117__tar.gz → 0.2.118__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 (126) hide show
  1. {fleet_python-0.2.117/fleet_python.egg-info → fleet_python-0.2.118}/PKG-INFO +1 -1
  2. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/__init__.py +3 -1
  3. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/__init__.py +1 -1
  4. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/base.py +1 -1
  5. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/client.py +29 -0
  6. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/base.py +1 -1
  7. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/client.py +26 -0
  8. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/__init__.py +2 -1
  9. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/local_executor.py +127 -3
  10. {fleet_python-0.2.117 → fleet_python-0.2.118/fleet_python.egg-info}/PKG-INFO +1 -1
  11. {fleet_python-0.2.117 → fleet_python-0.2.118}/pyproject.toml +1 -1
  12. {fleet_python-0.2.117 → fleet_python-0.2.118}/LICENSE +0 -0
  13. {fleet_python-0.2.117 → fleet_python-0.2.118}/README.md +0 -0
  14. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/diff_example.py +0 -0
  15. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/dsl_example.py +0 -0
  16. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example.py +0 -0
  17. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/exampleResume.py +0 -0
  18. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_account.py +0 -0
  19. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_action_log.py +0 -0
  20. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_client.py +0 -0
  21. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_mcp_anthropic.py +0 -0
  22. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_mcp_openai.py +0 -0
  23. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_sync.py +0 -0
  24. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_task.py +0 -0
  25. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_tasks.py +0 -0
  26. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_verifier.py +0 -0
  27. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/export_tasks.py +0 -0
  28. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/export_tasks_filtered.py +0 -0
  29. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/fetch_tasks.py +0 -0
  30. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/gemini_example.py +0 -0
  31. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/import_tasks.py +0 -0
  32. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/iterate_verifiers.py +0 -0
  33. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/json_tasks_example.py +0 -0
  34. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/nova_act_example.py +0 -0
  35. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/openai_example.py +0 -0
  36. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/openai_simple_example.py +0 -0
  37. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/query_builder_example.py +0 -0
  38. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/quickstart.py +0 -0
  39. {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/test_cdp_logging.py +0 -0
  40. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/env/__init__.py +0 -0
  41. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/env/client.py +0 -0
  42. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/exceptions.py +0 -0
  43. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/global_client.py +0 -0
  44. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/instance/__init__.py +0 -0
  45. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/instance/base.py +0 -0
  46. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/instance/client.py +0 -0
  47. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/judge.py +0 -0
  48. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/models.py +0 -0
  49. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/__init__.py +0 -0
  50. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/api.py +0 -0
  51. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/base.py +0 -0
  52. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/browser.py +0 -0
  53. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/filesystem.py +0 -0
  54. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/mcp.py +0 -0
  55. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/sqlite.py +0 -0
  56. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/tasks.py +0 -0
  57. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/verifiers/__init__.py +0 -0
  58. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/verifiers/bundler.py +0 -0
  59. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/verifiers/verifier.py +0 -0
  60. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/__init__.py +0 -0
  61. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/Dockerfile +0 -0
  62. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/__init__.py +0 -0
  63. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/agent.py +0 -0
  64. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp/main.py +0 -0
  65. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp_server/__init__.py +0 -0
  66. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp_server/main.py +0 -0
  67. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp_server/tools.py +0 -0
  68. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/requirements.txt +0 -0
  69. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/start.sh +0 -0
  70. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/orchestrator.py +0 -0
  71. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/types.py +0 -0
  72. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/utils.py +0 -0
  73. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/cli.py +0 -0
  74. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/config.py +0 -0
  75. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/env/__init__.py +0 -0
  76. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/env/client.py +0 -0
  77. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/eval/__init__.py +0 -0
  78. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/eval/uploader.py +0 -0
  79. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/exceptions.py +0 -0
  80. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/global_client.py +0 -0
  81. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/__init__.py +0 -0
  82. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/base.py +0 -0
  83. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/client.py +0 -0
  84. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/models.py +0 -0
  85. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/judge.py +0 -0
  86. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/models.py +0 -0
  87. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/proxy/__init__.py +0 -0
  88. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/proxy/proxy.py +0 -0
  89. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/proxy/whitelist.py +0 -0
  90. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/__init__.py +0 -0
  91. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/api.py +0 -0
  92. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/base.py +0 -0
  93. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/browser.py +0 -0
  94. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/filesystem.py +0 -0
  95. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/mcp.py +0 -0
  96. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/sqlite.py +0 -0
  97. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/tasks.py +0 -0
  98. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/types.py +0 -0
  99. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/__init__.py +0 -0
  100. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/http_logging.py +0 -0
  101. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/logging.py +0 -0
  102. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/playwright.py +0 -0
  103. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/bundler.py +0 -0
  104. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/code.py +0 -0
  105. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/db.py +0 -0
  106. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/decorator.py +0 -0
  107. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/parse.py +0 -0
  108. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/sql_differ.py +0 -0
  109. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/verifier.py +0 -0
  110. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/SOURCES.txt +0 -0
  111. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/dependency_links.txt +0 -0
  112. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/entry_points.txt +0 -0
  113. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/requires.txt +0 -0
  114. {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/top_level.txt +0 -0
  115. {fleet_python-0.2.117 → fleet_python-0.2.118}/scripts/fix_sync_imports.py +0 -0
  116. {fleet_python-0.2.117 → fleet_python-0.2.118}/scripts/unasync.py +0 -0
  117. {fleet_python-0.2.117 → fleet_python-0.2.118}/setup.cfg +0 -0
  118. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/__init__.py +0 -0
  119. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_app_method.py +0 -0
  120. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_expect_exactly.py +0 -0
  121. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_expect_only.py +0 -0
  122. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_instance_dispatch.py +0 -0
  123. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_judge_criteria_markers.py +0 -0
  124. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_sqlite_resource_dual_mode.py +0 -0
  125. {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_sqlite_shared_memory_behavior.py +0 -0
  126. {fleet_python-0.2.117 → fleet_python-0.2.118}/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.117
3
+ Version: 0.2.118
4
4
  Summary: Python SDK for Fleet environments
5
5
  Author-email: Fleet AI <nic@fleet.so>
6
6
  License: Apache-2.0
@@ -40,6 +40,7 @@ from .verifiers import (
40
40
  TASK_SUCCESSFUL_SCORE,
41
41
  execute_verifier_local,
42
42
  LocalEnvironment,
43
+ diff_dbs,
43
44
  )
44
45
 
45
46
  # Import async verifiers (default verifier is async for modern usage)
@@ -78,7 +79,7 @@ from . import env
78
79
  from . import global_client as _global_client
79
80
  from ._async import global_client as _async_global_client
80
81
 
81
- __version__ = "0.2.117"
82
+ __version__ = "0.2.118"
82
83
 
83
84
  __all__ = [
84
85
  # Core classes
@@ -118,6 +119,7 @@ __all__ = [
118
119
  "TASK_SUCCESSFUL_SCORE",
119
120
  "execute_verifier_local",
120
121
  "LocalEnvironment",
122
+ "diff_dbs",
121
123
  # Environment module
122
124
  "env",
123
125
  # Global client helpers
@@ -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.117"
47
+ __version__ = "0.2.118"
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.117"
29
+ __version__ = "0.2.118"
30
30
 
31
31
  logger = logging.getLogger(__name__)
32
32
 
@@ -871,6 +871,35 @@ class AsyncFleet:
871
871
  execute_verifier_local, verifier_func, seed_db, current_db, final_answer
872
872
  )
873
873
 
874
+ @staticmethod
875
+ async def diff_dbs(
876
+ seed_db: str,
877
+ current_db: str,
878
+ ignore_tables: Optional[set] = None,
879
+ ignore_table_fields: Optional[Dict[str, set]] = None,
880
+ ) -> Dict[str, Any]:
881
+ """Compute a structured diff between two local SQLite databases.
882
+
883
+ Returns the same format as the runner's ``/diff/structured`` endpoint.
884
+ No authentication or network access required.
885
+
886
+ Args:
887
+ seed_db: Path to the seed (before) SQLite database file.
888
+ current_db: Path to the current (after) SQLite database file.
889
+ ignore_tables: Optional set of table names to skip entirely.
890
+ ignore_table_fields: Optional mapping of ``{table: {field, ...}}``
891
+ to strip from the output.
892
+
893
+ Returns:
894
+ Dict with keys ``success``, ``diff``, and ``message``.
895
+ """
896
+ import asyncio
897
+ from ..verifiers.local_executor import diff_dbs
898
+
899
+ return await asyncio.to_thread(
900
+ diff_dbs, seed_db, current_db, ignore_tables, ignore_table_fields
901
+ )
902
+
874
903
  async def list_runs(
875
904
  self, profile_id: Optional[str] = None, status: Optional[str] = "active"
876
905
  ) -> List[Run]:
@@ -27,7 +27,7 @@ from .exceptions import (
27
27
  try:
28
28
  from . import __version__
29
29
  except ImportError:
30
- __version__ = "0.2.117"
30
+ __version__ = "0.2.118"
31
31
 
32
32
  logger = logging.getLogger(__name__)
33
33
 
@@ -880,6 +880,32 @@ class Fleet:
880
880
 
881
881
  return execute_verifier_local(verifier_func, seed_db, current_db, final_answer)
882
882
 
883
+ @staticmethod
884
+ def diff_dbs(
885
+ seed_db: str,
886
+ current_db: str,
887
+ ignore_tables: Optional[set] = None,
888
+ ignore_table_fields: Optional[Dict[str, set]] = None,
889
+ ) -> Dict[str, Any]:
890
+ """Compute a structured diff between two local SQLite databases.
891
+
892
+ Returns the same format as the runner's ``/diff/structured`` endpoint.
893
+ No authentication or network access required.
894
+
895
+ Args:
896
+ seed_db: Path to the seed (before) SQLite database file.
897
+ current_db: Path to the current (after) SQLite database file.
898
+ ignore_tables: Optional set of table names to skip entirely.
899
+ ignore_table_fields: Optional mapping of ``{table: {field, ...}}``
900
+ to strip from the output.
901
+
902
+ Returns:
903
+ Dict with keys ``success``, ``diff``, and ``message``.
904
+ """
905
+ from .verifiers.local_executor import diff_dbs
906
+
907
+ return diff_dbs(seed_db, current_db, ignore_tables, ignore_table_fields)
908
+
883
909
  def list_runs(
884
910
  self, profile_id: Optional[str] = None, status: Optional[str] = "active"
885
911
  ) -> List[Run]:
@@ -6,7 +6,7 @@ from .verifier import (
6
6
  verifier,
7
7
  SyncVerifierFunction,
8
8
  )
9
- from .local_executor import execute_verifier_local, LocalEnvironment
9
+ from .local_executor import execute_verifier_local, LocalEnvironment, diff_dbs
10
10
 
11
11
  __all__ = [
12
12
  "DatabaseSnapshot",
@@ -18,4 +18,5 @@ __all__ = [
18
18
  "SyncVerifierFunction",
19
19
  "execute_verifier_local",
20
20
  "LocalEnvironment",
21
+ "diff_dbs",
21
22
  ]
@@ -1,7 +1,8 @@
1
- """Local verifier execution against SQLite files.
1
+ """Local verifier execution and database diffing against SQLite files.
2
2
 
3
- Executes verifier function code directly against local SQLite database files,
4
- without requiring authentication or a remote runner API server.
3
+ Executes verifier function code directly against local SQLite database files
4
+ and computes structured diffs, without requiring authentication or a remote
5
+ runner API server.
5
6
  """
6
7
 
7
8
  import inspect
@@ -245,3 +246,126 @@ def execute_verifier_local(
245
246
  "error": error_msg,
246
247
  "stdout": captured_stdout.getvalue(),
247
248
  }
249
+
250
+
251
+ # ---------------------------------------------------------------------------
252
+ # Structured database diff (matches /diff/structured response format)
253
+ # ---------------------------------------------------------------------------
254
+
255
+ def diff_dbs(
256
+ seed_db: str,
257
+ current_db: str,
258
+ ignore_tables: Optional[set] = None,
259
+ ignore_table_fields: Optional[dict] = None,
260
+ ) -> Dict[str, Any]:
261
+ """Compute a structured diff between two SQLite databases locally.
262
+
263
+ Returns the exact same format as the runner's ``/diff/structured`` endpoint:
264
+
265
+ .. code-block:: python
266
+
267
+ {
268
+ "success": True,
269
+ "diff": {
270
+ "table_name": {
271
+ "table_name": str,
272
+ "primary_key": [str],
273
+ "added_rows": [{"row_id": ..., "data": {...}}],
274
+ "removed_rows": [{"row_id": ..., "data": {...}}],
275
+ "modified_rows": [{"row_id": ..., "changes": {...}, "data": {...}}],
276
+ "unchanged_count": int,
277
+ "total_changes": int,
278
+ }
279
+ },
280
+ "message": str,
281
+ }
282
+
283
+ No authentication or network access required.
284
+
285
+ Args:
286
+ seed_db: Path to the seed (before) SQLite database file.
287
+ current_db: Path to the current (after) SQLite database file.
288
+ ignore_tables: Optional set of table names to skip entirely.
289
+ ignore_table_fields: Optional mapping of ``{table_name: {field, ...}}``
290
+ whose fields are stripped from the diff output.
291
+
292
+ Returns:
293
+ Dict matching the ``StructuredDiffResponse`` schema.
294
+ """
295
+ from .sql_differ import SQLiteDiffer
296
+
297
+ ignore_tables = ignore_tables or set()
298
+ ignore_table_fields = ignore_table_fields or {}
299
+
300
+ try:
301
+ differ = SQLiteDiffer(seed_db, current_db)
302
+ raw_diff = differ.diff_all_tables()
303
+
304
+ filtered_diff: Dict[str, Any] = {}
305
+ for table_name, table_diff in raw_diff.items():
306
+ if table_name in ignore_tables:
307
+ continue
308
+
309
+ # Skip tables that errored during diffing
310
+ if "error" in table_diff:
311
+ continue
312
+
313
+ ignored_fields = ignore_table_fields.get(table_name, set())
314
+
315
+ # Added rows
316
+ filtered_added = []
317
+ for row in table_diff.get("added_rows", []):
318
+ filtered_data = {
319
+ k: v for k, v in row["data"].items() if k not in ignored_fields
320
+ }
321
+ filtered_added.append({"row_id": row["row_id"], "data": filtered_data})
322
+
323
+ # Removed rows
324
+ filtered_removed = []
325
+ for row in table_diff.get("removed_rows", []):
326
+ filtered_data = {
327
+ k: v for k, v in row["data"].items() if k not in ignored_fields
328
+ }
329
+ filtered_removed.append({"row_id": row["row_id"], "data": filtered_data})
330
+
331
+ # Modified rows
332
+ filtered_modified = []
333
+ for row in table_diff.get("modified_rows", []):
334
+ filtered_changes = {
335
+ k: v for k, v in row["changes"].items() if k not in ignored_fields
336
+ }
337
+ if filtered_changes:
338
+ after_row = row.get("after_row", {})
339
+ filtered_data = {
340
+ k: v for k, v in after_row.items() if k not in ignored_fields
341
+ }
342
+ filtered_modified.append({
343
+ "row_id": row["row_id"],
344
+ "changes": filtered_changes,
345
+ "data": filtered_data,
346
+ })
347
+
348
+ total_changes = len(filtered_added) + len(filtered_removed) + len(filtered_modified)
349
+
350
+ filtered_diff[table_name] = {
351
+ "table_name": table_name,
352
+ "primary_key": table_diff.get("primary_key", []),
353
+ "added_rows": filtered_added,
354
+ "removed_rows": filtered_removed,
355
+ "modified_rows": filtered_modified,
356
+ "unchanged_count": table_diff.get("unchanged_count", 0),
357
+ "total_changes": total_changes,
358
+ }
359
+
360
+ return {
361
+ "success": True,
362
+ "diff": filtered_diff,
363
+ "message": "Structured diff generated successfully",
364
+ }
365
+
366
+ except Exception as e:
367
+ return {
368
+ "success": False,
369
+ "diff": {},
370
+ "message": f"Failed to generate structured diff: {e}",
371
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fleet-python
3
- Version: 0.2.117
3
+ Version: 0.2.118
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.117"
8
+ version = "0.2.118"
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