ci/lint: per-file ignores for tests in ruff and basedpyright

Relax ANN/ARG/PLR/C901 and related rules under tests/**; silence noisy
basedpyright reports for test fakes and private helpers.
This commit is contained in:
2026-07-15 10:35:30 +08:00
parent c5745e0711
commit 5c13e06427
10 changed files with 58 additions and 25 deletions
+33
View File
@@ -42,6 +42,23 @@ reportExplicitAny = "hint"
reportImplicitStringConcatenation = "hint" reportImplicitStringConcatenation = "hint"
reportImportCycles = "hint" reportImportCycles = "hint"
[[tool.basedpyright.executionEnvironments]]
root = "tests"
extraPaths = ["src", "."]
reportPrivateUsage = "none"
reportUnreachable = "none"
reportUnusedCallResult = "none"
reportUnannotatedClassAttribute = "none"
reportUnknownArgumentType = "none"
reportUnknownLambdaType = "none"
reportUnknownMemberType = "none"
reportUnknownVariableType = "none"
reportUnknownParameterType = "none"
reportMissingParameterType = "none"
reportUnusedParameter = "none"
reportMissingImports = "none"
reportMissingTypeStubs = "none"
[tool.pytest.ini_options] [tool.pytest.ini_options]
asyncio_mode = "auto" asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function" asyncio_default_fixture_loop_scope = "function"
@@ -129,3 +146,19 @@ allowed-confusables = [
"", "",
"、" "、"
] ]
[tool.ruff.lint.per-file-ignores]
"tests/**" = [
"ANN", # type annotations often noisy in tests
"ARG", # unused fixtures/args are common
"ASYNC240", # pathlib in async tests is fine
"PLR2004", # magic values in asserts
"PLR0911", # many returns in fixtures/helpers
"PLR0912", # branching in scripted clients
"PLR0915", # long test functions
"C901", # complexity in scripted fakes
"S101", # assert is the point of tests
"TC", # TYPE_CHECKING import churn
"TRY003", # long exception messages in tests
"FBT", # boolean positional args in helpers
]
+2 -2
View File
@@ -17,6 +17,6 @@ def test_truncate_tool_result_long() -> None:
def test_estimate_message_chars() -> None: def test_estimate_message_chars() -> None:
assert estimate_message_chars(UserChatMessage(content="hello")) == 5 # noqa: PLR2004 assert estimate_message_chars(UserChatMessage(content="hello")) == 5
tool = ToolChatMessage(content="abc", tool_call_id="id1") tool = ToolChatMessage(content="abc", tool_call_id="id1")
assert estimate_message_chars(tool) == 6 # noqa: PLR2004 assert estimate_message_chars(tool) == 6
+9 -9
View File
@@ -176,7 +176,7 @@ async def test_run_chat_loop_text_only() -> None:
assert isinstance(events[0], TextDeltaEvent) assert isinstance(events[0], TextDeltaEvent)
assert events[0].content == "hello" assert events[0].content == "hello"
assert isinstance(events[1], AssistantMessageEvent) assert isinstance(events[1], AssistantMessageEvent)
assert len(messages) == 2 # noqa: PLR2004 assert len(messages) == 2
assert len(client.calls) == 1 assert len(client.calls) == 1
@@ -256,7 +256,7 @@ async def test_run_chat_loop_with_tools() -> None:
assert ToolCallEvent in types assert ToolCallEvent in types
assert ToolResultEvent in types assert ToolResultEvent in types
assert any(isinstance(e, TextDeltaEvent) and e.content == "3" for e in events) assert any(isinstance(e, TextDeltaEvent) and e.content == "3" for e in events)
assert len(client.calls) == 2 # noqa: PLR2004 assert len(client.calls) == 2
# second call includes tool result message # second call includes tool result message
assert any(getattr(m, "tool_call_id", None) == "c1" for m in client.calls[1].messages) assert any(getattr(m, "tool_call_id", None) == "c1" for m in client.calls[1].messages)
@@ -281,8 +281,8 @@ async def test_max_rounds() -> None:
client = ScriptedClient([forever, forever, forever]) client = ScriptedClient([forever, forever, forever])
messages: list[AnyChatMessage] = [UserChatMessage(content="x")] messages: list[AnyChatMessage] = [UserChatMessage(content="x")]
events = [e async for e in run_chat_loop(client, messages, model="m", tools=registry, max_rounds=2)] events = [e async for e in run_chat_loop(client, messages, model="m", tools=registry, max_rounds=2)]
assert any(isinstance(e, MaxRoundsEvent) and e.rounds == 2 and not e.continued for e in events) # noqa: PLR2004 assert any(isinstance(e, MaxRoundsEvent) and e.rounds == 2 and not e.continued for e in events)
assert len(client.calls) == 2 # noqa: PLR2004 assert len(client.calls) == 2
async def test_max_rounds_continue_hook() -> None: async def test_max_rounds_continue_hook() -> None:
@@ -325,7 +325,7 @@ async def test_max_rounds_continue_hook() -> None:
assert len(asks) == 1 assert len(asks) == 1
assert any(isinstance(e, MaxRoundsEvent) and e.continued for e in events) assert any(isinstance(e, MaxRoundsEvent) and e.continued for e in events)
assert any(isinstance(e, TextDeltaEvent) and e.content == "done" for e in events) assert any(isinstance(e, TextDeltaEvent) and e.content == "done" for e in events)
assert len(client.calls) == 3 # noqa: PLR2004 assert len(client.calls) == 3
async def test_max_rounds_async_continue_hook() -> None: async def test_max_rounds_async_continue_hook() -> None:
@@ -373,7 +373,7 @@ async def test_max_rounds_async_continue_hook() -> None:
async def test_default_max_rounds_is_generous() -> None: async def test_default_max_rounds_is_generous() -> None:
from plyngent.agent.loop import DEFAULT_MAX_ROUNDS from plyngent.agent.loop import DEFAULT_MAX_ROUNDS
assert DEFAULT_MAX_ROUNDS >= 16 # noqa: PLR2004 assert DEFAULT_MAX_ROUNDS >= 16
async def test_chat_agent_memory_roundtrip() -> None: async def test_chat_agent_memory_roundtrip() -> None:
@@ -385,13 +385,13 @@ async def test_chat_agent_memory_roundtrip() -> None:
assert any(isinstance(e, TextDeltaEvent) and e.content == "yo" for e in events) assert any(isinstance(e, TextDeltaEvent) and e.content == "yo" for e in events)
loaded = await store.list_messages(session.sid) loaded = await store.list_messages(session.sid)
assert len(loaded) == 2 # noqa: PLR2004 assert len(loaded) == 2
assert isinstance(loaded[0], UserChatMessage) assert isinstance(loaded[0], UserChatMessage)
assert loaded[0].content == "hi" assert loaded[0].content == "hi"
agent2 = ChatAgent(client, model="m", memory=store, session_id=session.sid) agent2 = ChatAgent(client, model="m", memory=store, session_id=session.sid)
await agent2.load_history() await agent2.load_history()
assert len(agent2.messages) == 2 # noqa: PLR2004 assert len(agent2.messages) == 2
await store.close() await store.close()
@@ -477,7 +477,7 @@ async def test_chat_agent_retry_after_failure() -> None:
assert any(isinstance(e, TextDeltaEvent) and e.content == "recovered" for e in events) assert any(isinstance(e, TextDeltaEvent) and e.content == "recovered" for e in events)
assert agent.pending_retry_text is None assert agent.pending_retry_text is None
loaded = await store.list_messages(session.sid) loaded = await store.list_messages(session.sid)
assert len(loaded) == 2 # noqa: PLR2004 assert len(loaded) == 2
assert isinstance(loaded[0], UserChatMessage) assert isinstance(loaded[0], UserChatMessage)
assert loaded[0].content == "ping" assert loaded[0].content == "ping"
await store.close() await store.close()
+2 -2
View File
@@ -42,7 +42,7 @@ def test_open_in_editor_splits_args(tmp_path: Path, monkeypatch: pytest.MonkeyPa
path = tmp_path / "plyngent.toml" path = tmp_path / "plyngent.toml"
calls: list[list[str]] = [] calls: list[list[str]] = []
def fake_run(argv: list[str], check: bool = False) -> object: # noqa: FBT001, FBT002 def fake_run(argv: list[str], check: bool = False) -> object:
del check del check
calls.append(list(argv)) calls.append(list(argv))
@@ -112,7 +112,7 @@ def test_config_edit_command(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) ->
monkeypatch.setenv("EDITOR", "true") monkeypatch.setenv("EDITOR", "true")
calls: list[list[str]] = [] calls: list[list[str]] = []
def fake_run(argv: list[str], check: bool = False) -> object: # noqa: FBT001, FBT002 def fake_run(argv: list[str], check: bool = False) -> object:
del check del check
calls.append(list(argv)) calls.append(list(argv))
+2 -2
View File
@@ -138,8 +138,8 @@ async def test_history(state: ReplState, capsys: pytest.CaptureFixture[str]) ->
async def test_rounds(state: ReplState) -> None: async def test_rounds(state: ReplState) -> None:
assert await handle_slash(state, "/rounds 40") is True assert await handle_slash(state, "/rounds 40") is True
assert state.max_rounds == 40 # noqa: PLR2004 assert state.max_rounds == 40
assert state.agent.max_rounds == 40 # noqa: PLR2004 assert state.agent.max_rounds == 40
async def test_status_shows_context_chars( async def test_status_shows_context_chars(
+3 -3
View File
@@ -112,9 +112,9 @@ async def test_auto_retry_eventually_succeeds(monkeypatch: pytest.MonkeyPatch) -
delays=(0.01, 0.01, 0.01), delays=(0.01, 0.01, 0.01),
) )
assert ok is True assert ok is True
assert client.calls == 3 # noqa: PLR2004 assert client.calls == 3
loaded = await store.list_messages(session.sid) loaded = await store.list_messages(session.sid)
assert len(loaded) == 2 # noqa: PLR2004 assert len(loaded) == 2
assert isinstance(loaded[0], UserChatMessage) assert isinstance(loaded[0], UserChatMessage)
assert loaded[0].content == "hello" assert loaded[0].content == "hello"
await store.close() await store.close()
@@ -205,7 +205,7 @@ async def test_manual_retry_after_exhausted(monkeypatch: pytest.MonkeyPatch) ->
assert ok2 is True assert ok2 is True
assert agent.pending_retry_text is None assert agent.pending_retry_text is None
loaded = await store.list_messages(session.sid) loaded = await store.list_messages(session.sid)
assert len(loaded) == 2 # noqa: PLR2004 assert len(loaded) == 2
assert isinstance(loaded[0], UserChatMessage) assert isinstance(loaded[0], UserChatMessage)
assert loaded[0].content == "hold-me" assert loaded[0].content == "hold-me"
await store.close() await store.close()
+4 -4
View File
@@ -13,11 +13,11 @@ def test_agent_section_defaults(tmp_path: Path) -> None:
_ = path.write_text("", encoding="utf-8") _ = path.write_text("", encoding="utf-8")
store = load(path) store = load(path)
assert store.agent_config.system_prompt == "" assert store.agent_config.system_prompt == ""
assert store.agent_config.max_tool_result_chars == 32_000 # noqa: PLR2004 assert store.agent_config.max_tool_result_chars == 32_000
assert store.agent_config.parallel_tools is True assert store.agent_config.parallel_tools is True
assert store.agent_config.confirm_destructive is True assert store.agent_config.confirm_destructive is True
assert store.agent_config.path_denylist == [] assert store.agent_config.path_denylist == []
assert store.agent_config.max_context_chars == 200_000 # noqa: PLR2004 assert store.agent_config.max_context_chars == 200_000
def test_agent_section_parse(tmp_path: Path) -> None: def test_agent_section_parse(tmp_path: Path) -> None:
@@ -36,8 +36,8 @@ max_context_chars = 5000
) )
store = load(path) store = load(path)
assert store.agent_config.system_prompt == "Be brief." assert store.agent_config.system_prompt == "Be brief."
assert store.agent_config.max_tool_result_chars == 100 # noqa: PLR2004 assert store.agent_config.max_tool_result_chars == 100
assert store.agent_config.parallel_tools is False assert store.agent_config.parallel_tools is False
assert store.agent_config.confirm_destructive is False assert store.agent_config.confirm_destructive is False
assert store.agent_config.path_denylist == ["/secrets/", ".ssh/"] assert store.agent_config.path_denylist == ["/secrets/", ".ssh/"]
assert store.agent_config.max_context_chars == 5000 # noqa: PLR2004 assert store.agent_config.max_context_chars == 5000
+1 -1
View File
@@ -45,7 +45,7 @@ async def test_append_and_list_messages(store: MemoryStore) -> None:
assert row1.seq == 1 assert row1.seq == 1
messages = await store.list_messages(session.sid) messages = await store.list_messages(session.sid)
assert len(messages) == 2 # noqa: PLR2004 assert len(messages) == 2
assert isinstance(messages[0], UserChatMessage) assert isinstance(messages[0], UserChatMessage)
assert messages[0].content == "hello" assert messages[0].content == "hello"
assert isinstance(messages[1], AssistantChatMessage) assert isinstance(messages[1], AssistantChatMessage)
+1 -1
View File
@@ -181,7 +181,7 @@ def test_pty_session_limit_continue(workspace: object) -> None:
second = call_sync(open_pty, ["sleep", "30"]) second = call_sync(open_pty, ["sleep", "30"])
assert "session_id=" in first assert "session_id=" in first
assert "session_id=" in second assert "session_id=" in second
assert PtyManager.max_sessions >= 2 # noqa: PLR2004 assert PtyManager.max_sessions >= 2
finally: finally:
PtyManager.close_all() PtyManager.close_all()
PtyManager.configure(max_sessions=previous) PtyManager.configure(max_sessions=previous)
+1 -1
View File
@@ -60,7 +60,7 @@ def test_tree_max_entries(workspace: object) -> None:
assert "more entries not shown" in out assert "more entries not shown" in out
# only first 10 of 60 files listed as entries # only first 10 of 60 files listed as entries
listed = [line for line in out.splitlines() if line.strip().endswith(".txt")] listed = [line for line in out.splitlines() if line.strip().endswith(".txt")]
assert len(listed) == 10 # noqa: PLR2004 assert len(listed) == 10
def test_tree_origin_subdir(workspace: object) -> None: def test_tree_origin_subdir(workspace: object) -> None: