Skip to content

Commit 21e30e2

Browse files
Thibault-Pelletierjourdain
authored andcommitted
fix(state): fix dirty not triggering change listeners
Fix regression introduced by ec70d23 by properly tracking keys marked dirty and clean in the suppress change stack.
1 parent 7853c02 commit 21e30e2

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

src/trame_server/state.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ def dirty(self, *_args):
298298
_args = self._translator.translate_list(_args)
299299
for key in _args:
300300
self._pending_update.setdefault(key, self._pushed_state.get(key))
301+
self._suppress_change_stack.on_pending_key_added(key)
301302

302303
def clean(self, *_args):
303304
"""
@@ -310,6 +311,7 @@ def clean(self, *_args):
310311
for key in _args:
311312
if key in self._pending_update:
312313
self._pushed_state[key] = self._pending_update.pop(key)
314+
self._suppress_change_stack.on_pending_key_removed(key)
313315

314316
def update(self, _dict):
315317
"""Update the current state dict with the provided one"""

tests/test_state.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,3 +636,65 @@ def on_a(**kwargs):
636636

637637
state.flush()
638638
mock.assert_called_once_with(a=42, b=2, c=3)
639+
640+
641+
def test_keys_marked_dirty_triggers_listener_changes(state):
642+
mock = MagicMock()
643+
644+
@state.change("a")
645+
def on_change(a, **_):
646+
mock(a)
647+
648+
state.a = 1
649+
state.flush()
650+
mock.reset_mock()
651+
652+
state.dirty("a")
653+
state.flush()
654+
mock.assert_called_once_with(1)
655+
656+
657+
def test_keys_marked_dirty_in_suppress_does_not_trigger_listener_changes(state):
658+
mock = MagicMock()
659+
660+
@state.change("a")
661+
def on_change(a, **_):
662+
mock(a)
663+
664+
state.a = 1
665+
state.flush()
666+
mock.reset_mock()
667+
668+
with state.suppress_change_listeners("a"):
669+
state.dirty("a")
670+
671+
state.flush()
672+
mock.assert_not_called()
673+
674+
675+
def test_keys_marked_clean_does_not_trigger_listener_changes(state):
676+
mock = MagicMock()
677+
678+
@state.change("a")
679+
def on_change(a, **_):
680+
mock(a)
681+
682+
state.a = 2
683+
state.clean("a")
684+
state.flush()
685+
mock.assert_not_called()
686+
687+
688+
def test_keys_marked_clean_in_suppress_does_not_trigger_listener_changes(state):
689+
mock = MagicMock()
690+
691+
@state.change("a")
692+
def on_change(a, **_):
693+
mock(a)
694+
695+
state.a = 2
696+
with state.suppress_change_listeners("a"):
697+
state.clean("a")
698+
699+
state.flush()
700+
mock.assert_not_called()

0 commit comments

Comments
 (0)