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.
- {fleet_python-0.2.117/fleet_python.egg-info → fleet_python-0.2.118}/PKG-INFO +1 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/__init__.py +3 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/__init__.py +1 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/base.py +1 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/client.py +29 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/base.py +1 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/client.py +26 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/__init__.py +2 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/local_executor.py +127 -3
- {fleet_python-0.2.117 → fleet_python-0.2.118/fleet_python.egg-info}/PKG-INFO +1 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/pyproject.toml +1 -1
- {fleet_python-0.2.117 → fleet_python-0.2.118}/LICENSE +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/README.md +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/diff_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/dsl_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/exampleResume.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_account.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_action_log.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_client.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_mcp_anthropic.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_mcp_openai.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_sync.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_task.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_tasks.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/example_verifier.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/export_tasks.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/export_tasks_filtered.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/fetch_tasks.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/gemini_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/import_tasks.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/iterate_verifiers.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/json_tasks_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/nova_act_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/openai_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/openai_simple_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/query_builder_example.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/quickstart.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/examples/test_cdp_logging.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/env/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/env/client.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/exceptions.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/global_client.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/instance/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/instance/base.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/instance/client.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/judge.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/models.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/api.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/base.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/browser.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/filesystem.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/mcp.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/resources/sqlite.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/tasks.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/verifiers/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/verifiers/bundler.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/_async/verifiers/verifier.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/Dockerfile +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/agent.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp/main.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp_server/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp_server/main.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/mcp_server/tools.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/requirements.txt +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/gemini_cua/start.sh +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/orchestrator.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/types.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/agent/utils.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/cli.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/config.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/env/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/env/client.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/eval/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/eval/uploader.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/exceptions.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/global_client.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/base.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/client.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/instance/models.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/judge.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/models.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/proxy/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/proxy/proxy.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/proxy/whitelist.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/api.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/base.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/browser.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/filesystem.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/mcp.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/resources/sqlite.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/tasks.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/types.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/http_logging.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/logging.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/utils/playwright.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/bundler.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/code.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/db.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/decorator.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/parse.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/sql_differ.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet/verifiers/verifier.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/SOURCES.txt +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/dependency_links.txt +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/entry_points.txt +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/requires.txt +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/fleet_python.egg-info/top_level.txt +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/scripts/fix_sync_imports.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/scripts/unasync.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/setup.cfg +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/__init__.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_app_method.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_expect_exactly.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_expect_only.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_instance_dispatch.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_judge_criteria_markers.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_sqlite_resource_dual_mode.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_sqlite_shared_memory_behavior.py +0 -0
- {fleet_python-0.2.117 → fleet_python-0.2.118}/tests/test_verifier_from_string.py +0 -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.
|
|
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
|
|
@@ -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]:
|
|
@@ -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
|
|
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
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|