mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[chore] clear all 64 pre-existing mypy errors in tests/ (no type:ignore)
Convention: no type:ignore/noqa, and pre-existing violations still violate. The make-quality gate runs 'mypy roboco/ tests/', but the prior commits' gates only ran mypy on production files, masking 64 type errors across 15 test files (method-assign, unused-ignore, no-untyped-def, attr-defined, union-attr, has-type, index, misc). Fixed without any type:ignore: - method-assign (svc.session.X = / svc.method = AsyncMock()): hold a local 'session: MagicMock'/'AsyncMock' and assert on it, or stub via object.__setattr__ / monkeypatch / a typed '_bind' helper returning Any, or alias 'cc: Any = c' (the pattern the file already used). - unused 'type: ignore[assignment]' (real code was method-assign): removed; replaced with the no-suppression patterns above. - 'Callable[...] has no attribute assert_*': keep a typed local ref to the AsyncMock and assert on the local, not the method-typed attr. - no-untyped-def: annotate helper params (Any / pytest.MonkeyPatch). - attr-defined / index / union-attr: type the helper as Any, narrow with an 'is not None' assert, or add the missing attr to a fake. - has-type / return-value: fix the declared return type to the tuple the function actually returns. - PLC0415 inline imports: hoisted to top-level. test_pr_gate_notifies_pm._stub_gate_path converted fully to the 'cc: Any = c' alias (it already used it for one attr) so its five '# type: ignore[method-assign]' suppressions are gone. mypy tests/: 64 errors -> 0 (538 files). ruff check tests/: clean. All 84 tests in the touched files pass.
This commit is contained in:
@@ -74,6 +74,7 @@ async def test_cost_over_cap_finalizes_spawn_session_before_evict(
|
||||
finalize.assert_awaited_once()
|
||||
# finalize ran with the agent still registered (so it could read the model +
|
||||
# usage_session_id), and the instance was evicted only after.
|
||||
assert finalize.await_args is not None
|
||||
assert finalize.await_args.args[0] == "be-dev-1"
|
||||
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ def orch(monkeypatch: pytest.MonkeyPatch) -> AgentOrchestrator:
|
||||
class _FakeTracker:
|
||||
def __init__(self) -> None:
|
||||
self.activated_with: dict[str, object] | None = None
|
||||
self.clear = AsyncMock()
|
||||
|
||||
async def activate(
|
||||
self, *, retry_after: float, affected_agents: list[str], kind: str
|
||||
@@ -141,9 +142,7 @@ async def test_agent_writing_about_error_500_does_not_park(
|
||||
orch, "_tail_container_logs", AsyncMock(return_value=agent_note)
|
||||
)
|
||||
monkeypatch.setattr(orch, "_transcript_tail_text", lambda _a, _lines=80: "")
|
||||
assert (
|
||||
await orch._provider_overload_park_target("be-dev-1", _instance()) is None
|
||||
)
|
||||
assert await orch._provider_overload_park_target("be-dev-1", _instance()) is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -245,7 +244,7 @@ async def test_probe_success_respawns_parked_agent(
|
||||
)
|
||||
}
|
||||
tracker = _FakeTracker()
|
||||
tracker.clear = AsyncMock() # type: ignore[method-assign]
|
||||
tracker.clear = AsyncMock()
|
||||
monkeypatch.setattr(orch, "_make_tracker", lambda _p: tracker)
|
||||
monkeypatch.setattr(orch, "_delete_waiting_record", AsyncMock())
|
||||
monkeypatch.setattr(orch, "_generate_resume_prompt", lambda _r, _res: "resume")
|
||||
|
||||
@@ -126,10 +126,13 @@ async def test_non_self_heal_tasks_dispatch_regardless_of_confirmation() -> None
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _originate_engine(captured: dict[str, Any]) -> SelfHealEngine:
|
||||
def _originate_engine(
|
||||
captured: dict[str, Any],
|
||||
) -> tuple[SelfHealEngine, MagicMock, MagicMock, Any]:
|
||||
"""An engine whose task/project services are mocks that capture the create
|
||||
request — so the held-for-CEO invariant is unit-testable without a DB."""
|
||||
session = MagicMock()
|
||||
session.flush = AsyncMock()
|
||||
|
||||
task_svc = MagicMock()
|
||||
task_svc.list_open_self_heal_tasks = AsyncMock(return_value=[])
|
||||
@@ -147,6 +150,11 @@ def _originate_engine(captured: dict[str, Any]) -> SelfHealEngine:
|
||||
return engine, task_svc, project_svc, _self_heal_mod
|
||||
|
||||
|
||||
def _bind(svc: object, name: str, value: object) -> None:
|
||||
"""Stub `name` on `svc` without tripping mypy's method-assign check."""
|
||||
object.__setattr__(svc, name, value)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_originate_opens_task_held_for_ceo(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
@@ -169,8 +177,7 @@ async def test_originate_opens_task_held_for_ceo(
|
||||
raw_ref="r",
|
||||
)
|
||||
]
|
||||
# Bypass the session.flush (MagicMock session) — _originate awaits it.
|
||||
engine.session.flush = AsyncMock() # type: ignore[assignment]
|
||||
# session.flush is set in _originate_engine (MagicMock) — _originate awaits it.
|
||||
|
||||
count = await engine._originate(obs)
|
||||
|
||||
@@ -196,8 +203,9 @@ async def test_approve_and_start_lifts_the_ceo_hold(
|
||||
) -> None:
|
||||
"""``approve_and_start`` is the CEO's start gate — it flips
|
||||
``confirmed_by_human`` True so a held self-heal task finally dispatches."""
|
||||
svc = TaskService(MagicMock())
|
||||
svc.session.flush = AsyncMock() # type: ignore[assignment]
|
||||
session = MagicMock()
|
||||
session.flush = AsyncMock()
|
||||
svc = TaskService(session)
|
||||
task = MagicMock()
|
||||
task.status = TaskStatus.PENDING
|
||||
task.team = MagicMock()
|
||||
@@ -207,7 +215,7 @@ async def test_approve_and_start_lifts_the_ceo_hold(
|
||||
task.assigned_to = "someone-else"
|
||||
task.task_type = MagicMock()
|
||||
task.task_type.value = "code"
|
||||
svc.get = AsyncMock(return_value=task)
|
||||
_bind(svc, "get", AsyncMock(return_value=task))
|
||||
main_pm = MagicMock(id=MAIN_PM_UUID)
|
||||
agent_svc = MagicMock()
|
||||
agent_svc.get_by_slug = AsyncMock(return_value=main_pm)
|
||||
@@ -240,15 +248,16 @@ async def test_list_pending_for_agent_excludes_held_self_heal() -> None:
|
||||
(``source != 'self_heal' OR confirmed_by_human``), so the database drops a
|
||||
held self-heal task before the agent ever sees the list.
|
||||
"""
|
||||
svc = TaskService(MagicMock())
|
||||
session = MagicMock()
|
||||
result = MagicMock()
|
||||
result.scalars.return_value.all.return_value = []
|
||||
svc.session.execute = AsyncMock(return_value=result)
|
||||
svc.unmet_dependency_ids = AsyncMock(return_value=[]) # type: ignore[assignment]
|
||||
session.execute = AsyncMock(return_value=result)
|
||||
svc = TaskService(session)
|
||||
_bind(svc, "unmet_dependency_ids", AsyncMock(return_value=[]))
|
||||
|
||||
await svc.list_pending_for_agent(MAIN_PM_UUID)
|
||||
|
||||
stmt = svc.session.execute.await_args.args[0]
|
||||
stmt = session.execute.await_args.args[0]
|
||||
compiled = str(
|
||||
stmt.compile(
|
||||
dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}
|
||||
@@ -265,7 +274,7 @@ async def test_list_pending_for_agent_still_offers_delegated_subtask() -> None:
|
||||
PM-delegated work, where the delegation IS the authorization to start) must
|
||||
STILL be offered via give_me_work. A universal confirmed_by_human filter
|
||||
would starve devs of all delegated work."""
|
||||
svc = TaskService(MagicMock())
|
||||
session = MagicMock()
|
||||
|
||||
delegated = MagicMock()
|
||||
delegated.source = "manual" # not self_heal
|
||||
@@ -274,8 +283,9 @@ async def test_list_pending_for_agent_still_offers_delegated_subtask() -> None:
|
||||
|
||||
result = MagicMock()
|
||||
result.scalars.return_value.all.return_value = [delegated]
|
||||
svc.session.execute = AsyncMock(return_value=result)
|
||||
svc.unmet_dependency_ids = AsyncMock(return_value=[]) # type: ignore[assignment]
|
||||
session.execute = AsyncMock(return_value=result)
|
||||
svc = TaskService(session)
|
||||
_bind(svc, "unmet_dependency_ids", AsyncMock(return_value=[]))
|
||||
|
||||
available = await svc.list_pending_for_agent(MAIN_PM_UUID)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user