home · contact · privacy
Refactor TUI client events to make use of affector pattern.
authorChristian Heller <c.heller@plomlompom.de>
Wed, 6 Aug 2025 20:09:54 +0000 (22:09 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Wed, 6 Aug 2025 20:09:54 +0000 (22:09 +0200)
ircplom/client.py
ircplom/client_tui.py

index 71cf2e5ad1f37f1f5ab8a256c2f208122c050cfe..621e956402e0ddbabcea230d2610d1325ae73011 100644 (file)
@@ -51,12 +51,9 @@ class _IrcConnection(BaseIrcConnection, ClientIdMixin):
 
 @dataclass
 class ClientQueueMixin(QueueMixin, ClientIdMixin):
-    'To QueueMixin adds _cput to extend ._put with client_id= setting.'
+    'To QueueMixin adds _cput to send ClientEvent for self.'
 
-    def _cput(self, event_class, **kwargs) -> None:
-        self._put(event_class(client_id=self.client_id, **kwargs))
-
-    def _cputs(self, t_method: str, **kwargs) -> None:
+    def _cput(self, t_method: str, **kwargs) -> None:
         self._put(ClientEvent.affector()(
             client_id=self.client_id, t_method=t_method).kw(**kwargs))
 
@@ -201,7 +198,7 @@ class Client(ABC, ClientQueueMixin):
                                            port=self.conn_setup.port,
                                            _q_out=self._q_out,
                                            client_id=self.client_id)
-                self._cputs('_on_connect')
+                self._cput('_on_connect')
             except IrcConnAbortException as e:
                 self.log.alert(str(e))
             except Exception as e:  # pylint: disable=broad-exception-caught
index 14557ea0dda02ed0645412b23b44d951c10af8e1..356032745d983a549a4eff952bb628a31c5a6bce 100644 (file)
@@ -1,6 +1,5 @@
 'TUI adaptions to Client.'
 # built-ins
-from dataclasses import dataclass
 from getpass import getuser
 from typing import Any, Optional
 # ourselves
@@ -9,7 +8,7 @@ from ircplom.tui_base import (BaseTui, PromptWidget, TuiEvent, Window,
 from ircplom.irc_conn import IrcMessage
 from ircplom.client import (
         STREAM_GLOB, STREAM_PREFIX_META, STREAM_RAW, STREAM_SERVER,
-        IrcConnSetup, Client, ClientIdMixin, ClientQueueMixin, NewClientEvent)
+        IrcConnSetup, Client, ClientQueueMixin, NewClientEvent)
 
 CMD_SHORTCUTS['disconnect'] = 'window.disconnect'
 CMD_SHORTCUTS['nick'] = 'window.nick'
@@ -30,7 +29,7 @@ class _ClientWindow(Window, ClientQueueMixin):
         return f'{super()._status_title}|{self.client_id}|{self.stream}'
 
     def _send_msg(self, verb: str, params: tuple[str, ...], **kwargs) -> None:
-        self._cputs('send', msg=IrcMessage(verb=verb, params=params), **kwargs)
+        self._cput('send', msg=IrcMessage(verb=verb, params=params), **kwargs)
 
     def cmd__disconnect(self, quit_msg: str = 'ircplom says bye') -> None:
         'Send QUIT command to server.'
@@ -38,7 +37,7 @@ class _ClientWindow(Window, ClientQueueMixin):
 
     def cmd__reconnect(self) -> None:
         'Attempt reconnection.'
-        self._cputs('start_connecting')
+        self._cput('start_connecting')
 
     def cmd__nick(self, new_nick: str) -> None:
         'Attempt nickname change.'
@@ -82,7 +81,7 @@ class ClientTui(BaseTui):
 
     def __init__(self, **kwargs) -> None:
         super().__init__(**kwargs)
-        self.clients_data: dict[str, dict[str, Any]] = {}
+        self._clients_data: dict[str, dict[str, Any]] = {}
 
     def _new_client_window(self, client_id: str, stream: str) -> _ClientWindow:
         new_idx = len(self._windows)
@@ -91,7 +90,7 @@ class ClientTui(BaseTui):
         win = win_class(idx=new_idx, term=self._term, _q_out=self._q_out,
                         client_id=client_id, stream=stream)
         if isinstance(win, _PrivmsgWindow):
-            win.prompt.update_prefix(**{k: self.clients_data[client_id][k]
+            win.prompt.update_prefix(**{k: self._clients_data[client_id][k]
                                         for k in _PROMPT_UPDATE_TRIGGER_KEYS})
         self._windows += [win]
         self._switch_window(new_idx)
@@ -118,6 +117,30 @@ class ClientTui(BaseTui):
         win = self._new_client_window(client_id=client_id, stream=stream)
         return win
 
+    def log_for_client(self, client_id: str, stream: str, msg: str) -> None:
+        'To stream of client_id, log msg.'
+        if stream == STREAM_GLOB:
+            for win in self.client_wins(client_id):
+                win.log.append(msg)
+        else:
+            self.client_win(client_id, stream).log.append(msg)
+        self.redraw_affected()
+
+    def update_client_data(self, client_id: str, **kwargs) -> None:
+        'Apply kwargs settings to client data, update representation.'
+        if client_id not in self._clients_data:
+            self._clients_data[client_id] = {}
+        clients_data = self._clients_data[client_id]
+        for k, v in kwargs.items():
+            clients_data[k] = v
+        if _PROMPT_UPDATE_TRIGGER_KEYS & set(kwargs.keys()):
+            for prompt in [w.prompt for w in self.client_wins(client_id)
+                           if isinstance(w.prompt, _PrivmsgPromptWidget)]:
+                assert isinstance(prompt, _PrivmsgPromptWidget)
+                prompt.update_prefix(**{k: clients_data[k]
+                                        for k in _PROMPT_UPDATE_TRIGGER_KEYS})
+            self.redraw_affected()
+
     def cmd__connect(self,
                      host_port: str,
                      nickname_pw: str = '',
@@ -126,7 +149,7 @@ class ClientTui(BaseTui):
         'Create Client and pass it via NewClientEvent.'
         split = host_port.split(':', maxsplit=1)
         hostname = split[0]
-        if hostname in self.clients_data:
+        if hostname in self._clients_data:
             return f'already set up connection to {hostname}'
         port = -1
         if len(split) > 1:
@@ -148,47 +171,16 @@ class ClientTui(BaseTui):
         return None
 
 
-@dataclass
-class _ClientLogEvent(TuiEvent, ClientIdMixin):
-    stream: str
-    msg: str
-
-    def affect(self, target: ClientTui) -> None:
-        if self.stream == STREAM_GLOB:
-            for win in target.client_wins(self.client_id):
-                win.log.append(self.msg)
-        else:
-            target.client_win(self.client_id, self.stream
-                              ).log.append(self.msg)
-        target.redraw_affected()
-
-
-@dataclass
-class _ClientDataEvent(TuiEvent, ClientIdMixin):
-    _updates: dict[str, Any]
-
-    def affect(self, target: ClientTui) -> None:
-        if self.client_id not in target.clients_data:
-            target.clients_data[self.client_id] = {}
-        clients_data = target.clients_data[self.client_id]
-        for k, v in self._updates.items():
-            clients_data[k] = v
-        if _PROMPT_UPDATE_TRIGGER_KEYS & set(self._updates.keys()):
-            for prompt in [w.prompt for w in target.client_wins(self.client_id)
-                           if isinstance(w.prompt, _PrivmsgPromptWidget)]:
-                assert isinstance(prompt, _PrivmsgPromptWidget)
-                prompt.update_prefix(**{k: clients_data[k]
-                                        for k in _PROMPT_UPDATE_TRIGGER_KEYS})
-        target.redraw_affected()
-
-
 class _ClientKnowingTui(Client):
 
+    def _ctput(self, t_method: str, **kwargs) -> None:
+        self._put(TuiEvent.affector()(t_method).kw(client_id=self.client_id
+                                                   ).kw(**kwargs))
+
     def _log(self, msg: str, stream: str = STREAM_SERVER) -> None:
-        self._cput(_ClientLogEvent, stream=stream, msg=msg)
+        self._ctput('log_for_client', stream=stream, msg=msg)
 
     def update_login(self, nick_confirmed: bool, nickname: str = '') -> None:
         super().update_login(nick_confirmed, nickname)
-        self._cput(_ClientDataEvent,
-                   _updates={'nick_confirmed': self.nick_confirmed,
-                             'nickname': self.conn_setup.nickname})
+        self._ctput('update_client_data', nick_confirmed=self.nick_confirmed,
+                    nickname=self.conn_setup.nickname)