fix(tests): resolve pyright strict errors in forge test helpers
CI runs `pyright .` over the whole repo including tests; the earlier run only checked the source paths. The test helpers used `**over` dict-splat into typed constructors, which pyright strict rejects. - forge_state: build a typed ForgeState base and dataclasses.replace(**over) - provenance: explicit typed keyword params instead of a **over dict - resume: _launch_kwargs returns dict[str, Any] (copy call_args.kwargs) - forge_base: assert PermissionError in __mro__ (avoids always-true issubclass) - client: annotate _resp body param; type: ignore the mock __enter__ lambda pyright . now 0 errors; 47 tests still pass; pylint 9.97/10. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WL77TgFxKbs3cidGMG9dz7
This commit is contained in:
@@ -8,6 +8,7 @@ core (`assume_yes` + `headless_prompt_text`) as `start --headless`.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
from typing import Any
|
||||||
from unittest.mock import MagicMock, patch
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
import bot_bottle.cli.resume as resume_mod
|
import bot_bottle.cli.resume as resume_mod
|
||||||
@@ -40,9 +41,9 @@ class ResumeHeadlessTest(unittest.TestCase):
|
|||||||
).start()
|
).start()
|
||||||
self.addCleanup(patch.stopall)
|
self.addCleanup(patch.stopall)
|
||||||
|
|
||||||
def _launch_kwargs(self) -> dict:
|
def _launch_kwargs(self) -> dict[str, Any]:
|
||||||
self._launch.assert_called_once()
|
self._launch.assert_called_once()
|
||||||
return self._launch.call_args.kwargs
|
return dict(self._launch.call_args.kwargs)
|
||||||
|
|
||||||
def test_headless_passes_assume_yes_and_prompt(self):
|
def test_headless_passes_assume_yes_and_prompt(self):
|
||||||
rc = resume_mod.cmd_resume(
|
rc = resume_mod.cmd_resume(
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class TestScopedForgeWrites(unittest.TestCase):
|
|||||||
|
|
||||||
def test_scope_error_is_permission_error(self):
|
def test_scope_error_is_permission_error(self):
|
||||||
# Sidecars can catch the stdlib base type.
|
# Sidecars can catch the stdlib base type.
|
||||||
self.assertTrue(issubclass(ForgeScopeError, PermissionError))
|
self.assertIn(PermissionError, ForgeScopeError.__mro__)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ def _client() -> GiteaClient:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _resp(body, status: int = 200) -> MagicMock:
|
def _resp(body: object, status: int = 200) -> MagicMock:
|
||||||
resp = MagicMock()
|
resp = MagicMock()
|
||||||
resp.read.return_value = json.dumps(body).encode() if body is not None else b""
|
resp.read.return_value = json.dumps(body).encode() if body is not None else b""
|
||||||
resp.status = status
|
resp.status = status
|
||||||
resp.__enter__ = lambda s: s
|
resp.__enter__ = lambda s: s # type: ignore
|
||||||
resp.__exit__ = MagicMock(return_value=False)
|
resp.__exit__ = MagicMock(return_value=False)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
from dataclasses import replace
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
@@ -15,22 +16,21 @@ from bot_bottle.contrib.gitea.forge_state import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _state(**over) -> ForgeState:
|
def _state(**over: object) -> ForgeState:
|
||||||
base = {
|
base = ForgeState(
|
||||||
"owner": "didericis",
|
owner="didericis",
|
||||||
"repo": "bot-bottle",
|
repo="bot-bottle",
|
||||||
"issue_number": 17,
|
issue_number=17,
|
||||||
"slug": "implementer-abc12",
|
slug="implementer-abc12",
|
||||||
"agent_name": "implementer",
|
agent_name="implementer",
|
||||||
"bottle_names": ["claude"],
|
bottle_names=["claude"],
|
||||||
"backend_name": "docker",
|
backend_name="docker",
|
||||||
"agent_git_user": "didericis-claude",
|
agent_git_user="didericis-claude",
|
||||||
"pr_number": 42,
|
pr_number=42,
|
||||||
"status": STATUS_FROZEN,
|
status=STATUS_FROZEN,
|
||||||
"last_checkin_at": "2026-06-29T12:04:12-04:00",
|
last_checkin_at="2026-06-29T12:04:12-04:00",
|
||||||
}
|
)
|
||||||
base.update(over)
|
return replace(base, **over)
|
||||||
return ForgeState(**base)
|
|
||||||
|
|
||||||
|
|
||||||
class ForgeStateTest(unittest.TestCase):
|
class ForgeStateTest(unittest.TestCase):
|
||||||
|
|||||||
@@ -7,16 +7,29 @@ import unittest
|
|||||||
from bot_bottle.contrib.gitea.provenance import build_provenance_footer
|
from bot_bottle.contrib.gitea.provenance import build_provenance_footer
|
||||||
|
|
||||||
|
|
||||||
def _footer(slug: str = "implementer-abc12", **over) -> str:
|
def _footer(
|
||||||
base = {
|
slug: str = "implementer-abc12",
|
||||||
"agent_name": "implementer",
|
*,
|
||||||
"bottle_names": ("claude",),
|
agent_name: str = "implementer",
|
||||||
"started_at": "2026-06-29T12:00:00-04:00",
|
bottle_names: tuple[str, ...] = ("claude",),
|
||||||
"finished_at": "2026-06-29T12:04:12-04:00",
|
started_at: str = "2026-06-29T12:00:00-04:00",
|
||||||
"exit_code": 0,
|
finished_at: str = "2026-06-29T12:04:12-04:00",
|
||||||
}
|
exit_code: int = 0,
|
||||||
base.update(over)
|
watchdog_fired: bool = False,
|
||||||
return build_provenance_footer(slug, **base)
|
gitleaks_clean: bool | None = None,
|
||||||
|
egress_routes: list[str] | None = None,
|
||||||
|
) -> str:
|
||||||
|
return build_provenance_footer(
|
||||||
|
slug,
|
||||||
|
agent_name=agent_name,
|
||||||
|
bottle_names=bottle_names,
|
||||||
|
started_at=started_at,
|
||||||
|
finished_at=finished_at,
|
||||||
|
exit_code=exit_code,
|
||||||
|
watchdog_fired=watchdog_fired,
|
||||||
|
gitleaks_clean=gitleaks_clean,
|
||||||
|
egress_routes=egress_routes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ProvenanceTest(unittest.TestCase):
|
class ProvenanceTest(unittest.TestCase):
|
||||||
|
|||||||
Reference in New Issue
Block a user