From: Christian Heller Date: Mon, 25 Aug 2025 20:01:31 +0000 (+0200) Subject: Refactor _CompletableStringsList usage. X-Git-Url: https://plomlompom.com/repos/do_tasks?a=commitdiff_plain;h=f0327c1429d96a4121d98dd0d07e1b9601c92bc0;p=ircplom Refactor _CompletableStringsList usage. --- diff --git a/ircplom/client.py b/ircplom/client.py index 4784507..babc87f 100644 --- a/ircplom/client.py +++ b/ircplom/client.py @@ -478,15 +478,11 @@ class _CapsManager: 'Parse CAP message to negot. steps, DB inputs; return if successful.' for item in items: if verb == 'NEW': - self._ls.append(item, stay_complete=True) - self._update_cap(item) + name, data = _ServerCapability.split_name_data(item) + self._dict[name] = _ServerCapability(False, data) elif verb == 'DEL': - self._ls.remove(item, stay_complete=True) - for name in [ - name for name in self._list.visible - if _ServerCapability.split_name_data(name)[0] == item]: - self._list.remove(name, stay_complete=True) - self._del_cap(item) + name, _ = _ServerCapability.split_name_data(item) + del self._dict[name] elif verb in {'ACK', 'NACK'}: self._list_expectations[verb].add(item) if verb in {'LS', 'LIST'}: @@ -494,22 +490,22 @@ class _CapsManager: for item in items: target.append(item) if not incomplete: - target.is_complete = True + target.complete() if target == self._list: acks = self._list_expectations['ACK'] naks = self._list_expectations['NAK'] - list_set = set(self._list.visible) + list_set = set(target.completed) assert acks == list_set & acks assert set() == list_set & naks - if self._list.is_complete: + if self._list.completed: for name, data in [_ServerCapability.split_name_data(item) - for item in self._ls.visible]: + for item in self._ls.completed]: self._dict[name] = _ServerCapability( - name in self._list.visible, data) + name in self._list.completed, data) return True - if self._ls.is_complete: + if self._ls.completed: availables = [_ServerCapability.split_name_data(item)[0] - for item in self._ls.visible] + for item in self._ls.completed] for cap_name in [n for n in _NAMES_DESIRED_SERVER_CAPS if n in availables]: self._challenge('REQ', cap_name) @@ -526,15 +522,6 @@ class _CapsManager: self._send(*params) self._sent_challenges.append(' '.join(params)) - def _update_cap(self, full_ls_item: str) -> None: - name, data = _ServerCapability.split_name_data(full_ls_item) - is_enabled = name in self._list.visible - self._dict[name] = _ServerCapability(is_enabled, data) - - def _del_cap(self, full_ls_item) -> None: - name, _ = _ServerCapability.split_name_data(full_ls_item) - del self._dict[name] - @dataclass class IrcConnSetup: @@ -572,33 +559,22 @@ class Db: class _CompletableStringsList: + _on_update: Callable def __init__(self) -> None: - self._items: list[str] = [] - self.is_complete = False + self._incomplete: list[str] = [] + self.completed: tuple[str, ...] = tuple() - @property - def visible(self) -> tuple[str, ...]: - 'Tuple of collected items if .is_complete, otherwise empty.' - return tuple(self._items) if self.is_complete else tuple() - - def _stay_complete(self, assert_complete: bool) -> None: - if assert_complete: - assert self.is_complete - else: - if self.is_complete: - self._items.clear() - self.is_complete = False + def append(self, value: str) -> None: + 'Append value to list.' + self._incomplete.append(value) - def append(self, item: str, stay_complete=False) -> None: - 'Append to list; if .is_complete yet not stay_complete, tabula rasa.' - self._stay_complete(stay_complete) - self._items.append(item) - - def remove(self, item: str, stay_complete=False) -> None: - 'Remove from list; if .is_complete yet not stay_complete, tabula rasa.' - self._stay_complete(stay_complete) - self._items.remove(item) + def complete(self) -> None: + 'Declare list done, call updater if set.' + self.completed = tuple(self._incomplete) + self._incomplete.clear() + if hasattr(self, '_on_update'): + self._on_update() class _Db(Db): @@ -652,7 +628,6 @@ class _ChannelDb(_Db, SharedChannelDbFields): class SharedClientDbFields(IrcConnSetup, Generic[_ChannelDbFields]): 'API for fields shared directly in name and type with TUI.' connection_state: str - motd: tuple[str, ...] sasl_account: str sasl_auth_state: str user_modes: str @@ -706,21 +681,12 @@ class _ClientDb(_Db, SharedClientDbFields): caps: _UpdatingDict isupports: _UpdatingDict users: _UpdatingDict - _completable_motd: list[str] + motd: _CompletableStringsList _channels: dict[str, _ChannelDb] - def _get_completable(self, key) -> list[str]: - return getattr(self, f'_completable_{key}') - - def append_completable(self, key: str, value: str) -> None: - 'To completable list of key append value.' - self._get_completable(key).append(value) - - def declare_complete(self, key: str) -> None: - 'Declare completable at key complete.' - completable = self._get_completable(key) - setattr(self, key, tuple(completable)) - completable.clear() + def __init__(self, **kwargs) -> None: + super().__init__(**kwargs) + self.motd._on_update = lambda: self._on_update('motd') def user_id(self, query: str | _NickUserHost) -> str: 'Return user_id for nickname of entire NickUserHost, create if none.' @@ -754,7 +720,8 @@ class _ClientDb(_Db, SharedClientDbFields): def needs_arg(self, key: str) -> bool: 'Reply if attribute of key may reasonably be addressed without an arg.' - return not isinstance(getattr(self, key), (bool, int, str, tuple)) + return not isinstance(getattr(self, key), (bool, int, str, tuple, + _CompletableStringsList)) @property def chan_names(self) -> tuple[str, ...]: @@ -962,9 +929,9 @@ class Client(ABC, ClientQueueMixin): for name in ret['names']]: ret['channel']['db'].add_user(user_id) elif ret['verb'] == '372': # RPL_MOTD - self._db.append_completable('motd', ret['line']) + self._db.motd.append(ret['line']) elif ret['verb'] == '376': # RPL_ENDOFMOTD - self._db.declare_complete('motd') + self._db.motd.complete() elif ret['verb'] == '401': # ERR_NOSUCHNICK self._log(f'{ret["target"]} not online', scope=LogScope.CHAT, target=ret['target'], alert=True) diff --git a/ircplom/client_tui.py b/ircplom/client_tui.py index fae8c6a..a4e9e93 100644 --- a/ircplom/client_tui.py +++ b/ircplom/client_tui.py @@ -178,6 +178,7 @@ class _ChannelDb(_Db, SharedChannelDbFields): class _TuiClientDb(_Db, SharedClientDbFields): caps: dict[str, str] isupports: dict[str, str] + motd: tuple[str, ...] users: dict[str, NickUserHost] _channels: dict[str, _ChannelDb] @@ -405,5 +406,7 @@ class _ClientKnowingTui(Client): value = getattr(self._db, path) if isinstance(value, NickUserHost): value = value.copy() + elif value and hasattr(value, 'completed'): + value = value.completed self._client_tui_trigger('update_db', update=_Update( path, arg, value, display))