From 9af8684d8fac3e8a7fa339217228804357a43671 Mon Sep 17 00:00:00 2001 From: Joshua Jeon Date: Mon, 28 Sep 2026 11:21:48 -0700 Subject: [PATCH] fix(server): annotate SQLAlchemy result rows for 2.1 type inference [SAO-17580] SQLAlchemy 2.1.0 no longer lets mypy infer the element type through `result.scalars().all()`, so `make typecheck` fails on `main` and on every open PR with var-annotated. The repository lock pins 2.0.51, which still infers it, so the error surfaces only in CI where dependencies resolve fresh. Main's own run at bd7d91f installs mypy 2.3.1 and sqlalchemy 2.1.0 and reports the error, which is why re-running a job does not clear it. Annotate all four call sites that share the pattern. CI reports only the first, so fixing them one at a time would surface the next on the following run. The annotations hold under 2.0.51 and 2.1.0 alike, so the result does not depend on which version CI resolves. Raising the SQLAlchemy floor or regenerating the lock is left alone. That is a wider dependency decision, and these annotations are correct either way. --- server/src/agent_control_server/endpoints/agents.py | 2 +- server/src/agent_control_server/services/control_bindings.py | 2 +- server/src/agent_control_server/services/controls.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/agent_control_server/endpoints/agents.py b/server/src/agent_control_server/endpoints/agents.py index 1d8efe4b3..e397134b7 100644 --- a/server/src/agent_control_server/endpoints/agents.py +++ b/server/src/agent_control_server/endpoints/agents.py @@ -460,7 +460,7 @@ async def list_agents( # Fetch limit + 1 to check if there are more pages query = query.limit(limit + 1) result = await db.execute(query) - agents = result.scalars().all() + agents: Sequence[Agent] = result.scalars().all() # Check if there are more pages has_more = len(agents) > limit diff --git a/server/src/agent_control_server/services/control_bindings.py b/server/src/agent_control_server/services/control_bindings.py index f6b04d443..b4118bd6b 100644 --- a/server/src/agent_control_server/services/control_bindings.py +++ b/server/src/agent_control_server/services/control_bindings.py @@ -279,7 +279,7 @@ def _apply_filters(stmt): # type: ignore[no-untyped-def] if cursor is not None: page_stmt = page_stmt.where(ControlBinding.id < cursor) result = await self._db.execute(page_stmt.limit(limit + 1)) - rows = list(result.scalars().all()) + rows: list[ControlBinding] = list(result.scalars().all()) has_more = len(rows) > limit if has_more: rows = rows[:limit] diff --git a/server/src/agent_control_server/services/controls.py b/server/src/agent_control_server/services/controls.py index 619cbed1f..afe38bf62 100644 --- a/server/src/agent_control_server/services/controls.py +++ b/server/src/agent_control_server/services/controls.py @@ -303,7 +303,7 @@ async def list_versions( stmt = stmt.where(ControlVersion.version_num < cursor) result = await self._db.execute(stmt.limit(limit + 1)) - versions = list(result.scalars().all()) + versions: list[ControlVersion] = list(result.scalars().all()) has_more = len(versions) > limit if has_more: @@ -509,7 +509,7 @@ async def list_controls_page( query = query.where(Control.id < cursor) result = await self._db.execute(query.limit(limit + 1)) - controls = list(result.scalars().all()) + controls: list[Control] = list(result.scalars().all()) total_query = ( select(func.count())