From 3a8ee0300d1810fd447d041126798abcc3438277 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Sat, 20 Jun 2026 15:25:21 +0200 Subject: [PATCH] swap: fix list element order on revert * Reverses the changes produced by swap's remove handler so that reverting a diff which removed three or more list elements restores their original order. diff emits list removals in descending index order, but revert replays them as inserts (which need ascending order); the add handler already reverses its changes, the remove handler did not. Signed-off-by: Vincent Gao --- dictdiffer/__init__.py | 2 +- tests/test_dictdiffer.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/dictdiffer/__init__.py b/dictdiffer/__init__.py index debd78a..1d78fff 100644 --- a/dictdiffer/__init__.py +++ b/dictdiffer/__init__.py @@ -358,7 +358,7 @@ def add(node, changes): return REMOVE, node, list(reversed(changes)) def remove(node, changes): - return ADD, node, changes + return ADD, node, list(reversed(changes)) def change(node, changes): first, second = changes diff --git a/tests/test_dictdiffer.py b/tests/test_dictdiffer.py index c1152b8..db52a98 100644 --- a/tests/test_dictdiffer.py +++ b/tests/test_dictdiffer.py @@ -712,6 +712,19 @@ def test_revert(self): reverted = revert(diffed, second) assert reverted == first + def test_revert_list_with_three_or_more_removed_elements(self): + # revert must restore list order when 3+ elements are removed: swap's + # remove handler has to reverse its changes like the add handler, since + # diff emits removals in descending index order but revert replays them + # as inserts (which need ascending order). + first = {'a': ['p', 'q', 'r']} + second = {'a': []} + assert revert(diff(first, second), second) == first + + first = {'a': list('abcdef')} + second = {'a': ['a', 'd']} + assert revert(diff(first, second), second) == first + def test_list_of_different_length(self): """Check that one can revert list with different length.""" first = [1]