diff --git a/idom/core/dispatcher.py b/idom/core/dispatcher.py index cfe4c5c14..27b655445 100644 --- a/idom/core/dispatcher.py +++ b/idom/core/dispatcher.py @@ -4,7 +4,6 @@ from anyio import create_task_group from anyio.abc import TaskGroup -from jsonpatch import make_patch, apply_patch from .layout import ( LayoutEvent, @@ -122,14 +121,14 @@ async def run( async def _render_loop(self) -> None: while True: update = await super()._outgoing(self.layout, None) - self._model_state = _apply_layout_update(self._model_state, update) + self._model_state = update.apply_to(self._model_state) # append updates to all other contexts for queue in self._update_queues.values(): await queue.put(update) async def _outgoing_loop(self, send: SendCoroutine, context: Any) -> None: self._update_queues[context] = asyncio.Queue() - await send(LayoutUpdate("", make_patch({}, self._model_state).patch)) + await send(LayoutUpdate.create_from({}, self._model_state)) await super()._outgoing_loop(send, context) async def _outgoing(self, layout: Layout, context: str) -> LayoutUpdate: @@ -142,9 +141,3 @@ async def _join_event(self) -> AsyncIterator[asyncio.Event]: yield event finally: event.set() - - -def _apply_layout_update(doc: Dict[str, Any], update: LayoutUpdate) -> Any: - return apply_patch( - doc, [{**c, "path": update.path + c["path"]} for c in update.changes] - ) diff --git a/idom/core/layout.py b/idom/core/layout.py index 47b7bbc55..60e2a5129 100644 --- a/idom/core/layout.py +++ b/idom/core/layout.py @@ -15,7 +15,7 @@ ) from loguru import logger -from jsonpatch import make_patch +from jsonpatch import make_patch, apply_patch from .element import AbstractElement from .events import EventHandler, EventTarget @@ -29,6 +29,16 @@ class LayoutUpdate(NamedTuple): path: str changes: List[Dict[str, Any]] + def apply_to(self, model: Any) -> Any: + """Return the model resulting from the changes in this update""" + return apply_patch( + model, [{**c, "path": self.path + c["path"]} for c in self.changes] + ) + + @classmethod + def create_from(cls, source: Any, target: Any) -> "LayoutUpdate": + return cls("", make_patch(source, target).patch) + class LayoutEvent(NamedTuple): target: str