home · contact · privacy
Use set completable for CapsManager._ls, ._list, no need for order there.
authorChristian Heller <c.heller@plomlompom.de>
Thu, 11 Sep 2025 17:03:33 +0000 (19:03 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Thu, 11 Sep 2025 17:03:33 +0000 (19:03 +0200)
ircplom/client.py

index 1bf64d515c83784e2ae1ecac304056a30859d043..3b7115848a9f822bf55cd086df7b7fc5bd2cca81 100644 (file)
@@ -6,8 +6,8 @@ from dataclasses import dataclass, InitVar
 from enum import Enum, auto
 from getpass import getuser
 from threading import Thread
-from typing import (Any, Callable, Collection, Generic, Iterator, NamedTuple,
-                    Optional, Self, TypeVar)
+from typing import (Any, Callable, Collection, Generic, Iterable, Iterator,
+                    NamedTuple, Optional, Self, Set, TypeVar)
 from uuid import uuid4
 # ourselves
 from ircplom.events import (
@@ -138,6 +138,32 @@ class _CompletableStringsCollection(_Completable, Collection):
         yield from self._completed
 
 
+class _CompletableStringsSet(_CompletableStringsCollection, Set):
+    _collected: set[str]
+    _completed: Optional[set[str]] = None
+
+    def __init__(self) -> None:
+        self._collected = set()
+
+    def _copy_collected(self) -> set[str]:
+        return set(self._collected)
+
+    def add(self, item: str) -> None:
+        'Put item into collection.'
+        assert self._completed is None
+        assert item not in self._collected
+        self._collected.add(item)
+
+    def intersection(self, *others: Iterable[str]) -> set[str]:
+        'Compare self to other set(s).'
+        assert self._completed is not None
+        result = self._completed
+        for other in others:
+            assert isinstance(other, set)
+            result = result.intersection(other)
+        return result
+
+
 class _CompletableStringsOrdered(_Clearable, _CompletableStringsCollection):
     _collected: tuple[str, ...] = tuple()
     _completed: Optional[tuple[str, ...]] = None
@@ -162,11 +188,6 @@ class _CompletableStringsOrdered(_Clearable, _CompletableStringsCollection):
         self._completed = None
         self._collected = tuple()
 
-    def into_set(self) -> set[str]:
-        'Return as mere set.'
-        assert self._completed is not None
-        return set(self._completed)
-
 
 class IntoUpdateValueMixin(AutoAttrMixin):
     'Provides .into_update_value(), exportable for module-external consumers.'
@@ -637,8 +658,8 @@ class _CapsManager(_Clearable):
 
     def clear(self) -> None:
         self._dict.clear()
-        self._ls = _CompletableStringsOrdered()
-        self._list = _CompletableStringsOrdered()
+        self._ls = _CompletableStringsSet()
+        self._list = _CompletableStringsSet()
         self._list_expectations: dict[str, set[str]] = {
                 'ACK': set(), 'NAK': set()}
 
@@ -665,19 +686,18 @@ class _CapsManager(_Clearable):
         if verb in {'LS', 'LIST'}:
             target = getattr(self, f'_{verb.lower()}')
             for item in items:
-                target.append(item)
+                target.add(item)
             if complete:
                 target.complete()
-                if target == self._ls:
+                if target is self._ls:
                     for cap_name in _NAMES_DESIRED_SERVER_CAPS:
                         self._send('REQ', cap_name)
                     self._send('LIST')
-                elif target == self._list:
+                else:
                     acks = self._list_expectations['ACK']
                     naks = self._list_expectations['NAK']
-                    list_set = target.into_set()
-                    assert acks == list_set & acks
-                    assert set() == list_set & naks
+                    assert acks == self._list.intersection(acks)
+                    assert set() == self._list.intersection(naks)
                     for key, data in [_Dict.key_val_from_eq_str(entry)
                                       for entry in self._ls]:
                         self._dict[key].data = data