From 8f89c4615f63fdc8ee1343185358a711f4384205 Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Wed, 27 May 2026 11:58:19 -0700 Subject: [PATCH] chore(photon): clean up ty type-checker warnings from lint-diff bot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The advisory lint-diff bot flagged 17 new ty diagnostics. 6 are `unresolved-import` for httpx/aiohttp/pytest, which is structural (CI lint env has no project deps) and matches every other platform plugin's noise floor. The remaining 11 are real and fixable: - `Optional[callable]` → `Optional[Callable[..., None]]` (auth.py) invalid-type-form on `callable` as a type expression. Added the proper `typing.Callable` import. Two sites: on_pending in poll_for_token, on_user_code in login_device_flow. - Dropped three unused `# type: ignore` comments on hermes_constants / hermes_cli.config imports — ty can resolve those modules fine, the comments were dead. - _supervise_sidecar(proc) widened `proc.stdout` from `IO[Any] | None` to a narrowed local after an early `is None` guard. Defensive against subprocesses launched without stdout=PIPE. - cli.py _cmd_setup: dropped the `has_existing_project = bool(...)` intermediate, did the narrowing inline with `if existing_id and existing_secret:` so ty can see project_id/project_secret are non-None when create_user is called. - test_inbound.py: replaced three `adapter.handle_message = fake_handle # type: ignore[assignment]` with `monkeypatch.setattr(adapter, 'handle_message', fake_handle)`. Same behavior, no type-ignore, and the monkeypatch reverts cleanly between tests. Validation: ty check plugins/platforms/photon/ tests/plugins/platforms/photon/ → All checks passed! tests/plugins/platforms/photon/ → 26/26 pass py_compile clean Windows footgun checker → 0 footguns --- plugins/platforms/photon/adapter.py | 5 ++++- plugins/platforms/photon/auth.py | 12 ++++++------ plugins/platforms/photon/cli.py | 5 +++-- tests/plugins/platforms/photon/test_inbound.py | 6 +++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/plugins/platforms/photon/adapter.py b/plugins/platforms/photon/adapter.py index 3586f195d3b..0747ab7db3e 100644 --- a/plugins/platforms/photon/adapter.py +++ b/plugins/platforms/photon/adapter.py @@ -513,10 +513,13 @@ class PhotonAdapter(BasePlatformAdapter): async def _supervise_sidecar(self, proc: subprocess.Popen) -> None: """Pump the sidecar's stdout/stderr into our logger.""" + if proc.stdout is None: # subprocess was launched without stdout=PIPE + return + stdout = proc.stdout loop = asyncio.get_event_loop() try: while True: - line = await loop.run_in_executor(None, proc.stdout.readline) + line = await loop.run_in_executor(None, stdout.readline) if not line: break logger.info("[photon-sidecar] %s", line.decode("utf-8", "replace").rstrip()) diff --git a/plugins/platforms/photon/auth.py b/plugins/platforms/photon/auth.py index 978823f5764..3ca2da4c467 100644 --- a/plugins/platforms/photon/auth.py +++ b/plugins/platforms/photon/auth.py @@ -32,7 +32,7 @@ import re import time from dataclasses import dataclass from pathlib import Path -from typing import Any, Dict, Optional, Tuple +from typing import Any, Callable, Dict, Optional, Tuple try: import httpx @@ -68,7 +68,7 @@ E164_RE = re.compile(r"^\+[1-9]\d{6,14}$") def _auth_json_path() -> Path: """Resolve ``~/.hermes/auth.json`` honouring the active Hermes profile.""" try: - from hermes_constants import get_hermes_home # type: ignore + from hermes_constants import get_hermes_home return Path(get_hermes_home()) / "auth.json" except Exception: return Path(os.path.expanduser("~/.hermes")) / "auth.json" @@ -203,7 +203,7 @@ def poll_for_token( client_id: str = DEFAULT_CLIENT_ID, timeout: Optional[int] = None, interval: Optional[int] = None, - on_pending: Optional[callable] = None, + on_pending: Optional[Callable[[], None]] = None, ) -> str: """Poll ``/api/auth/device/token`` until the user approves. @@ -277,7 +277,7 @@ def login_device_flow( *, client_id: str = DEFAULT_CLIENT_ID, open_browser: bool = True, - on_user_code: Optional[callable] = None, + on_user_code: Optional[Callable[["DeviceCode"], None]] = None, ) -> str: """Run the full device-code login flow and persist the token. @@ -536,7 +536,7 @@ def persist_webhook_signing_secret( if not has_secret: return False try: - from hermes_cli.config import save_env_value # type: ignore + from hermes_cli.config import save_env_value except ImportError: return False try: @@ -548,7 +548,7 @@ def persist_webhook_signing_secret( return False if on_summary is not None: try: - from hermes_constants import get_hermes_home # type: ignore + from hermes_constants import get_hermes_home env_path = Path(get_hermes_home()) / ".env" except Exception: env_path = Path(os.path.expanduser("~/.hermes")) / ".env" diff --git a/plugins/platforms/photon/cli.py b/plugins/platforms/photon/cli.py index 9ae1cf07853..420eb4474ab 100644 --- a/plugins/platforms/photon/cli.py +++ b/plugins/platforms/photon/cli.py @@ -131,8 +131,9 @@ def _cmd_setup(args: argparse.Namespace) -> int: # 2. Create (or surface existing) project. existing_id, existing_secret = photon_auth.load_project_credentials() - has_existing_project = bool(existing_id and existing_secret) - if has_existing_project: + project_id: str + project_secret: str + if existing_id and existing_secret: project_id, project_secret = existing_id, existing_secret # `project_id` is a Photon-assigned UUID, not a secret — but we # keep the print terse to avoid CodeQL flow noise. diff --git a/tests/plugins/platforms/photon/test_inbound.py b/tests/plugins/platforms/photon/test_inbound.py index 10c66d07214..00ddcfe4620 100644 --- a/tests/plugins/platforms/photon/test_inbound.py +++ b/tests/plugins/platforms/photon/test_inbound.py @@ -32,7 +32,7 @@ async def test_dispatch_text_dm(monkeypatch: pytest.MonkeyPatch) -> None: async def fake_handle(event: MessageEvent) -> None: captured.append(event) - adapter.handle_message = fake_handle # type: ignore[assignment] + monkeypatch.setattr(adapter, "handle_message", fake_handle) payload = { "event": "messages", @@ -70,7 +70,7 @@ async def test_dispatch_group_id_detected(monkeypatch: pytest.MonkeyPatch) -> No async def fake_handle(event: MessageEvent) -> None: captured.append(event) - adapter.handle_message = fake_handle # type: ignore[assignment] + monkeypatch.setattr(adapter, "handle_message", fake_handle) payload = { "event": "messages", @@ -97,7 +97,7 @@ async def test_dispatch_attachment_surfaces_marker( async def fake_handle(event: MessageEvent) -> None: captured.append(event) - adapter.handle_message = fake_handle # type: ignore[assignment] + monkeypatch.setattr(adapter, "handle_message", fake_handle) payload = { "event": "messages",