diff --git a/pyproject.toml b/pyproject.toml index b9a5321..7728039 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,23 @@ reportExplicitAny = "hint" reportImplicitStringConcatenation = "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] asyncio_mode = "auto" 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 +] diff --git a/tests/test_agent/test_budget.py b/tests/test_agent/test_budget.py index 0f2d758..b4eb18b 100644 --- a/tests/test_agent/test_budget.py +++ b/tests/test_agent/test_budget.py @@ -17,6 +17,6 @@ def test_truncate_tool_result_long() -> 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") - assert estimate_message_chars(tool) == 6 # noqa: PLR2004 + assert estimate_message_chars(tool) == 6 diff --git a/tests/test_agent/test_loop.py b/tests/test_agent/test_loop.py index 2517284..c2e5290 100644 --- a/tests/test_agent/test_loop.py +++ b/tests/test_agent/test_loop.py @@ -176,7 +176,7 @@ async def test_run_chat_loop_text_only() -> None: assert isinstance(events[0], TextDeltaEvent) assert events[0].content == "hello" assert isinstance(events[1], AssistantMessageEvent) - assert len(messages) == 2 # noqa: PLR2004 + assert len(messages) == 2 assert len(client.calls) == 1 @@ -256,7 +256,7 @@ async def test_run_chat_loop_with_tools() -> None: assert ToolCallEvent in types assert ToolResultEvent in types 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 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]) messages: list[AnyChatMessage] = [UserChatMessage(content="x")] 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 len(client.calls) == 2 # noqa: PLR2004 + assert any(isinstance(e, MaxRoundsEvent) and e.rounds == 2 and not e.continued for e in events) + assert len(client.calls) == 2 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 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 len(client.calls) == 3 # noqa: PLR2004 + assert len(client.calls) == 3 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: 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: @@ -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) loaded = await store.list_messages(session.sid) - assert len(loaded) == 2 # noqa: PLR2004 + assert len(loaded) == 2 assert isinstance(loaded[0], UserChatMessage) assert loaded[0].content == "hi" agent2 = ChatAgent(client, model="m", memory=store, session_id=session.sid) await agent2.load_history() - assert len(agent2.messages) == 2 # noqa: PLR2004 + assert len(agent2.messages) == 2 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 agent.pending_retry_text is None loaded = await store.list_messages(session.sid) - assert len(loaded) == 2 # noqa: PLR2004 + assert len(loaded) == 2 assert isinstance(loaded[0], UserChatMessage) assert loaded[0].content == "ping" await store.close() diff --git a/tests/test_cli/test_editor.py b/tests/test_cli/test_editor.py index 5c03b3c..0915293 100644 --- a/tests/test_cli/test_editor.py +++ b/tests/test_cli/test_editor.py @@ -42,7 +42,7 @@ def test_open_in_editor_splits_args(tmp_path: Path, monkeypatch: pytest.MonkeyPa path = tmp_path / "plyngent.toml" 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 calls.append(list(argv)) @@ -112,7 +112,7 @@ def test_config_edit_command(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> monkeypatch.setenv("EDITOR", "true") 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 calls.append(list(argv)) diff --git a/tests/test_cli/test_repl_commands.py b/tests/test_cli/test_repl_commands.py index 4b697af..bf1e5bd 100644 --- a/tests/test_cli/test_repl_commands.py +++ b/tests/test_cli/test_repl_commands.py @@ -138,8 +138,8 @@ async def test_history(state: ReplState, capsys: pytest.CaptureFixture[str]) -> async def test_rounds(state: ReplState) -> None: assert await handle_slash(state, "/rounds 40") is True - assert state.max_rounds == 40 # noqa: PLR2004 - assert state.agent.max_rounds == 40 # noqa: PLR2004 + assert state.max_rounds == 40 + assert state.agent.max_rounds == 40 async def test_status_shows_context_chars( diff --git a/tests/test_cli/test_retry.py b/tests/test_cli/test_retry.py index 3e0e168..b858489 100644 --- a/tests/test_cli/test_retry.py +++ b/tests/test_cli/test_retry.py @@ -112,9 +112,9 @@ async def test_auto_retry_eventually_succeeds(monkeypatch: pytest.MonkeyPatch) - delays=(0.01, 0.01, 0.01), ) assert ok is True - assert client.calls == 3 # noqa: PLR2004 + assert client.calls == 3 loaded = await store.list_messages(session.sid) - assert len(loaded) == 2 # noqa: PLR2004 + assert len(loaded) == 2 assert isinstance(loaded[0], UserChatMessage) assert loaded[0].content == "hello" await store.close() @@ -205,7 +205,7 @@ async def test_manual_retry_after_exhausted(monkeypatch: pytest.MonkeyPatch) -> assert ok2 is True assert agent.pending_retry_text is None loaded = await store.list_messages(session.sid) - assert len(loaded) == 2 # noqa: PLR2004 + assert len(loaded) == 2 assert isinstance(loaded[0], UserChatMessage) assert loaded[0].content == "hold-me" await store.close() diff --git a/tests/test_config/test_agent_section.py b/tests/test_config/test_agent_section.py index 961e59d..9032bae 100644 --- a/tests/test_config/test_agent_section.py +++ b/tests/test_config/test_agent_section.py @@ -13,11 +13,11 @@ def test_agent_section_defaults(tmp_path: Path) -> None: _ = path.write_text("", encoding="utf-8") store = load(path) 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.confirm_destructive is True 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: @@ -36,8 +36,8 @@ max_context_chars = 5000 ) store = load(path) 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.confirm_destructive is False 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 diff --git a/tests/test_memory/test_store.py b/tests/test_memory/test_store.py index 81fc902..97c8efc 100644 --- a/tests/test_memory/test_store.py +++ b/tests/test_memory/test_store.py @@ -45,7 +45,7 @@ async def test_append_and_list_messages(store: MemoryStore) -> None: assert row1.seq == 1 messages = await store.list_messages(session.sid) - assert len(messages) == 2 # noqa: PLR2004 + assert len(messages) == 2 assert isinstance(messages[0], UserChatMessage) assert messages[0].content == "hello" assert isinstance(messages[1], AssistantChatMessage) diff --git a/tests/test_tools/test_process.py b/tests/test_tools/test_process.py index bac49ac..445c116 100644 --- a/tests/test_tools/test_process.py +++ b/tests/test_tools/test_process.py @@ -181,7 +181,7 @@ def test_pty_session_limit_continue(workspace: object) -> None: second = call_sync(open_pty, ["sleep", "30"]) assert "session_id=" in first assert "session_id=" in second - assert PtyManager.max_sessions >= 2 # noqa: PLR2004 + assert PtyManager.max_sessions >= 2 finally: PtyManager.close_all() PtyManager.configure(max_sessions=previous) diff --git a/tests/test_tools/test_tree.py b/tests/test_tools/test_tree.py index 42b51b4..9cc4e1b 100644 --- a/tests/test_tools/test_tree.py +++ b/tests/test_tools/test_tree.py @@ -60,7 +60,7 @@ def test_tree_max_entries(workspace: object) -> None: assert "more entries not shown" in out # only first 10 of 60 files listed as entries 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: