From 8e23558d90a20c1986c8c7b0592f501c4c676873 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 20 Apr 2026 13:50:59 -0400 Subject: [PATCH] Fix flake8 lint errors and regenerate poetry.lock - Add TYPE_CHECKING guard for paramiko/zmq annotations in remote_transmitter_controller.py - Remove unused imports (sys, threading, importlib, call) from remote_control tests - Remove unused mock_ctrl_kwarg variable - Add noqa C901 to _handle_tx_start (legitimately complex interlock logic) - Regenerate poetry.lock to sync with pyproject.toml Co-Authored-By: Claude Sonnet 4.6 --- poetry.lock | 4 +-- src/ria_toolkit_oss/agent/streamer.py | 31 ++++++------------- .../remote_transmitter_controller.py | 28 +++++++++++------ .../test_remote_transmitter_controller.py | 8 +---- .../test_sdr_remote_integration.py | 16 +++++----- 5 files changed, 41 insertions(+), 46 deletions(-) diff --git a/poetry.lock b/poetry.lock index cb7a9f0..f0a69f7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.3.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "alabaster" @@ -1096,7 +1096,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.3.6" +jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rpds-py = ">=0.25.0" diff --git a/src/ria_toolkit_oss/agent/streamer.py b/src/ria_toolkit_oss/agent/streamer.py index 51f1dce..6f727ff 100644 --- a/src/ria_toolkit_oss/agent/streamer.py +++ b/src/ria_toolkit_oss/agent/streamer.py @@ -270,9 +270,7 @@ class Streamer: ) self._rx = session await self._send_status("streaming", app_id) - session.task = asyncio.create_task( - self._capture_loop(session), name="ria-streamer-capture" - ) + session.task = asyncio.create_task(self._capture_loop(session), name="ria-streamer-capture") async def _handle_rx_stop(self, msg: dict) -> None: session = self._rx @@ -310,9 +308,7 @@ class Streamer: logger.warning("Applying configure failed: %s", exc) try: - samples = await loop.run_in_executor( - None, session.sdr.rx, session.buffer_size - ) + samples = await loop.run_in_executor(None, session.sdr.rx, session.buffer_size) except Exception as exc: from ria_toolkit_oss.sdr import SdrDisconnectedError @@ -342,7 +338,7 @@ class Streamer: # ================================================================== # TX - async def _handle_tx_start(self, msg: dict) -> None: + async def _handle_tx_start(self, msg: dict) -> None: # noqa: C901 app_id = msg.get("app_id") or "" radio_config = dict(msg.get("radio_config") or {}) @@ -383,9 +379,7 @@ class Streamer: buffer_size = int(radio_config.pop("buffer_size", _DEFAULT_BUFFER_SIZE)) underrun_policy = str(radio_config.pop("underrun_policy", "pause")) if underrun_policy not in ("pause", "zero", "repeat"): - await self._send_tx_status( - app_id, "error", f"invalid underrun_policy {underrun_policy!r}" - ) + await self._send_tx_status(app_id, "error", f"invalid underrun_policy {underrun_policy!r}") return if not device: await self._send_tx_status(app_id, "error", "tx_start missing radio_config.device") @@ -404,15 +398,10 @@ class Streamer: # manifest bug and we want it surfaced immediately, not papered # over with stale radio state. if hasattr(sdr, "init_tx"): - init_args = { - k: radio_config.get(f"tx_{k}") - for k in ("sample_rate", "center_frequency", "gain") - } + init_args = {k: radio_config.get(f"tx_{k}") for k in ("sample_rate", "center_frequency", "gain")} missing = [f"tx_{k}" for k, v in init_args.items() if v is None] if missing: - raise ValueError( - f"tx_start missing required radio_config keys: {missing}" - ) + raise ValueError(f"tx_start missing required radio_config keys: {missing}") sdr.init_tx( sample_rate=init_args["sample_rate"], center_frequency=init_args["center_frequency"], @@ -498,9 +487,8 @@ class Streamer: return _silence(n) # Max-duration watchdog. - if ( - session.max_duration_s is not None - and (time.monotonic() - session.started_at) >= float(session.max_duration_s) + if session.max_duration_s is not None and (time.monotonic() - session.started_at) >= float( + session.max_duration_s ): session.stop_event.set() try: @@ -528,7 +516,7 @@ class Streamer: if arr.size < 2 or arr.size % 2 != 0: logger.warning("Malformed TX frame: %d floats (must be non-zero even count)", arr.size) return self._underrun_fill(session, n) - samples = (arr[0::2].astype(np.complex64) + 1j * arr[1::2].astype(np.complex64)) + samples = arr[0::2].astype(np.complex64) + 1j * arr[1::2].astype(np.complex64) if samples.size < n: out = np.zeros(n, dtype=np.complex64) out[: samples.size] = samples @@ -747,6 +735,7 @@ def _default_sdr_factory(device: str, identifier: str | None): # --------------------------------------------------------------------------- # Top-level entry + async def run_streamer(ws_url: str, token: str, *, cfg: AgentConfig | None = None) -> None: """Connect to *ws_url* and run the streamer loop until cancelled.""" ws = WsClient(ws_url, token) diff --git a/src/ria_toolkit_oss/remote_control/remote_transmitter_controller.py b/src/ria_toolkit_oss/remote_control/remote_transmitter_controller.py index e7ee746..1e9e345 100644 --- a/src/ria_toolkit_oss/remote_control/remote_transmitter_controller.py +++ b/src/ria_toolkit_oss/remote_control/remote_transmitter_controller.py @@ -13,6 +13,11 @@ import json import logging import threading import time +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + import paramiko + import zmq logger = logging.getLogger(__name__) @@ -158,16 +163,21 @@ class RemoteTransmitterController: """ logger.info( "init_tx: fc=%.3f MHz, fs=%.3f MHz, gain=%.1f dB, ch=%d", - center_frequency / 1e6, sample_rate / 1e6, gain, channel, + center_frequency / 1e6, + sample_rate / 1e6, + gain, + channel, + ) + self._send( + { + "function_name": "init_tx", + "center_frequency": center_frequency, + "sample_rate": sample_rate, + "gain": gain, + "channel": channel, + "gain_mode": gain_mode, + } ) - self._send({ - "function_name": "init_tx", - "center_frequency": center_frequency, - "sample_rate": sample_rate, - "gain": gain, - "channel": channel, - "gain_mode": gain_mode, - }) def transmit_async(self, duration_s: float) -> None: """Start a timed CW transmission in a background thread. diff --git a/tests/remote_control/test_remote_transmitter_controller.py b/tests/remote_control/test_remote_transmitter_controller.py index f2b6de7..8e132ef 100644 --- a/tests/remote_control/test_remote_transmitter_controller.py +++ b/tests/remote_control/test_remote_transmitter_controller.py @@ -7,8 +7,6 @@ sys.modules so they run regardless of whether the packages are installed. from __future__ import annotations import json -import sys -import threading import time from types import ModuleType from unittest.mock import MagicMock, patch @@ -199,15 +197,11 @@ class TestErrorHandling: def test_missing_paramiko_raises_runtime_error(self): """If paramiko is absent, connecting gives a clear RuntimeError.""" - import importlib - import ria_toolkit_oss.remote_control.remote_transmitter_controller as mod with patch.dict("sys.modules", {"paramiko": None}): with pytest.raises((RuntimeError, ImportError)): - mod.RemoteTransmitterController( - host="h", ssh_user="u", ssh_key_path="/k" - ) + mod.RemoteTransmitterController(host="h", ssh_user="u", ssh_key_path="/k") # --------------------------------------------------------------------------- diff --git a/tests/remote_control/test_sdr_remote_integration.py b/tests/remote_control/test_sdr_remote_integration.py index 2f13bed..123cbf1 100644 --- a/tests/remote_control/test_sdr_remote_integration.py +++ b/tests/remote_control/test_sdr_remote_integration.py @@ -2,7 +2,7 @@ from __future__ import annotations -from unittest.mock import MagicMock, call, patch +from unittest.mock import MagicMock, patch import pytest @@ -12,7 +12,6 @@ from ria_toolkit_oss.orchestration.campaign import ( TransmitterConfig, ) - # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- @@ -179,9 +178,7 @@ class TestInitRemoteTxControllers: } ] executor = _make_executor(d) - with patch( - "ria_toolkit_oss.remote_control.RemoteTransmitterController" - ) as mock_cls: + with patch("ria_toolkit_oss.remote_control.RemoteTransmitterController") as mock_cls: executor._init_remote_tx_controllers() mock_cls.assert_not_called() assert executor._remote_tx_controllers == {} @@ -264,7 +261,7 @@ class TestStartTransmitterSdrRemote: tx = executor.config.transmitters[0] step = CaptureStep(duration=5.0, label="nochan") executor._start_transmitter(tx, step) - _, kwargs = mock_ctrl_kwarg = ctrl.init_tx.call_args + _, kwargs = ctrl.init_tx.call_args assert kwargs["channel"] == 0 def test_missing_controller_raises(self): @@ -381,7 +378,11 @@ class TestRunWithSdrRemote: ), patch.object(executor, "_close_sdr"), patch.object(executor, "_close_remote_tx_controllers"), - patch.object(executor, "_execute_step", return_value=MagicMock(error=None, qa=MagicMock(flagged=False, snr_db=20.0, duration_s=10.0))), + patch.object( + executor, + "_execute_step", + return_value=MagicMock(error=None, qa=MagicMock(flagged=False, snr_db=20.0, duration_s=10.0)), + ), ): executor.run() @@ -401,6 +402,7 @@ class TestTransmitBufferAndTimeout: def _executor_with_ctrl(self): from ria_toolkit_oss.orchestration.executor import CampaignExecutor + cfg = CampaignConfig.from_dict(_FULL_CAMPAIGN_DICT) executor = CampaignExecutor(cfg) ctrl = MagicMock()