From 6f943da688bc0fe7b91311d59c3434e5675fea4b Mon Sep 17 00:00:00 2001 From: Alex Morson Date: Tue, 19 May 2026 21:47:52 +0100 Subject: [PATCH] Support nested batching of broadcasts This isn't currently used, but I can easily see myself refactoring stuff in a way that causes this to happen, so it would be nice if it worked. --- src/dusted/broadcaster.py | 5 +++-- tests/test_broadcaster.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 tests/test_broadcaster.py diff --git a/src/dusted/broadcaster.py b/src/dusted/broadcaster.py index 0e51ab0..12a1c43 100644 --- a/src/dusted/broadcaster.py +++ b/src/dusted/broadcaster.py @@ -14,11 +14,12 @@ def __init__(self) -> None: @contextmanager def batch(self) -> Generator[None, None, None]: """Batch any events until the context manager has closed.""" + was_batching = self._batching + self._batching = True try: - self._batching = True yield finally: - self._batching = False + self._batching = was_batching if self._broadcast_scheduled: self.broadcast() diff --git a/tests/test_broadcaster.py b/tests/test_broadcaster.py new file mode 100644 index 0000000..7fdd22e --- /dev/null +++ b/tests/test_broadcaster.py @@ -0,0 +1,36 @@ +from unittest import TestCase +from unittest.mock import Mock + +from dusted.broadcaster import Broadcaster + + +class TestBroadcaster(TestCase): + def test_multiple_subscribers(self): + """Test that multiple subscribers get notified.""" + + broadcaster = Broadcaster() + mock_callback_1 = Mock(spec_set=[]) + mock_callback_2 = Mock(spec_set=[]) + broadcaster.subscribe(mock_callback_1) + broadcaster.subscribe(mock_callback_2) + + broadcaster.broadcast() + + mock_callback_1.assert_called_once() + mock_callback_2.assert_called_once() + + def test_nested_batch(self): + """Test that nested batching works.""" + + broadcaster = Broadcaster() + mock_callback = Mock(spec_set=[]) + broadcaster.subscribe(mock_callback) + + with broadcaster.batch(): + with broadcaster.batch(): + broadcaster.broadcast() + broadcaster.broadcast() + + mock_callback.assert_not_called() + + mock_callback.assert_called_once()