simplify dedupe
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 16s
JS/TS / lint (pull_request) Successful in 19s
Python / fmt (pull_request) Successful in 34s
Python / lint (pull_request) Failing after 31s
Python / test (pull_request) Failing after 59s
Python / typecheck (pull_request) Failing after 1m7s
C++ / build (pull_request) Successful in 1m54s
Rust / fmt (pull_request) Successful in 49s
Rust / build (pull_request) Successful in 1m41s
Rust / clippy (pull_request) Successful in 1m33s
Python / buildcheck (pull_request) Successful in 2m38s
C++ / clang-tidy (pull_request) Successful in 3m31s

This commit is contained in:
2026-07-13 22:10:41 +02:00
parent a9bbb21f54
commit bf5a8b8049
+27 -30
View File
@@ -491,11 +491,23 @@ class _ListenerRegistry:
entries = list(self._entries.values()) entries = list(self._entries.values())
result = [] result = []
seen_idents = set()
for obj, _listener in entries: for obj, _listener in entries:
if obj.isDevice: if obj.isDevice:
ident = obj.unitId or obj.serial
if ident and ident in seen_idents:
continue
if ident:
seen_idents.add(ident)
result.append(obj) result.append(obj)
else: else:
result.extend(list(obj)) for child in obj:
ident = child.unitId or child.serial
if ident and ident in seen_idents:
continue
if ident:
seen_idents.add(ident)
result.append(child)
return result return result
def stop(self): def stop(self):
@@ -510,28 +522,8 @@ class _ListenerRegistry:
listener.join(timeout=2.0) listener.join(timeout=2.0)
def _dedupe_by_identity(
pairs: list[tuple[object, DeviceBattery]],
freshness: Callable[[object], float],
) -> list[DeviceBattery]:
passthrough: list[DeviceBattery] = []
best: dict[str, tuple[float, DeviceBattery]] = {}
for dev, entry in pairs:
key = entry.serial
if not key:
passthrough.append(entry)
continue
ts = freshness(dev)
current = best.get(key)
if current is None or ts >= current[0]:
best[key] = (ts, entry)
return passthrough + [entry for _ts, entry in best.values()]
def _snapshot(registry: _ListenerRegistry) -> list[DeviceBattery]: def _snapshot(registry: _ListenerRegistry) -> list[DeviceBattery]:
pairs: list[tuple[object, DeviceBattery]] = [] results: list[DeviceBattery] = []
with registry._hidpp_io_lock: with registry._hidpp_io_lock:
for dev in registry.known_devices(): for dev in registry.known_devices():
@@ -547,8 +539,8 @@ def _snapshot(registry: _ListenerRegistry) -> list[DeviceBattery]:
info = None info = None
entry = _to_device_battery(dev, info) entry = _to_device_battery(dev, info)
if entry is not None: if entry is not None:
pairs.append((dev, entry)) results.append(entry)
return _dedupe_by_identity(pairs, registry.last_change) return results
def _clean_json(path: Path) -> None: def _clean_json(path: Path) -> None:
@@ -642,19 +634,24 @@ def _read_battery(dev) -> DeviceBattery | None:
def poll_once() -> list[DeviceBattery]: def poll_once() -> list[DeviceBattery]:
pairs: list[tuple[object, DeviceBattery]] = [] results: list[DeviceBattery] = []
seen_idents = set()
for dev in _iter_open_devices(): for dev in _iter_open_devices():
try: try:
info = _read_battery(dev) info = _read_battery(dev)
if info is not None: if info is not None:
pairs.append((dev, info)) entry = _to_device_battery(dev, info)
if entry:
ident = entry.serial or (getattr(dev, "unitId", None))
if ident and ident in seen_idents:
continue
if ident:
seen_idents.add(ident)
results.append(entry)
finally: finally:
with contextlib.suppress(Exception): with contextlib.suppress(Exception):
dev.close() dev.close()
return results
return _dedupe_by_identity(
pairs, lambda dev: 1.0 if dev.receiver is None else 0.0
)
def _write_json_atomic(path: Path, results: list[DeviceBattery]) -> None: def _write_json_atomic(path: Path, results: list[DeviceBattery]) -> None: