home · contact · privacy
Move more processing into _Update.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 11 Sep 2025 14:43:11 +0000 (16:43 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 11 Sep 2025 14:43:11 +0000 (16:43 +0200)
ircplom/client_tui.py

index 5d920b9f8e4aa2478a37f26db4b7b35369496cf4..ff841321f2ccbe7b3019f3bd600000915b17aa47 100644 (file)
@@ -3,7 +3,7 @@
 from getpass import getuser
 from dataclasses import dataclass, asdict as dc_asdict
 from types import get_original_bases
-from typing import Any, Callable, Optional, Sequence
+from typing import Any, Callable, Optional, Self, Sequence
 # ourselves
 from ircplom.tui_base import (BaseTui, PromptWidget, TuiEvent, Window,
                               CMD_SHORTCUTS)
@@ -30,6 +30,15 @@ class _Update:
     path: tuple[str, ...]
     value: Optional[Any] = None
 
+    @property
+    def key(self) -> str:
+        'Name of item or attribute to be processed.'
+        return self.path[0]
+
+    def decremented(self) -> Self:
+        'Create copy with .path reduced by leftmost step.'
+        return self.__class__(self.path[1:], self.value)
+
 
 class _UpdatingNode(AutoAttrMixin):
     log_scopes: dict[str, LogScope] = {'': LogScope.SERVER}
@@ -48,24 +57,23 @@ class _UpdatingNode(AutoAttrMixin):
     def recursive_set_and_report_change(
             self, update: _Update) -> Optional[tuple[LogScope, Any]]:
         'Apply update, return if that actually made a difference.'
-        node = self._get(update.path[0])
+        node = self._get(update.key)
         if len(update.path) > 1:
-            return node.recursive_set_and_report_change(
-                    _Update(update.path[1:], update.value))
+            return node.recursive_set_and_report_change(update.decremented())
         return self._focused_set_and_report_change(node, update)
 
     def _focused_set_and_report_change(
             self, old_value: '_UpdatingNode', update: _Update
             ) -> Optional[tuple[LogScope, Any]]:
-        scope = self._scope(update.path[0])
+        scope = self._scope(update.key)
         if update.value is None:
-            if not self._is_set(update.path[0]):
+            if not self._is_set(update.key):
                 return None
-            self._unset(update.path[0])
+            self._unset(update.key)
             return (scope, None)
         if old_value == update.value:
             return None
-        self._set(update.path[0], update.value)
+        self._set(update.key, update.value)
         return (scope, update.value)
 
     def _get(self, key: str):
@@ -207,13 +215,13 @@ class _UpdatingChannel(_UpdatingNode):
     def _focused_set_and_report_change(
             self, old_value: '_UpdatingNode', update: _Update
             ) -> Optional[tuple[LogScope, Any]]:
-        scope = self._scope(update.path[0])
-        if update.path[0] == 'topic':
+        scope = self._scope(update.key)
+        if update.key == 'topic':
             if super()._focused_set_and_report_change(old_value, update):
                 return (scope,
                         f'RAW:{self.topic.who} set topic: {self.topic.what}')
             return None
-        assert update.path[0] == 'user_ids'
+        assert update.key == 'user_ids'
         assert isinstance(update.value, tuple)
         d = {'NUHS:joining': tuple(id_ for id_ in update.value
                                    if id_ not in self.user_ids)
@@ -233,14 +241,14 @@ class _UpdatingUser(_UpdatingNode, NickUserHost):
             self, old_value: '_UpdatingNode', update: _Update
             ) -> Optional[tuple[LogScope, Any]]:
         assert isinstance(update.value, str)
-        if update.path[0] == 'modes':
+        if update.key == 'modes':
             return super()._focused_set_and_report_change(old_value, update)
         if super()._focused_set_and_report_change(old_value, update):
-            scope = self._scope(update.path[0])
+            scope = self._scope(update.key)
             msg = 'RAW: '
-            if update.path[0] == 'nick':
+            if update.key == 'nick':
                 return scope, msg + f'{self.prev} renames {update.value}'
-            if update.path[0] == 'exit_msg' and update.value:
+            if update.key == 'exit_msg' and update.value:
                 msg += f'{self}'
                 msg += 'quits' if update.value[0] == 'Q' else 'parts'
                 if len(update.value) > 1: