From caf800e5e83780f53dc1d215b5ef3e99786879fc Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Fri, 3 Jul 2026 14:46:12 +0200 Subject: [PATCH] fix(admin): guard find_changed_cell against cross-table schema mismatch When switching tables, the table-switch branch writes fresh data for the new table, which re-fires the same callback with data_previous still holding the old table's rows. find_changed_cell only checked row count before diffing, so if the two tables happened to have the same number of rows it would zip mismatched-schema dicts and report a spurious changed cell (usually the PK column), producing a confusing red alert right after switching tables. --- src/admin/tables.py | 4 ++++ tests/admin/test_tables.py | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/admin/tables.py b/src/admin/tables.py index a1240cc..c49221c 100644 --- a/src/admin/tables.py +++ b/src/admin/tables.py @@ -144,6 +144,10 @@ def find_changed_cell( ) -> tuple[int, str, object, object] | None: if data_previous is None or len(data) != len(data_previous): return None + if not data or not data_previous: + return None + if set(data[0].keys()) != set(data_previous[0].keys()): + return None for i, (new_row, old_row) in enumerate(zip(data, data_previous)): for col, new_val in new_row.items(): old_val = old_row.get(col) diff --git a/tests/admin/test_tables.py b/tests/admin/test_tables.py index d85e91e..bf55ce7 100644 --- a/tests/admin/test_tables.py +++ b/tests/admin/test_tables.py @@ -99,6 +99,16 @@ def test_find_changed_cell_returns_none_when_identical(): assert tables.find_changed_cell(data, data_previous) is None +def test_find_changed_cell_returns_none_when_schemas_differ(): + # Mimics switching from "users" to "admin_actions" mid-callback: the two + # tables' row lists happen to have the same length but different + # columns, so this must not be mistaken for a genuine cell edit. + data = [{"id": 1, "email": "a@ex.fr"}] + data_previous = [{"id": 1, "admin_email": "x@ex.fr"}] + + assert tables.find_changed_cell(data, data_previous) is None + + def test_find_changed_cell_returns_none_when_previous_is_none(): assert tables.find_changed_cell([{"id": 1}], None) is None