From 353cfa138fa26c218af221cc226495be12479322 Mon Sep 17 00:00:00 2001
From: Talley Lambert <talley.lambert@gmail.com>
Date: Sat, 2 Nov 2024 17:53:49 -0400
Subject: [PATCH] linting

---
 .pre-commit-config.yaml           |  7 +++----
 pyproject.toml                    |  3 +++
 src/pymmcore_remote/_serialize.py | 11 +----------
 src/pymmcore_remote/_util.py      |  2 +-
 src/pymmcore_remote/client.py     | 17 ++++++++++++++---
 src/pymmcore_remote/server.py     | 20 +++++++++++++++-----
 tests/remote/test_server.py       | 11 +----------
 7 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7d8cbdf..61a4612 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -31,7 +31,6 @@ repos:
     hooks:
       - id: mypy
         files: "^src/"
-        # # you have to add the things you want to type check against here
-        # additional_dependencies:
-        #   - numpy
-
+        additional_dependencies:
+          - pymmcore_plus
+          - Pyro5
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index e52560f..5814523 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -124,3 +124,6 @@ source = ["pymmcore_remote"]
 
 [tool.check-manifest]
 ignore = [".pre-commit-config.yaml", ".ruff_cache/**/*", "tests/**/*"]
+
+[tool.typos.default]
+extend-ignore-identifiers-re = ["(?i)Ser"]
diff --git a/src/pymmcore_remote/_serialize.py b/src/pymmcore_remote/_serialize.py
index e9703dd..27e34a1 100644
--- a/src/pymmcore_remote/_serialize.py
+++ b/src/pymmcore_remote/_serialize.py
@@ -1,12 +1,11 @@
 import atexit
 import contextlib
 import datetime
-import threading
 from abc import ABC, abstractmethod
 from collections import deque
 from collections.abc import Sized
 from multiprocessing.shared_memory import SharedMemory
-from typing import Any, ClassVar, Generic, TypeVar
+from typing import ClassVar, Generic, TypeVar
 
 import numpy as np
 import pymmcore
@@ -93,14 +92,6 @@ def from_dict(self, classname: str, d: dict) -> datetime.timedelta:
         return datetime.timedelta(d["val"])
 
 
-class SerLock(Serializer[type(threading.Lock())]):
-    def to_dict(self, obj: Any) -> dict:
-        return {"val": str(obj)}
-
-    def from_dict(self, classname: str, d: dict) -> datetime.timedelta:
-        return threading.Lock()
-
-
 class SerCMMError(Serializer[pymmcore.CMMError]):
     def to_dict(self, obj: pymmcore.CMMError) -> dict:
         try:
diff --git a/src/pymmcore_remote/_util.py b/src/pymmcore_remote/_util.py
index fe4e310..5f0f8ea 100644
--- a/src/pymmcore_remote/_util.py
+++ b/src/pymmcore_remote/_util.py
@@ -36,7 +36,7 @@ def _f(self: Any, *args: Any, **kwargs: Any) -> Any:
         _f.__name__ = name
         return _f
 
-    _dict_ = {}
+    _dict_: dict = {}
     for member_name, obj in chain(*(c.__dict__.items() for c in reversed(cls.mro()))):
         if member_name.startswith("_"):
             continue
diff --git a/src/pymmcore_remote/client.py b/src/pymmcore_remote/client.py
index 2eb3559..8ecb66b 100644
--- a/src/pymmcore_remote/client.py
+++ b/src/pymmcore_remote/client.py
@@ -17,7 +17,9 @@
 
 
 class MDARunnerProxy(Pyro5.api.Proxy):
-    def __init__(self, mda_runner_uri: Any, cb_thread: DaemonThread) -> None:
+    """Proxy for MDARunner object on server."""
+
+    def __init__(self, mda_runner_uri: Any, cb_thread: _DaemonThread) -> None:
         super().__init__(mda_runner_uri)
         events = ClientSideMDASignaler()
         object.__setattr__(self, "events", events)
@@ -26,10 +28,13 @@ def __init__(self, mda_runner_uri: Any, cb_thread: DaemonThread) -> None:
 
     # this is a lie... but it's more useful than -> Self
     def __enter__(self) -> MDARunner:
+        """Use as a context manager."""
         return super().__enter__()  # type: ignore [no-any-return]
 
 
 class MMCoreProxy(Pyro5.api.Proxy):
+    """Proxy for CMMCorePlus object on server."""
+
     _mda_runner: MDARunnerProxy
 
     def __init__(
@@ -43,7 +48,7 @@ def __init__(
         events = ClientSideCMMCoreSignaler()
         object.__setattr__(self, "events", events)
 
-        cb_thread = DaemonThread(name="CallbackDaemon")
+        cb_thread = _DaemonThread(name="CallbackDaemon")
         cb_thread.api_daemon.register(events)
         self.connect_client_side_callback(events)  # must come after register()
 
@@ -56,10 +61,12 @@ def __init__(
 
     # this is a lie... but it's more useful than -> Self
     def __enter__(self) -> CMMCorePlus:
+        """Use as a context manager."""
         return super().__enter__()  # type: ignore [no-any-return]
 
     @property
     def mda(self) -> MDARunner:
+        """Return the MDARunner proxy."""
         return self._mda_runner
 
 
@@ -71,14 +78,18 @@ def receive_server_callback(self: Any, signal_name: str, args: tuple) -> None:
 
 
 class ClientSideCMMCoreSignaler(CMMCoreSignaler):
+    """Client-side signaler for CMMCore events."""
+
     receive_server_callback = receive_server_callback
 
 
 class ClientSideMDASignaler(MDASignaler):
+    """Client-side signaler for MDA events."""
+
     receive_server_callback = receive_server_callback
 
 
-class DaemonThread(threading.Thread):
+class _DaemonThread(threading.Thread):
     def __init__(self, name: str = "DaemonThread"):
         self.api_daemon = Pyro5.api.Daemon()
         self._stop_event = threading.Event()
diff --git a/src/pymmcore_remote/server.py b/src/pymmcore_remote/server.py
index 85c549f..d094868 100644
--- a/src/pymmcore_remote/server.py
+++ b/src/pymmcore_remote/server.py
@@ -5,6 +5,7 @@
 
 import Pyro5
 import Pyro5.api
+import Pyro5.core
 import Pyro5.errors
 from click import Path
 from pymmcore_plus import CMMCorePlus
@@ -23,14 +24,16 @@
 DEFAULT_URI = f"PYRO:{CORE_NAME}@{DEFAULT_HOST}:{DEFAULT_PORT}"
 
 
-class CallbackProtocol(Protocol):
+class ClientSideCallbackHandler(Protocol):
+    """Protocol for callback handlers on the client side."""
+
     def receive_server_callback(self, signal_name: str, args: tuple) -> None:
         """Will be called by server with name of signal, and tuple of args."""
 
 
 class _CallbackMixin:
     def __init__(self, signal_type: type, events: Any) -> None:
-        self._callback_handlers: set[CallbackProtocol] = set()
+        self._callback_handlers: set[ClientSideCallbackHandler] = set()
 
         for name in {
             name
@@ -42,10 +45,12 @@ def __init__(self, signal_type: type, events: Any) -> None:
                 # FIXME: devicePropertyChanged will not work on Remote
                 attr.connect(partial(self.emit_signal, name))
 
-    def connect_client_side_callback(self, handler: CallbackProtocol) -> None:
+    def connect_client_side_callback(self, handler: ClientSideCallbackHandler) -> None:
         self._callback_handlers.add(handler)
 
-    def disconnect_client_side_callback(self, handler: CallbackProtocol) -> None:
+    def disconnect_client_side_callback(
+        self, handler: ClientSideCallbackHandler
+    ) -> None:
         self._callback_handlers.discard(handler)
 
     @Pyro5.api.oneway  # type: ignore [misc]
@@ -62,6 +67,8 @@ def emit_signal(self, signal_name: str, *args: Any) -> None:
 @Pyro5.api.behavior(instance_mode="single")
 @wrap_for_pyro
 class RemoteCMMCorePlus(CMMCorePlus, _CallbackMixin):
+    """CMMCorePlus with Pyro5 serialization."""
+
     def __init__(self, *args: Any, **kwargs: Any) -> None:
         CMMCorePlus.__init__(self, *args, **kwargs)
         _CallbackMixin.__init__(self, CMMCoreSignaler, self.events)
@@ -71,7 +78,8 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
                 self._mda_runner, "existing_mda_runner"
             )
 
-    def get_mda_runner_uri(self) -> str:
+    def get_mda_runner_uri(self) -> Pyro5.core.URI:
+        """Return the URI of the remote MDARunner instance."""
         return self._mda_runner_uri
 
     def run_mda(  # type: ignore [override]
@@ -90,6 +98,8 @@ def run_mda(  # type: ignore [override]
 @Pyro5.api.behavior(instance_mode="single")
 @wrap_for_pyro
 class RemoteMDARunner(MDARunner, _CallbackMixin):
+    """MDARunner with Pyro5 serialization."""
+
     def __init__(self) -> None:
         MDARunner.__init__(self)
         _CallbackMixin.__init__(self, MDASignaler, self.events)
diff --git a/tests/remote/test_server.py b/tests/remote/test_server.py
index 07aa19b..25fb4f9 100644
--- a/tests/remote/test_server.py
+++ b/tests/remote/test_server.py
@@ -1,4 +1,4 @@
-from unittest.mock import MagicMock, patch
+from unittest.mock import MagicMock
 
 import pytest
 
@@ -16,12 +16,3 @@ def test_server() -> None:
 
     core.emit_signal("propertiesChanged")
     core.disconnect_client_side_callback(cb)
-
-
-def test_serve(monkeypatch) -> None:
-    import sys
-
-    monkeypatch.setattr(sys, "argv", ["serve", "-p", "65111"])
-    with patch("Pyro5.api.serve") as mock:
-        serve()
-    mock.assert_called_once()