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()