Skip to content

Commit

Permalink
linting
Browse files Browse the repository at this point in the history
  • Loading branch information
tlambert03 committed Nov 2, 2024
1 parent 4831755 commit 353cfa1
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 33 deletions.
7 changes: 3 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
11 changes: 1 addition & 10 deletions src/pymmcore_remote/_serialize.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion src/pymmcore_remote/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 14 additions & 3 deletions src/pymmcore_remote/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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__(
Expand All @@ -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()

Expand All @@ -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


Expand All @@ -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()
Expand Down
20 changes: 15 additions & 5 deletions src/pymmcore_remote/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import Pyro5
import Pyro5.api
import Pyro5.core
import Pyro5.errors
from click import Path
from pymmcore_plus import CMMCorePlus
Expand All @@ -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
Expand All @@ -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]
Expand All @@ -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)
Expand All @@ -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]
Expand All @@ -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)
Expand Down
11 changes: 1 addition & 10 deletions tests/remote/test_server.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock

import pytest

Expand All @@ -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()

0 comments on commit 353cfa1

Please sign in to comment.