diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2e96975..08ebfa03 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,22 @@ on: branches: [main] jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-python@v6 + with: + python-version: "3.12" + cache: "pip" + - name: Install ruff + # Pinned to match the ruff-pre-commit rev in .pre-commit-config.yaml + run: pip install ruff==0.15.8 + - name: Ruff lint + run: ruff check src/ tests/ + - name: Ruff format check + run: ruff format --check src/ tests/ + test: runs-on: ubuntu-latest strategy: @@ -45,7 +61,7 @@ jobs: build: runs-on: ubuntu-latest - needs: [test, security] + needs: [lint, test, security] steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 diff --git a/tests/agent/test_agent_cache.py b/tests/agent/test_agent_cache.py index b36942e4..b131b5ab 100644 --- a/tests/agent/test_agent_cache.py +++ b/tests/agent/test_agent_cache.py @@ -295,11 +295,11 @@ def test_routing_mode_caches(self) -> None: config = AgentConfig(max_iterations=1, routing_only=True, cache=cache) agent = Agent(tools=[_dummy_tool()], provider=provider, config=config) - result1 = agent.run([Message(role=Role.USER, content="Route me")]) + agent.run([Message(role=Role.USER, content="Route me")]) assert provider.call_count == 1 agent.reset() - result2 = agent.run([Message(role=Role.USER, content="Route me")]) + agent.run([Message(role=Role.USER, content="Route me")]) assert provider.call_count == 1 # cache hit assert cache.stats.hits == 1 diff --git a/tests/agent/test_agent_observer.py b/tests/agent/test_agent_observer.py index fe2f0554..f2975e49 100644 --- a/tests/agent/test_agent_observer.py +++ b/tests/agent/test_agent_observer.py @@ -22,8 +22,6 @@ from __future__ import annotations -import asyncio -import copy import json import logging from dataclasses import dataclass, field @@ -723,7 +721,7 @@ def complete( return msg, stats agent, obs = _agent(provider=JSONProvider()) - result = agent.run("what is the answer?", response_format=Response) + agent.run("what is the answer?", response_format=Response) validates = obs.get("structured_validate") assert len(validates) >= 1 assert validates[0].args["success"] is True diff --git a/tests/agent/test_agent_v013_e2e.py b/tests/agent/test_agent_v013_e2e.py index 4a3167b4..4319ed7f 100644 --- a/tests/agent/test_agent_v013_e2e.py +++ b/tests/agent/test_agent_v013_e2e.py @@ -28,16 +28,13 @@ ConversationMemory, FallbackProvider, Message, - PolicyDecision, Role, ToolPolicy, tool, ) -from selectools.providers.base import Provider, ProviderError +from selectools.providers.base import ProviderError from selectools.providers.openai_provider import OpenAIProvider from selectools.trace import AgentTrace -from selectools.types import Message as Msg -from selectools.usage import UsageStats try: from pydantic import BaseModel diff --git a/tests/agent/test_astream_parity.py b/tests/agent/test_astream_parity.py index 8acf4fe0..c1faeed7 100644 --- a/tests/agent/test_astream_parity.py +++ b/tests/agent/test_astream_parity.py @@ -7,21 +7,19 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Any, AsyncGenerator, Dict, List, Optional, Tuple, Union +from typing import Any, AsyncGenerator, Dict, List, Tuple, Union from unittest.mock import MagicMock import pytest -from selectools.agent.core import Agent, AgentConfig, _RunContext +from selectools.agent.core import Agent, AgentConfig from selectools.exceptions import GraphExecutionError -from selectools.guardrails import Guardrail, GuardrailAction, GuardrailResult, GuardrailsPipeline +from selectools.guardrails import Guardrail, GuardrailResult, GuardrailsPipeline from selectools.observer import AgentObserver from selectools.policy import PolicyDecision, PolicyResult, ToolPolicy from selectools.providers.base import Provider -from selectools.structured import ResponseFormat -from selectools.tools import Tool, tool -from selectools.trace import AgentTrace -from selectools.types import AgentResult, Message, Role, StreamChunk, ToolCall +from selectools.tools import tool +from selectools.types import AgentResult, Message, Role, ToolCall from selectools.usage import UsageStats _DUMMY_USAGE = UsageStats(0, 0, 0, 0.0, "mock", "mock") @@ -242,7 +240,7 @@ def check(self, content: str) -> GuardrailResult: provider=provider, config=AgentConfig(max_iterations=1, guardrails=pipeline), ) - result = await _collect_astream(agent, "This is bad") + await _collect_astream(agent, "This is bad") # The guardrail should have rewritten "bad" to "good" in the history user_msgs = [m for m in agent._history if m.role == Role.USER] assert any("good" in (m.content or "") for m in user_msgs) @@ -288,7 +286,7 @@ async def test_knowledge_memory_context_injected(self) -> None: provider=provider, config=AgentConfig(max_iterations=1, knowledge_memory=km), ) - result = await _collect_astream(agent, "Hello") + await _collect_astream(agent, "Hello") system_msgs = [m for m in agent._history if m.role == Role.SYSTEM] assert any("User prefers Python" in (m.content or "") for m in system_msgs) @@ -308,7 +306,7 @@ async def test_entity_memory_context_injected(self) -> None: provider=provider, config=AgentConfig(max_iterations=1, entity_memory=em), ) - result = await _collect_astream(agent, "Hi") + await _collect_astream(agent, "Hi") system_msgs = [m for m in agent._history if m.role == Role.SYSTEM] assert any("Alice: engineer" in (m.content or "") for m in system_msgs) @@ -328,7 +326,7 @@ async def test_knowledge_graph_context_injected(self) -> None: provider=provider, config=AgentConfig(max_iterations=1, knowledge_graph=kg), ) - result = await _collect_astream(agent, "Tell me about Alice") + await _collect_astream(agent, "Tell me about Alice") system_msgs = [m for m in agent._history if m.role == Role.SYSTEM] assert any("Alice -> works_at -> Acme" in (m.content or "") for m in system_msgs) @@ -501,7 +499,7 @@ async def test_analytics_recorded(self) -> None: provider=provider, config=AgentConfig(max_iterations=2, enable_analytics=True), ) - result = await _collect_astream(agent, "Greet Bob") + await _collect_astream(agent, "Greet Bob") assert agent.analytics is not None metrics = agent.analytics.get_metrics("greet_tool") assert metrics is not None @@ -895,7 +893,7 @@ async def test_tool_usage_dict_populated(self) -> None: provider=provider, config=AgentConfig(max_iterations=2), ) - result = await _collect_astream(agent, "Greet Alice") + await _collect_astream(agent, "Greet Alice") assert "greet_tool" in agent.usage.tool_usage assert agent.usage.tool_usage["greet_tool"] >= 1 @@ -1184,7 +1182,7 @@ def suspicious_tool() -> str: provider=provider, config=AgentConfig(max_iterations=2, screen_tool_output=True), ) - result = agent.run("Use both tools") + agent.run("Use both tools") # Screening should have caught the injection pattern in the tool result # The tool result in history should be modified by screening tool_msgs = [ @@ -1209,7 +1207,7 @@ def suspicious_tool_async() -> str: provider=provider, config=AgentConfig(max_iterations=2, screen_tool_output=True), ) - result = await agent.arun("Use both tools") + await agent.arun("Use both tools") tool_msgs = [ m for m in agent._history diff --git a/tests/agent/test_batch.py b/tests/agent/test_batch.py index 4647a7a4..cbaf5d12 100644 --- a/tests/agent/test_batch.py +++ b/tests/agent/test_batch.py @@ -7,15 +7,14 @@ from __future__ import annotations -from typing import Any, Dict, List, Optional, Tuple -from unittest.mock import MagicMock +from typing import Any, List, Tuple import pytest from selectools.agent.core import Agent, AgentConfig from selectools.providers.base import Provider, ProviderError from selectools.tools import tool -from selectools.types import AgentResult, Message, Role, ToolCall +from selectools.types import AgentResult, Message, Role from selectools.usage import UsageStats _DUMMY_USAGE = UsageStats(0, 0, 0, 0.0, "mock", "mock") @@ -183,6 +182,6 @@ def test_partial_failure_returns_all_results(self) -> None: assert len(results) == 3 contents = [r.content for r in results] - error_results = [c for c in contents if "error" in c.lower() or "Error" in c] + [c for c in contents if "error" in c.lower() or "Error" in c] success_results = [c for c in contents if "ok" in c.lower()] assert len(success_results) >= 1 diff --git a/tests/agent/test_parallel_tools.py b/tests/agent/test_parallel_tools.py index 72eae383..733e0dd9 100644 --- a/tests/agent/test_parallel_tools.py +++ b/tests/agent/test_parallel_tools.py @@ -309,7 +309,7 @@ async def test_partial_failure_async(self) -> None: provider=provider, config=AgentConfig(max_iterations=3, parallel_tool_execution=True), ) - result = await agent.arun([Message(role=Role.USER, content="go")]) + await agent.arun([Message(role=Role.USER, content="go")]) tool_results = [m for m in agent._history if m.role == Role.TOOL] assert len(tool_results) == 3 @@ -334,7 +334,7 @@ def test_unknown_tool_in_parallel_batch(self) -> None: provider=provider, config=AgentConfig(max_iterations=3, parallel_tool_execution=True), ) - result = agent.run([Message(role=Role.USER, content="go")]) + agent.run([Message(role=Role.USER, content="go")]) tool_results = [m for m in agent._history if m.role == Role.TOOL] assert len(tool_results) == 2 diff --git a/tests/agent/test_regression.py b/tests/agent/test_regression.py index 7a90d31d..66e02393 100644 --- a/tests/agent/test_regression.py +++ b/tests/agent/test_regression.py @@ -11,7 +11,6 @@ import asyncio import base64 -import copy import json import threading import time @@ -22,7 +21,7 @@ from selectools.agent.core import Agent, AgentConfig from selectools.observer import AgentObserver -from selectools.policy import PolicyDecision, ToolPolicy +from selectools.policy import ToolPolicy from selectools.providers.base import Provider, ProviderError from selectools.providers.fallback import FallbackProvider from selectools.providers.stubs import LocalProvider @@ -291,7 +290,7 @@ async def test_routing_only_fires_iteration_end_async(self) -> None: observers=[observer], ), ) - result = await agent.arun("route me") + await agent.arun("route me") assert len(observer.events.get("on_iteration_end", [])) == 1 @@ -1130,7 +1129,6 @@ def tool_b() -> str: # Second call returns no tool calls, ending the loop call_no = {"n": 0} - original_complete = provider.complete def complete_once(**kw): call_no["n"] += 1 @@ -1230,9 +1228,6 @@ class TestCoherenceCheckTraceStepType: def _make_coherence_provider(self, incoherent: bool): """Return a provider that fails coherence checks when incoherent=True.""" - from unittest.mock import patch - - from selectools.coherence import CoherenceResult class _CoherenceProvider(Provider): name = "coherence" @@ -1661,7 +1656,7 @@ def complete(self, **kwargs: Any) -> Tuple[Message, UsageStats]: "selectools.agent._memory_manager.estimate_run_tokens", return_value=high_fill, ): - result = agent.run("current user message") + agent.run("current user message") # The current user message must have been seen by the provider. assert any("current user message" in msg for msg in call_log), ( @@ -1755,7 +1750,7 @@ def complete(self, **kwargs: Any) -> Tuple[Message, UsageStats]: ) # Must complete within a reasonable timeout — not deadlock. - result = agent.run("run all tools") + agent.run("run all tools") assert call_count["n"] == 10, f"All 10 tool calls must execute, got {call_count['n']}" @@ -1887,7 +1882,6 @@ class _FailingGuardrail: """Guardrail that always raises so _prepare_run fails after prompt mutation.""" def check(self, text: str) -> Any: - from selectools.guardrails.base import GuardrailResult raise RuntimeError("guardrail boom") @@ -2968,7 +2962,7 @@ def test_bug15_summary_helper_caps_at_max_chars(): def test_bug15_summary_helper_empty_existing(): - from selectools.agent._memory_manager import _MAX_SUMMARY_CHARS, _append_summary + from selectools.agent._memory_manager import _append_summary assert _append_summary(None, "first summary") == "first summary" assert _append_summary("", "first summary") == "first summary" @@ -3175,7 +3169,6 @@ def worker(thread_id: int) -> None: def test_bug17_agent_trace_has_lock(): """Verify the lock attribute exists and is a threading.Lock.""" - import threading from selectools.trace import AgentTrace @@ -3383,7 +3376,6 @@ def test_bug16_build_cancelled_result_calls_extraction(): def test_bug22_optional_without_default_is_not_required(): - from typing import Optional from selectools.tools import tool as _bug22_tool @@ -3400,7 +3392,6 @@ def search(query: str, filter: Optional[str]) -> str: def test_bug22_optional_with_default_still_not_required(): """Regression guard: Optional[T] with a default value remains optional.""" - from typing import Optional from selectools.tools import tool as _bug22_tool @@ -3968,7 +3959,6 @@ def f(stuff: list) -> str: def test_bug29_optional_list_str_still_preserves_items(): """`Optional[list[str]]` must still emit `items: {type: string}`.""" - from typing import Optional from selectools.tools import tool diff --git a/tests/benchmarks/bench_overhead.py b/tests/benchmarks/bench_overhead.py index 2edbe166..13e96d80 100644 --- a/tests/benchmarks/bench_overhead.py +++ b/tests/benchmarks/bench_overhead.py @@ -17,7 +17,7 @@ from selectools import Agent, AgentConfig, AgentGraph, tool from selectools.orchestration.state import STATE_KEY_LAST_OUTPUT, GraphState -from selectools.pipeline import Pipeline, Step, parallel, step +from selectools.pipeline import Pipeline, Step, step from selectools.providers.stubs import LocalProvider diff --git a/tests/benchmarks/bench_vs_langchain.py b/tests/benchmarks/bench_vs_langchain.py index bb765892..d7667891 100644 --- a/tests/benchmarks/bench_vs_langchain.py +++ b/tests/benchmarks/bench_vs_langchain.py @@ -192,7 +192,7 @@ def lg_router(state): # Task 3: Pipeline composition (selectools only — no LCEL comparison) # ========================================================= - from selectools.pipeline import Pipeline, Step, step + from selectools.pipeline import step @step def upper(x: str) -> str: diff --git a/tests/core/test_framework.py b/tests/core/test_framework.py index 132c5c8a..c012fddf 100644 --- a/tests/core/test_framework.py +++ b/tests/core/test_framework.py @@ -11,7 +11,7 @@ import sys import types from pathlib import Path -from typing import Any, Callable, Coroutine, Dict, Generator, List, Optional +from typing import Any, Callable, Coroutine, Generator, List, Optional import pytest @@ -229,7 +229,7 @@ def test_conversation_memory_with_agent() -> None: assert memory.get_history()[1].role == Role.ASSISTANT # Second turn - memory should persist - response2 = agent.run([Message(role=Role.USER, content="Hi again")]) + agent.run([Message(role=Role.USER, content="Hi again")]) assert len(memory) == 4 # 2 previous + 2 new history = memory.get_history() assert history[0].content == "Hello" @@ -698,11 +698,11 @@ def simple_tool(x: int) -> str: agent = Agent(tools=[tool], provider=LocalProvider(), memory=memory) # First turn - response1 = await agent.arun([Message(role=Role.USER, content="Hello 1")]) + await agent.arun([Message(role=Role.USER, content="Hello 1")]) assert len(memory) >= 1 # Second turn - response2 = await agent.arun([Message(role=Role.USER, content="Hello 2")]) + await agent.arun([Message(role=Role.USER, content="Hello 2")]) assert len(memory) >= 2 diff --git a/tests/integration/test_advanced_chunking_e2e.py b/tests/integration/test_advanced_chunking_e2e.py index 158db281..7a40fa10 100644 --- a/tests/integration/test_advanced_chunking_e2e.py +++ b/tests/integration/test_advanced_chunking_e2e.py @@ -8,9 +8,7 @@ from __future__ import annotations import os -import tempfile from pathlib import Path -from typing import List import pytest @@ -19,7 +17,6 @@ from selectools.rag import Document, RecursiveTextSplitter, VectorStore from selectools.rag.chunking import ContextualChunker, SemanticChunker from selectools.tools import ToolLoader, tool -from selectools.tools.base import Tool from selectools.types import Message, Role OPENAI_KEY = os.getenv("OPENAI_API_KEY") diff --git a/tests/integration/test_context_propagation.py b/tests/integration/test_context_propagation.py index 99960b17..66e98018 100644 --- a/tests/integration/test_context_propagation.py +++ b/tests/integration/test_context_propagation.py @@ -108,7 +108,7 @@ async def acomplete(self, **kwargs: Any) -> Tuple[Message, UsageStats]: ) # 3. Execute agent - result = await agent.arun([Message(role=Role.USER, content="start")]) + await agent.arun([Message(role=Role.USER, content="start")]) # 4. Verify results in history # Check agent history directly diff --git a/tests/integration/test_streaming_integration.py b/tests/integration/test_streaming_integration.py index 9fc946bb..27047967 100644 --- a/tests/integration/test_streaming_integration.py +++ b/tests/integration/test_streaming_integration.py @@ -14,7 +14,7 @@ import asyncio from pathlib import Path -from typing import Any, AsyncGenerator, Generator +from typing import AsyncGenerator, Generator import pytest @@ -184,7 +184,7 @@ def test_streaming_with_memory_context(self) -> None: config = AgentConfig(max_iterations=2) agent = Agent(tools=[stream_numbers], provider=provider, config=config, memory=memory) - response = agent.run([Message(role=Role.USER, content="Stream some numbers")]) + agent.run([Message(role=Role.USER, content="Stream some numbers")]) # Memory should contain the interaction history = memory.get_history() @@ -263,7 +263,7 @@ def test_all_features_with_streaming(self) -> None: tools=[stream_numbers, get_info], provider=provider, config=config, memory=memory ) - response = agent.run([Message(role=Role.USER, content="Run both tools")]) + agent.run([Message(role=Role.USER, content="Run both tools")]) # Verify observer events assert "agent_start" in hook_events diff --git a/tests/integration/test_stress.py b/tests/integration/test_stress.py index e0a3c89e..030bed36 100644 --- a/tests/integration/test_stress.py +++ b/tests/integration/test_stress.py @@ -256,7 +256,7 @@ async def request_with_errors(request_id: int) -> Tuple[str, bool]: try: response = await agent.arun([Message(role=Role.USER, content=f"Request {request_id}")]) return "success", response.role == Role.ASSISTANT - except Exception as e: + except Exception: return "error", False start_time = time.time() diff --git a/tests/integration/test_v0_6_0_integration.py b/tests/integration/test_v0_6_0_integration.py index b45bff14..d33e5fea 100644 --- a/tests/integration/test_v0_6_0_integration.py +++ b/tests/integration/test_v0_6_0_integration.py @@ -12,8 +12,6 @@ from __future__ import annotations -from typing import Any - import pytest from selectools import Agent, AgentConfig, Message, Role, Tool, ToolParameter @@ -385,7 +383,7 @@ def test_analytics_reset_preserves_other_features(self, simple_tool: Tool) -> No # Verify analytics has data (may or may not depending on execution) analytics = agent.get_analytics() - initial_metrics_count = len(analytics.get_all_metrics()) + len(analytics.get_all_metrics()) # Reset analytics analytics.reset() diff --git a/tests/providers/test_azure_openai.py b/tests/providers/test_azure_openai.py index 1fef6fdb..b7c1eca0 100644 --- a/tests/providers/test_azure_openai.py +++ b/tests/providers/test_azure_openai.py @@ -7,7 +7,6 @@ from __future__ import annotations -import json import os from typing import Any from unittest.mock import AsyncMock, MagicMock, patch @@ -18,7 +17,6 @@ from selectools.providers.base import ProviderError from selectools.tools.base import Tool, ToolParameter from selectools.types import Message, Role, ToolCall -from selectools.usage import UsageStats # --------------------------------------------------------------------------- # Helpers @@ -146,7 +144,7 @@ def test_init_with_aad_token(self) -> None: ): from selectools.providers.azure_openai_provider import AzureOpenAIProvider - provider = AzureOpenAIProvider( + AzureOpenAIProvider( azure_endpoint=_ENDPOINT, azure_ad_token="my-aad-token", azure_deployment="gpt-4o", diff --git a/tests/providers/test_fallback_unit.py b/tests/providers/test_fallback_unit.py index b522c8f6..5d2b0965 100644 --- a/tests/providers/test_fallback_unit.py +++ b/tests/providers/test_fallback_unit.py @@ -9,7 +9,6 @@ import time from typing import Any, List, Optional, Tuple -from unittest.mock import MagicMock import pytest @@ -246,7 +245,6 @@ class _StreamingOkProvider: supports_async = True def __init__(self, chunks: Optional[List[Any]] = None): - from selectools.types import ToolCall self._chunks: List[Any] = chunks if chunks is not None else ["hello ", "world"] diff --git a/tests/providers/test_format_messages.py b/tests/providers/test_format_messages.py index a67a493a..c9e129eb 100644 --- a/tests/providers/test_format_messages.py +++ b/tests/providers/test_format_messages.py @@ -11,7 +11,7 @@ from __future__ import annotations import json -from typing import Any, Dict, List +from typing import Any from unittest.mock import MagicMock import pytest @@ -175,7 +175,7 @@ def _get_provider(self) -> Any: def test_tool_role_as_function_response(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -199,7 +199,7 @@ def test_tool_role_as_function_response(self) -> None: def test_assistant_with_function_call(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -227,7 +227,7 @@ def test_assistant_with_function_call(self) -> None: def test_user_with_image(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -240,7 +240,7 @@ def test_user_with_image(self) -> None: def test_tool_without_name_fallback(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -381,7 +381,7 @@ def _make_mock_response(self) -> Any: def test_complete_passes_timeout_to_config(self) -> None: """complete() must set http_options with timeout_ms when timeout is given.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -413,7 +413,7 @@ def test_complete_passes_timeout_to_config(self) -> None: def test_complete_no_timeout_does_not_set_http_options(self) -> None: """complete() must not set http_options when timeout=None.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -444,7 +444,7 @@ def test_complete_no_timeout_does_not_set_http_options(self) -> None: def test_stream_passes_timeout_to_config(self) -> None: """stream() must set http_options with timeout_ms when timeout is given.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -482,7 +482,7 @@ def test_stream_passes_timeout_to_config(self) -> None: def test_timeout_seconds_converted_to_milliseconds(self) -> None: """Timeout in seconds must be converted to milliseconds (SDK uses ms).""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") diff --git a/tests/providers/test_provider_coverage.py b/tests/providers/test_provider_coverage.py index a73a04c0..6e218beb 100644 --- a/tests/providers/test_provider_coverage.py +++ b/tests/providers/test_provider_coverage.py @@ -10,9 +10,7 @@ from __future__ import annotations -import asyncio -import json -from typing import Any, Dict, List +from typing import Any from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -20,7 +18,6 @@ from selectools.providers.base import ProviderError from selectools.tools.base import Tool, ToolParameter from selectools.types import Message, Role, ToolCall -from selectools.usage import UsageStats # --------------------------------------------------------------------------- # Helpers @@ -1783,7 +1780,7 @@ def _make_gemini_response( def test_complete_basic(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -1804,7 +1801,7 @@ def test_complete_basic(self) -> None: def test_complete_with_tool_calls(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -1833,7 +1830,7 @@ def test_complete_with_tool_calls(self) -> None: def test_complete_with_thought_signature_bytes(self) -> None: """thought_signature as bytes is base64-encoded.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -1878,7 +1875,7 @@ def test_complete_with_thought_signature_bytes(self) -> None: def test_complete_with_thought_signature_string(self) -> None: """thought_signature as string is converted with str().""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -1917,7 +1914,7 @@ def test_complete_with_thought_signature_string(self) -> None: def test_complete_text_value_error(self) -> None: """When response.text raises ValueError, content falls back to empty string.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -1943,7 +1940,7 @@ def test_complete_text_value_error(self) -> None: def test_complete_no_usage(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -1966,7 +1963,7 @@ def test_complete_no_usage(self) -> None: def test_complete_error(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -1981,7 +1978,7 @@ def test_complete_error(self) -> None: def test_complete_with_tools_in_config(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2005,7 +2002,7 @@ def test_complete_with_tools_in_config(self) -> None: def test_complete_function_call_no_args(self) -> None: """function_call with args=None gets empty dict.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2042,7 +2039,7 @@ def _get_provider(self) -> Any: def test_stream_text(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2070,7 +2067,7 @@ def test_stream_text(self) -> None: def test_stream_with_tool_call(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2110,7 +2107,7 @@ def test_stream_with_tool_call(self) -> None: def test_stream_with_thought_signature(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2148,7 +2145,7 @@ def test_stream_with_thought_signature(self) -> None: def test_stream_error_during_creation(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2165,7 +2162,7 @@ def test_stream_error_during_creation(self) -> None: def test_stream_error_mid_stream(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2191,7 +2188,7 @@ def exploding_iter(): def test_stream_provider_error_passthrough(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2214,7 +2211,7 @@ def exploding_iter(): def test_stream_function_call_no_args(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2271,7 +2268,7 @@ def _make_gemini_response(self, text: str = "hello", **kwargs: Any) -> MagicMock @pytest.mark.asyncio async def test_acomplete_basic(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2294,7 +2291,7 @@ async def test_acomplete_basic(self) -> None: @pytest.mark.asyncio async def test_acomplete_with_tool_calls(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2333,7 +2330,7 @@ async def test_acomplete_with_tool_calls(self) -> None: @pytest.mark.asyncio async def test_acomplete_text_value_error(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2360,7 +2357,7 @@ async def test_acomplete_text_value_error(self) -> None: @pytest.mark.asyncio async def test_acomplete_error(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2378,7 +2375,7 @@ async def test_acomplete_error(self) -> None: @pytest.mark.asyncio async def test_acomplete_no_usage(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2403,7 +2400,7 @@ async def test_acomplete_no_usage(self) -> None: @pytest.mark.asyncio async def test_acomplete_with_thought_signature_bytes(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2452,7 +2449,7 @@ def _get_provider(self) -> Any: @pytest.mark.asyncio async def test_astream_text(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2486,7 +2483,7 @@ async def mock_stream(): @pytest.mark.asyncio async def test_astream_with_tool_call(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2529,7 +2526,7 @@ async def mock_stream(): @pytest.mark.asyncio async def test_astream_with_thought_signature(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2571,7 +2568,7 @@ async def mock_stream(): @pytest.mark.asyncio async def test_astream_error_during_creation(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2590,7 +2587,7 @@ async def test_astream_error_during_creation(self) -> None: @pytest.mark.asyncio async def test_astream_error_mid_stream(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2617,7 +2614,7 @@ async def exploding_stream(): @pytest.mark.asyncio async def test_astream_provider_error_passthrough(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2641,7 +2638,7 @@ async def exploding_stream(): @pytest.mark.asyncio async def test_astream_function_call_no_args(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2682,7 +2679,7 @@ async def mock_stream(): async def test_astream_text_value_error(self) -> None: """When chunk.text raises ValueError during streaming, it's skipped.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2719,7 +2716,7 @@ def _get_provider(self) -> Any: def test_system_role_converted_to_user(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2732,7 +2729,7 @@ def test_system_role_converted_to_user(self) -> None: def test_tool_with_thought_signature_echo(self) -> None: """TOOL messages echo thought_signature from preceding ASSISTANT tool_calls.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2761,7 +2758,7 @@ def test_tool_with_thought_signature_echo(self) -> None: def test_unknown_role_falls_back_to_user(self) -> None: """Messages with an unrecognized role fall back to user.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2775,7 +2772,7 @@ def test_unknown_role_falls_back_to_user(self) -> None: def test_empty_parts_skipped(self) -> None: """Messages with no content produce no parts and are skipped.""" try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") @@ -2786,7 +2783,7 @@ def test_empty_parts_skipped(self) -> None: def test_map_tool_to_gemini(self) -> None: try: - from google.genai import types + from google.genai import types # noqa: F401 except ImportError: pytest.skip("google-genai not installed") diff --git a/tests/providers/test_provider_streaming_tools.py b/tests/providers/test_provider_streaming_tools.py index cb52bddf..7b8eeede 100644 --- a/tests/providers/test_provider_streaming_tools.py +++ b/tests/providers/test_provider_streaming_tools.py @@ -16,7 +16,6 @@ import json from typing import ( Any, - AsyncGenerator, AsyncIterable, Dict, Generator, @@ -845,12 +844,10 @@ def test_stream_skips_safety_filtered_chunk(self) -> None: provider._client.models.generate_content_stream.return_value = mock_stream provider.default_model = "gemini-test" - from google.genai import types # type: ignore[import] - provider._genai = MagicMock() # Build minimal config mock - config_mock = MagicMock() + MagicMock() with ( MagicMock() as _mock_types, ): diff --git a/tests/rag/test_advanced_chunking.py b/tests/rag/test_advanced_chunking.py index d1aa4365..eb8e622e 100644 --- a/tests/rag/test_advanced_chunking.py +++ b/tests/rag/test_advanced_chunking.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import List -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest diff --git a/tests/rag/test_faiss_store.py b/tests/rag/test_faiss_store.py index 29951e7d..6687e1d0 100644 --- a/tests/rag/test_faiss_store.py +++ b/tests/rag/test_faiss_store.py @@ -2,13 +2,12 @@ from __future__ import annotations -import json import os import sys import threading import types from typing import Any, List -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import numpy as np import pytest diff --git a/tests/rag/test_pgvector_store.py b/tests/rag/test_pgvector_store.py index 938740e6..47bef0b7 100644 --- a/tests/rag/test_pgvector_store.py +++ b/tests/rag/test_pgvector_store.py @@ -6,7 +6,7 @@ import sys import types from typing import Any, List -from unittest.mock import MagicMock, call, patch +from unittest.mock import MagicMock import pytest @@ -261,7 +261,6 @@ def test_add_rollback_on_error(self) -> None: store, conn = _make_store(dim=3, pre_initialized=True) # Make execute raise on the insert - original_execute = conn._cursor.execute call_count = [0] def failing_execute(sql: str, params: Any = None) -> None: @@ -308,7 +307,7 @@ def test_search_with_filter(self) -> None: ("doc_1", "matched", {"source": "pdf"}, 0.9), ] - results = store.search( + store.search( [0.1, 0.2, 0.3], top_k=5, filter={"source": "pdf"}, diff --git a/tests/rag/test_property_based_rag.py b/tests/rag/test_property_based_rag.py index d43ba04d..469b75e5 100644 --- a/tests/rag/test_property_based_rag.py +++ b/tests/rag/test_property_based_rag.py @@ -218,7 +218,6 @@ class TestVectorStoreFilterProperties: @settings(max_examples=150, deadline=None) def test_full_metadata_filter_always_matches(self, metadata) -> None: """A filter equal to the full metadata must match the document.""" - from selectools.rag.stores.memory import InMemoryVectorStore doc = Document(text="test", metadata=metadata) # Check filter inline (same logic as _matches_filter) diff --git a/tests/rag/test_qdrant_store.py b/tests/rag/test_qdrant_store.py index f9a57f0e..641da1b7 100644 --- a/tests/rag/test_qdrant_store.py +++ b/tests/rag/test_qdrant_store.py @@ -7,7 +7,7 @@ from __future__ import annotations import sys -from typing import Any, Dict, List +from typing import Any, List from unittest.mock import MagicMock, Mock, patch import pytest @@ -237,7 +237,7 @@ def test_add_documents_creates_collection( # Collection should have been created qdrant_store.client.create_collection.assert_called_once() - call_kwargs = ( + ( qdrant_store.client.create_collection.call_kwargs if hasattr(qdrant_store.client.create_collection, "call_kwargs") else qdrant_store.client.create_collection.call_args diff --git a/tests/rag/test_rag_basic.py b/tests/rag/test_rag_basic.py index bf96922e..c2138bc8 100644 --- a/tests/rag/test_rag_basic.py +++ b/tests/rag/test_rag_basic.py @@ -11,7 +11,7 @@ import pytest try: - import numpy + import numpy # noqa: F401 NUMPY_AVAILABLE = True except ImportError: diff --git a/tests/rag/test_rag_regression_pass1.py b/tests/rag/test_rag_regression_pass1.py index 691dd315..e118b3cf 100644 --- a/tests/rag/test_rag_regression_pass1.py +++ b/tests/rag/test_rag_regression_pass1.py @@ -9,15 +9,13 @@ from __future__ import annotations import json -import os import sys -import tempfile from typing import Any, List from unittest.mock import MagicMock, Mock, patch import pytest -from selectools.rag.vector_store import Document, SearchResult, VectorStore +from selectools.rag.vector_store import VectorStore # ============================================================================ # Fixtures diff --git a/tests/rag/test_rag_regression_phase3.py b/tests/rag/test_rag_regression_phase3.py index 1d2c430d..7db5c25e 100644 --- a/tests/rag/test_rag_regression_phase3.py +++ b/tests/rag/test_rag_regression_phase3.py @@ -9,7 +9,6 @@ from __future__ import annotations import threading -import time from typing import List from unittest.mock import MagicMock, Mock, patch @@ -382,7 +381,6 @@ def test_provider_exception_produces_empty_context_not_crash(self): def test_partial_provider_failure_continues(self): """Provider failure on chunk 1 must not prevent chunk 2 from being processed.""" from selectools.rag.chunking import ContextualChunker, TextSplitter - from selectools.types import Message, Role base = TextSplitter(chunk_size=50, chunk_overlap=0) call_count = [0] diff --git a/tests/rag/test_reranker.py b/tests/rag/test_reranker.py index 5a6e0202..621cc83d 100644 --- a/tests/rag/test_reranker.py +++ b/tests/rag/test_reranker.py @@ -13,7 +13,7 @@ import pytest try: - import numpy + import numpy # noqa: F401 NUMPY_AVAILABLE = True except ImportError: @@ -419,7 +419,7 @@ def test_reranker_changes_ordering(self, documents: List[Document]) -> None: searcher_no_rerank = HybridSearcher(vector_store=store) searcher_no_rerank.add_documents(documents) - results_original = searcher_no_rerank.search("Python programming", top_k=5) + searcher_no_rerank.search("Python programming", top_k=5) store2 = InMemoryVectorStore(MockEmbedder()) reranker = MockReranker(reverse=True) diff --git a/tests/rag/test_sqlite_integration.py b/tests/rag/test_sqlite_integration.py index 95f52104..969c9dfd 100644 --- a/tests/rag/test_sqlite_integration.py +++ b/tests/rag/test_sqlite_integration.py @@ -107,7 +107,7 @@ def test_basic_persistence( """Test basic persistence after reconnection.""" # Add documents and close store1 = SQLiteVectorStore(embedder=mock_embedder, db_path=temp_db_path) - doc_ids = store1.add_documents(sample_documents) + store1.add_documents(sample_documents) del store1 # Reopen and verify @@ -209,7 +209,7 @@ def test_database_file_creation(self, mock_embedder: Mock, temp_db_path: str) -> """Test that database file is created.""" assert not os.path.exists(temp_db_path) - store = SQLiteVectorStore(embedder=mock_embedder, db_path=temp_db_path) + SQLiteVectorStore(embedder=mock_embedder, db_path=temp_db_path) assert os.path.exists(temp_db_path) assert os.path.isfile(temp_db_path) @@ -259,7 +259,7 @@ def test_upsert_behavior(self, mock_embedder: Mock, temp_db_path: str) -> None: # Delete and re-add with new content store.delete(doc_ids) doc2 = Document(text="updated text", metadata={"version": 2}) - new_ids = store.add_documents([doc2]) + store.add_documents([doc2]) # Search and verify the new document is there query_embedding = mock_embedder.embed_query("updated") diff --git a/tests/rag/test_vector_stores_crud.py b/tests/rag/test_vector_stores_crud.py index 1c114c3a..9186f5e9 100644 --- a/tests/rag/test_vector_stores_crud.py +++ b/tests/rag/test_vector_stores_crud.py @@ -304,7 +304,7 @@ def test_persistence(self, mock_embedder: Mock, sample_documents: list[Document] try: # Add documents and close store1 = SQLiteVectorStore(embedder=mock_embedder, db_path=db_path) - doc_ids = store1.add_documents(sample_documents) + store1.add_documents(sample_documents) del store1 # Reopen and verify documents exist diff --git a/tests/simulations/sim_agent_memory_pressure.py b/tests/simulations/sim_agent_memory_pressure.py index c5f823c4..416e1dc5 100644 --- a/tests/simulations/sim_agent_memory_pressure.py +++ b/tests/simulations/sim_agent_memory_pressure.py @@ -17,7 +17,6 @@ import pytest from selectools.memory import ConversationMemory -from selectools.providers.stubs import LocalProvider from selectools.types import Message, Role diff --git a/tests/simulations/sim_hybrid_search_load.py b/tests/simulations/sim_hybrid_search_load.py index 776043e7..fe8226e4 100644 --- a/tests/simulations/sim_hybrid_search_load.py +++ b/tests/simulations/sim_hybrid_search_load.py @@ -16,7 +16,6 @@ import threading from typing import List -from unittest.mock import Mock import pytest diff --git a/tests/simulations/sim_parallel_analysis.py b/tests/simulations/sim_parallel_analysis.py index ec422cd2..659ecdde 100644 --- a/tests/simulations/sim_parallel_analysis.py +++ b/tests/simulations/sim_parallel_analysis.py @@ -21,7 +21,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "src")) from selectools import Agent, AgentConfig, AgentGraph, tool -from selectools.orchestration.state import STATE_KEY_LAST_OUTPUT, GraphState, MergePolicy +from selectools.orchestration.state import MergePolicy from selectools.providers.openai_provider import OpenAIProvider # --- Tools --- diff --git a/tests/simulations/sim_provider_failover.py b/tests/simulations/sim_provider_failover.py index c0cb5fcd..2d419f44 100644 --- a/tests/simulations/sim_provider_failover.py +++ b/tests/simulations/sim_provider_failover.py @@ -14,8 +14,7 @@ from __future__ import annotations -from typing import Any, Dict, List, Optional -from unittest.mock import Mock +from typing import List import pytest diff --git a/tests/simulations/sim_rag_concurrent.py b/tests/simulations/sim_rag_concurrent.py index fbfdcd04..97846d95 100644 --- a/tests/simulations/sim_rag_concurrent.py +++ b/tests/simulations/sim_rag_concurrent.py @@ -12,7 +12,6 @@ import threading from typing import List -from unittest.mock import Mock import pytest diff --git a/tests/simulations/sim_tool_errors.py b/tests/simulations/sim_tool_errors.py index 91caa2e7..7fd46e64 100644 --- a/tests/simulations/sim_tool_errors.py +++ b/tests/simulations/sim_tool_errors.py @@ -12,14 +12,11 @@ from __future__ import annotations -import random from typing import List import pytest -from selectools.providers.stubs import LocalProvider from selectools.tools import tool -from selectools.trace import StepType # --------------------------------------------------------------------------- # Tool definitions diff --git a/tests/simulations/sim_yaml_serve.py b/tests/simulations/sim_yaml_serve.py index 7d032c1d..bc76651d 100644 --- a/tests/simulations/sim_yaml_serve.py +++ b/tests/simulations/sim_yaml_serve.py @@ -14,10 +14,10 @@ from selectools import AgentConfig, tool from selectools.compose import compose from selectools.observe import InMemoryTraceStore -from selectools.pipeline import Pipeline, Step, cache_step, parallel, retry, step +from selectools.pipeline import cache_step, step from selectools.providers.stubs import LocalProvider from selectools.serve.app import AgentRouter -from selectools.templates import from_dict, from_yaml, list_templates, load_template +from selectools.templates import from_yaml, list_templates, load_template from selectools.trace import AgentTrace, StepType, TraceStep diff --git a/tests/test_bug_hunt_batch1_core.py b/tests/test_bug_hunt_batch1_core.py index b80f1822..5cc37590 100644 --- a/tests/test_bug_hunt_batch1_core.py +++ b/tests/test_bug_hunt_batch1_core.py @@ -1,12 +1,9 @@ """Regression tests for bug hunt batch 1 — agent core and provider fixes.""" -import inspect - import pytest from selectools.agent.config import AgentConfig from selectools.agent.core import Agent -from selectools.observer import AgentObserver from selectools.tools.base import Tool from selectools.trace import StepType from selectools.types import Message, Role, ToolCall diff --git a/tests/test_bug_hunt_batch1_security.py b/tests/test_bug_hunt_batch1_security.py index 38a1caf7..0c211907 100644 --- a/tests/test_bug_hunt_batch1_security.py +++ b/tests/test_bug_hunt_batch1_security.py @@ -1,8 +1,5 @@ """Regression tests for bug hunt batch 1 — security and memory fixes.""" -import os -import tempfile - import pytest from selectools.knowledge import FileKnowledgeStore, KnowledgeEntry diff --git a/tests/test_bug_hunt_batch1_tools.py b/tests/test_bug_hunt_batch1_tools.py index f25d749c..8023f2e6 100644 --- a/tests/test_bug_hunt_batch1_tools.py +++ b/tests/test_bug_hunt_batch1_tools.py @@ -1,14 +1,10 @@ """Regression tests for bug hunt batch 1 — tools, RAG, evals fixes.""" -import asyncio -import json -import re - import pytest from selectools.evals.evaluators import JsonValidityEvaluator, OutputEvaluator from selectools.evals.types import CaseResult, TestCase -from selectools.tools.base import Tool, ToolParameter +from selectools.tools.base import Tool class TestAsyncToolSync: diff --git a/tests/test_bug_hunt_regression.py b/tests/test_bug_hunt_regression.py index 4344a246..41650ed4 100644 --- a/tests/test_bug_hunt_regression.py +++ b/tests/test_bug_hunt_regression.py @@ -6,11 +6,7 @@ from __future__ import annotations -import json import os -import re -import tempfile -from dataclasses import dataclass from datetime import datetime, timedelta, timezone from unittest.mock import MagicMock @@ -18,15 +14,10 @@ from selectools.agent.config import AgentConfig from selectools.agent.core import Agent -from selectools.cancellation import CancellationToken -from selectools.knowledge import FileKnowledgeStore, KnowledgeEntry, KnowledgeMemory +from selectools.knowledge import FileKnowledgeStore, KnowledgeEntry from selectools.memory import ConversationMemory -from selectools.observer import AgentObserver -from selectools.policy import ToolPolicy from selectools.sessions import JsonFileSessionStore from selectools.tools.base import Tool, ToolParameter -from selectools.tools.decorators import tool -from selectools.trace import StepType from selectools.types import Message, Role, ToolCall from selectools.usage import UsageStats diff --git a/tests/test_checkpoint_postgres.py b/tests/test_checkpoint_postgres.py index b5479912..33e34e3f 100644 --- a/tests/test_checkpoint_postgres.py +++ b/tests/test_checkpoint_postgres.py @@ -4,10 +4,9 @@ import json import sys -import threading from datetime import datetime, timezone from types import ModuleType -from unittest.mock import MagicMock, call, patch +from unittest.mock import MagicMock, patch import pytest @@ -80,7 +79,7 @@ class TestPostgresCheckpointStoreInit: def test_creates_table_on_init(self): fake_pg, mock_conn, mock_cursor = _make_fake_psycopg2() - store = _make_store(fake_pg) + _make_store(fake_pg) # _init_table should have been called, executing CREATE TABLE and CREATE INDEX assert mock_cursor.execute.call_count >= 2 sql_calls = [str(c) for c in mock_cursor.execute.call_args_list] @@ -110,7 +109,7 @@ def test_custom_table_name(self): fake_pg, mock_conn, mock_cursor = _make_fake_psycopg2() cls = _import_store(fake_pg) with patch.dict(sys.modules, {"psycopg2": fake_pg}): - store = cls(dsn="postgresql://x@y/z", table="custom_cp") + cls(dsn="postgresql://x@y/z", table="custom_cp") sql_calls = [str(c) for c in mock_cursor.execute.call_args_list] assert any("custom_cp" in s for s in sql_calls) diff --git a/tests/test_coherence.py b/tests/test_coherence.py index 38206ffa..9689fbbe 100644 --- a/tests/test_coherence.py +++ b/tests/test_coherence.py @@ -2,8 +2,7 @@ from __future__ import annotations -from typing import Any, Dict, List, Optional, Tuple -from unittest.mock import MagicMock +from typing import Any, Tuple import pytest diff --git a/tests/test_concurrency_smoke.py b/tests/test_concurrency_smoke.py index f50a008a..fc4576e8 100644 --- a/tests/test_concurrency_smoke.py +++ b/tests/test_concurrency_smoke.py @@ -16,12 +16,9 @@ from __future__ import annotations import threading -import time -from typing import Any, List +from typing import List from unittest.mock import Mock -import pytest - from selectools.rag.vector_store import Document # ============================================================================ diff --git a/tests/test_consolidation_regression.py b/tests/test_consolidation_regression.py index 0b931347..a7ee5ee0 100644 --- a/tests/test_consolidation_regression.py +++ b/tests/test_consolidation_regression.py @@ -93,7 +93,7 @@ async def test_arun_records_tool_usage_like_run(self) -> None: memory=ConversationMemory(max_messages=50), config=AgentConfig(max_iterations=3), ) - result = await agent.arun("Test tool usage") + await agent.arun("Test tool usage") assert "echo" in agent.usage.tool_usage assert agent.usage.tool_usage["echo"] >= 1 @@ -312,7 +312,7 @@ class TestSQLiteTripleStoreWAL: def test_wal_mode_enabled(self, tmp_path: "os.PathLike[str]") -> None: """SQLiteTripleStore should use WAL journal mode.""" db = os.path.join(str(tmp_path), "triples.db") - store = SQLiteTripleStore(db_path=db) + SQLiteTripleStore(db_path=db) conn = sqlite3.connect(db) mode = conn.execute("PRAGMA journal_mode").fetchone()[0] diff --git a/tests/test_coverage_orchestration.py b/tests/test_coverage_orchestration.py index 412cd6c6..52a21cf3 100644 --- a/tests/test_coverage_orchestration.py +++ b/tests/test_coverage_orchestration.py @@ -11,8 +11,7 @@ from __future__ import annotations -import asyncio -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest @@ -21,30 +20,24 @@ from selectools.orchestration.graph import ( AgentGraph, ErrorPolicy, - GraphResult, _make_synthetic_result, _merge_usage, _state_hash, ) -from selectools.orchestration.node import GraphNode, ParallelGroupNode from selectools.orchestration.state import ( STATE_KEY_LAST_OUTPUT, ContextMode, - GraphEvent, GraphEventType, GraphState, InterruptRequest, - MergePolicy, Scatter, - _Goto, - _Update, goto, update, ) from selectools.patterns.plan_and_execute import PlanAndExecuteAgent, PlanStep from selectools.patterns.team_lead import Subtask, TeamLeadAgent, TeamLeadResult from selectools.trace import AgentTrace -from selectools.types import AgentResult, Message, Role +from selectools.types import Message, Role from selectools.usage import UsageStats # --------------------------------------------------------------------------- @@ -1317,7 +1310,7 @@ async def test_sequential_context_forwarding(self): team={"first": first, "second": second}, delegation_strategy="sequential", ) - result = await agent.arun("multi-step task") + await agent.arun("multi-step task") # Second agent should receive context from first second_call = second.arun.call_args[0][0] @@ -1350,7 +1343,7 @@ async def test_sequential_cancellation(self): delegation_strategy="sequential", cancellation_token=token, ) - result = await agent.arun("task") + await agent.arun("task") # Worker should not have been called due to cancellation worker.arun.assert_not_called() @@ -1534,7 +1527,7 @@ async def test_cancellation_stops_execution(self): executors={"writer": writer}, cancellation_token=token, ) - result = await agent.arun("task") + await agent.arun("task") # Writer should not have been called writer.arun.assert_not_called() @@ -1561,7 +1554,7 @@ async def test_context_from_prior_steps(self): planner=planner, executors={"step1": step1, "step2": step2}, ) - result = await agent.arun("multi-step task") + await agent.arun("multi-step task") # step2 should receive context including step1's output step2_call = step2.arun.call_args[0][0] @@ -1585,7 +1578,7 @@ async def test_unknown_executor_skipped_midplan(self): planner=planner, executors={"real": real}, ) - result = await agent.arun("task") + await agent.arun("task") # real should be called twice (first and third steps) assert real.arun.call_count == 2 diff --git a/tests/test_document_loaders_extended.py b/tests/test_document_loaders_extended.py index 882206cd..a37e3c12 100644 --- a/tests/test_document_loaders_extended.py +++ b/tests/test_document_loaders_extended.py @@ -3,9 +3,7 @@ from __future__ import annotations import json -import textwrap import urllib.error -from io import BytesIO from pathlib import Path from typing import Any from unittest.mock import MagicMock, patch @@ -13,7 +11,6 @@ import pytest from selectools.rag.loaders import DocumentLoader -from selectools.rag.vector_store import Document # --------------------------------------------------------------------------- # from_csv diff --git a/tests/test_e2e_multimodal.py b/tests/test_e2e_multimodal.py index ac2becfa..5d5f46e9 100644 --- a/tests/test_e2e_multimodal.py +++ b/tests/test_e2e_multimodal.py @@ -29,7 +29,6 @@ import os import struct import zlib -from pathlib import Path import pytest diff --git a/tests/test_entity_memory.py b/tests/test_entity_memory.py index d5d061d4..69830e3d 100644 --- a/tests/test_entity_memory.py +++ b/tests/test_entity_memory.py @@ -12,9 +12,7 @@ from __future__ import annotations import json -from typing import Any, Dict, List, Optional - -import pytest +from typing import Any, Dict, List from selectools.entity_memory import Entity, EntityMemory from selectools.types import Message, Role diff --git a/tests/test_evals.py b/tests/test_evals.py index 5be3de5b..09aa9ff4 100644 --- a/tests/test_evals.py +++ b/tests/test_evals.py @@ -3,9 +3,6 @@ from __future__ import annotations import json -import os -import tempfile -from dataclasses import dataclass from typing import Any, Dict, List, Optional from unittest.mock import MagicMock @@ -29,7 +26,6 @@ OutputEvaluator, PerformanceEvaluator, PIILeakEvaluator, - RegressionResult, StartsWithEvaluator, StructuredOutputEvaluator, TestCase, diff --git a/tests/test_evals_advanced.py b/tests/test_evals_advanced.py index e4520c09..8920f184 100644 --- a/tests/test_evals_advanced.py +++ b/tests/test_evals_advanced.py @@ -3,12 +3,10 @@ from __future__ import annotations import json -from typing import Any, Dict, List, Optional +from typing import Any, List, Optional from unittest.mock import MagicMock -import pytest - -from selectools.evals import CaseResult, CaseVerdict, EvalMetadata, EvalReport, EvalSuite, TestCase +from selectools.evals import CaseResult, CaseVerdict, EvalMetadata, EvalReport, TestCase from selectools.evals.badge import generate_badge, generate_detailed_badge from selectools.evals.generator import _parse_generated_cases, generate_cases from selectools.evals.pairwise import PairwiseCaseResult, PairwiseEval, PairwiseReport diff --git a/tests/test_evals_cli.py b/tests/test_evals_cli.py index 3942cad6..eefee5a3 100644 --- a/tests/test_evals_cli.py +++ b/tests/test_evals_cli.py @@ -2,8 +2,6 @@ from __future__ import annotations -import sys -from io import StringIO from unittest.mock import MagicMock, patch import pytest @@ -118,7 +116,7 @@ def test_local_provider(self, mock_agent_cls): @patch("selectools.Agent") def test_local_provider_with_model(self, mock_agent_cls): mock_agent_cls.return_value = MagicMock() - agent = _create_agent("local", "custom-local") + _create_agent("local", "custom-local") call_kwargs = mock_agent_cls.call_args assert call_kwargs.kwargs["config"].model == "custom-local" @@ -132,7 +130,7 @@ def test_openai_provider(self, mock_agent_cls): mock_agent_cls.return_value = MagicMock() with patch("selectools.providers.OpenAIProvider") as mock_prov: mock_prov.return_value = MagicMock() - agent = _create_agent("openai", None) + _create_agent("openai", None) mock_prov.assert_called_once() @patch("selectools.Agent") @@ -140,7 +138,7 @@ def test_anthropic_provider(self, mock_agent_cls): mock_agent_cls.return_value = MagicMock() with patch("selectools.providers.AnthropicProvider") as mock_prov: mock_prov.return_value = MagicMock() - agent = _create_agent("anthropic", None) + _create_agent("anthropic", None) mock_prov.assert_called_once() @patch("selectools.Agent") @@ -148,7 +146,7 @@ def test_gemini_provider(self, mock_agent_cls): mock_agent_cls.return_value = MagicMock() with patch("selectools.providers.GeminiProvider") as mock_prov: mock_prov.return_value = MagicMock() - agent = _create_agent("gemini", None) + _create_agent("gemini", None) mock_prov.assert_called_once() @patch("selectools.Agent") @@ -156,7 +154,7 @@ def test_ollama_provider(self, mock_agent_cls): mock_agent_cls.return_value = MagicMock() with patch("selectools.providers.OllamaProvider") as mock_prov: mock_prov.return_value = MagicMock() - agent = _create_agent("ollama", None) + _create_agent("ollama", None) mock_prov.assert_called_once() @patch("selectools.Agent") diff --git a/tests/test_evals_e2e.py b/tests/test_evals_e2e.py index 130f4673..41040af1 100644 --- a/tests/test_evals_e2e.py +++ b/tests/test_evals_e2e.py @@ -6,19 +6,16 @@ from __future__ import annotations -import asyncio import json import xml.etree.ElementTree as ET from pathlib import Path -from typing import Any, List +from typing import Any import pytest from selectools import Agent, AgentConfig, tool from selectools.evals import ( BaselineStore, - CaseResult, - CaseVerdict, DatasetLoader, EvalReport, EvalSuite, @@ -28,10 +25,8 @@ generate_badge, generate_cases, generate_detailed_badge, - serve_eval, ) -from selectools.evals.html import _donut_svg, _histogram_svg, render_html_report -from selectools.evals.junit import render_junit_xml +from selectools.evals.html import _donut_svg, _histogram_svg from selectools.evals.llm_evaluators import ( BiasEvaluator, CoherenceEvaluator, @@ -44,10 +39,7 @@ SummaryEvaluator, ToxicityEvaluator, ) -from selectools.evals.pairwise import PairwiseReport -from selectools.evals.snapshot import SnapshotDiff, SnapshotResult -from selectools.types import Message, Role, ToolCall -from selectools.usage import UsageStats +from selectools.types import ToolCall # Import shared test providers from conftest from tests.conftest import SharedFakeProvider, SharedToolCallProvider diff --git a/tests/test_evals_final.py b/tests/test_evals_final.py index 03cb795e..a2550183 100644 --- a/tests/test_evals_final.py +++ b/tests/test_evals_final.py @@ -3,7 +3,7 @@ from __future__ import annotations import json -from typing import Any, List, Optional +from typing import Any from unittest.mock import MagicMock import pytest diff --git a/tests/test_evals_hardening.py b/tests/test_evals_hardening.py index 8aee03ac..336244dc 100644 --- a/tests/test_evals_hardening.py +++ b/tests/test_evals_hardening.py @@ -10,7 +10,6 @@ from __future__ import annotations import json -import os from pathlib import Path from typing import Any from unittest.mock import MagicMock @@ -21,18 +20,13 @@ from selectools.evals import ( BaselineStore, CaseVerdict, - DatasetLoader, EvalSuite, HistoryStore, PairwiseEval, SnapshotStore, TestCase, generate_badge, - generate_detailed_badge, ) -from selectools.evals.evaluators import DEFAULT_EVALUATORS -from selectools.evals.history import HistoryEntry, HistoryTrend -from selectools.evals.html import _donut_svg, _histogram_svg, _trend_svg from selectools.evals.llm_evaluators import ( CorrectnessEvaluator, InstructionFollowingEvaluator, @@ -335,7 +329,6 @@ def test_badge_from_full_run(self, tmp_path: Path) -> None: def test_html_report_with_all_verdicts(self, tmp_path: Path) -> None: """HTML report handles pass, fail, and error in the same report.""" - from tests.conftest import SharedErrorProvider agent_good = _fake_agent(["good"]) r1 = EvalSuite( @@ -756,7 +749,6 @@ class TestBaselineStorePathTraversal: def test_save_strips_directory_traversal(self, tmp_path: Path) -> None: """A suite name with '../' components must not escape the baseline dir.""" - import json from selectools.evals import EvalReport from selectools.evals.regression import BaselineStore diff --git a/tests/test_evals_html_report.py b/tests/test_evals_html_report.py index f3ffa025..f26755d2 100644 --- a/tests/test_evals_html_report.py +++ b/tests/test_evals_html_report.py @@ -2,12 +2,6 @@ from __future__ import annotations -import os -import tempfile -from pathlib import Path - -import pytest - from selectools.evals.html import _donut_svg, _histogram_svg, _trend_svg, render_html_report from selectools.evals.report import EvalReport from selectools.evals.types import CaseResult, CaseVerdict, EvalFailure, EvalMetadata, TestCase diff --git a/tests/test_evals_new_evaluators.py b/tests/test_evals_new_evaluators.py index 46b87e73..16a4f2d9 100644 --- a/tests/test_evals_new_evaluators.py +++ b/tests/test_evals_new_evaluators.py @@ -2,11 +2,9 @@ from __future__ import annotations -from typing import Any, Dict, List, Optional +from typing import Any from unittest.mock import MagicMock -import pytest - from selectools.evals import ( ConcisenessEvaluator, ContextPrecisionEvaluator, @@ -26,7 +24,7 @@ URLValidityEvaluator, WordCountEvaluator, ) -from selectools.evals.types import CaseResult, CaseVerdict, EvalFailure +from selectools.evals.types import CaseResult, CaseVerdict # --------------------------------------------------------------------------- # Helpers diff --git a/tests/test_evals_ralph_bugs.py b/tests/test_evals_ralph_bugs.py index 31a4effa..da4f1c5d 100644 --- a/tests/test_evals_ralph_bugs.py +++ b/tests/test_evals_ralph_bugs.py @@ -2,15 +2,10 @@ from __future__ import annotations -import json -import tempfile -from dataclasses import dataclass from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import Any, List, Optional from unittest.mock import MagicMock -import pytest - from selectools.evals.badge import generate_badge, generate_detailed_badge from selectools.evals.dataset import DatasetLoader from selectools.evals.llm_evaluators import _extract_score, _strip_fenced_content @@ -232,7 +227,7 @@ def check(self, case, case_result): case = TestCase(input="test") agent_result = _make_agent_result(content="response") - case_result = CaseResult( + CaseResult( case=case, verdict=CaseVerdict.PASS, agent_result=agent_result, diff --git a/tests/test_evals_release.py b/tests/test_evals_release.py index a0a0f3c5..0ef4f443 100644 --- a/tests/test_evals_release.py +++ b/tests/test_evals_release.py @@ -2,11 +2,9 @@ from __future__ import annotations -from typing import Any, List +from typing import Any from unittest.mock import MagicMock -import pytest - from selectools import Agent, AgentConfig, tool from selectools.evals import ( CaseResult, @@ -14,7 +12,6 @@ EvalMetadata, EvalReport, EvalSuite, - HistoryStore, HistoryTrend, TestCase, ) diff --git a/tests/test_evals_serve.py b/tests/test_evals_serve.py index 443c66d8..1828483c 100644 --- a/tests/test_evals_serve.py +++ b/tests/test_evals_serve.py @@ -4,13 +4,8 @@ import io import json -import threading -import time -from http.server import HTTPServer from unittest.mock import MagicMock, patch -import pytest - from selectools.evals.serve import _DASHBOARD_HTML, _DashboardHandler, serve_eval # --------------------------------------------------------------------------- diff --git a/tests/test_evals_v017_features.py b/tests/test_evals_v017_features.py index 934022f5..1e093abb 100644 --- a/tests/test_evals_v017_features.py +++ b/tests/test_evals_v017_features.py @@ -24,12 +24,11 @@ import pytest -from selectools import Agent, AgentConfig, AgentResult, Message, Role, tool +from selectools import Agent, AgentConfig, Message, Role, tool from selectools.cache_semantic import SemanticCache, _cosine_similarity from selectools.evals import EvalSuite, TestCase from selectools.evals.evaluators import ContainsEvaluator, CustomEvaluator from selectools.evals.report import EvalReport -from selectools.evals.types import CaseResult, CaseVerdict, EvalMetadata from selectools.memory import ConversationMemory from selectools.sessions import JsonFileSessionStore, SQLiteSessionStore from selectools.token_estimation import TokenEstimate diff --git a/tests/test_evals_v0191.py b/tests/test_evals_v0191.py index 7564f52b..f2fa6d35 100644 --- a/tests/test_evals_v0191.py +++ b/tests/test_evals_v0191.py @@ -24,7 +24,7 @@ FactConsistencyEvaluator, StepReasoningEvaluator, ) -from selectools.evals.types import CaseResult, CaseVerdict, EvalFailure, TestCase +from selectools.evals.types import CaseResult, CaseVerdict, TestCase # --------------------------------------------------------------------------- # Test helpers @@ -583,7 +583,6 @@ def test_uses_default_rubric_when_case_rubric_none(self): case = _make_case(rubric=None) result = _make_result("Step-by-step analysis here.") ev.check(case, result) - call_args = provider.complete.call_args # The system prompt is in the call — verify it was called provider.complete.assert_called_once() diff --git a/tests/test_features_in_graph.py b/tests/test_features_in_graph.py index 471a8e1b..2cd63d1e 100644 --- a/tests/test_features_in_graph.py +++ b/tests/test_features_in_graph.py @@ -7,11 +7,7 @@ from __future__ import annotations -import asyncio -import threading -import time from typing import Any, Dict, List -from unittest.mock import MagicMock import pytest @@ -24,14 +20,13 @@ STATE_KEY_LAST_OUTPUT, GraphState, InterruptRequest, - MergePolicy, ) -from selectools.pipeline import Pipeline, Step, parallel, step -from selectools.policy import PolicyDecision, ToolPolicy +from selectools.pipeline import Pipeline, parallel, step +from selectools.policy import ToolPolicy from selectools.providers.base import Provider from selectools.tools.base import Tool from selectools.trace import StepType -from selectools.types import AgentResult, Message, Role, ToolCall +from selectools.types import Message, Role, ToolCall from selectools.usage import UsageStats # --------------------------------------------------------------------------- @@ -448,7 +443,7 @@ def test_react_strategy_in_graph_node(self): agent = _make_agent(provider, reasoning_strategy="react") graph = AgentGraph.chain(agent) - result = graph.run("Think step by step") + graph.run("Think step by step") # Verify the system prompt was modified to include ReAct instructions assert len(provider.calls) > 0 @@ -461,7 +456,7 @@ def test_cot_strategy_in_graph_node(self): agent = _make_agent(provider, reasoning_strategy="cot") graph = AgentGraph.chain(agent) - result = graph.run("Explain") + graph.run("Explain") system = provider.calls[0]["system_prompt"] assert "step" in system.lower() or "chain" in system.lower() or "think" in system.lower() @@ -482,8 +477,8 @@ def test_cache_works_across_graph_runs(self): agent = _make_agent(provider, cache=cache) graph = AgentGraph.chain(agent) - r1 = graph.run("same question") - r2 = graph.run("same question") + graph.run("same question") + graph.run("same question") # Second run should hit cache — fewer provider calls assert cache.stats.hits >= 1 or len(provider.calls) <= 2 diff --git a/tests/test_final_coverage_a.py b/tests/test_final_coverage_a.py index 4666a749..1602d79c 100644 --- a/tests/test_final_coverage_a.py +++ b/tests/test_final_coverage_a.py @@ -10,8 +10,7 @@ import sys import tempfile import time -import types -from dataclasses import dataclass +import types # noqa: F401 from pathlib import Path from typing import Any, Dict, List, Optional from unittest.mock import MagicMock, patch @@ -340,7 +339,6 @@ def test_unwrap_pipe_union_syntax(self): from selectools.tools.decorators import _unwrap_type # Construct str | None without eval - union_type = types.UnionType # type: ignore[attr-defined] # The standard way to get str | None at runtime on 3.10+ str_or_none = str | None # type: ignore[operator] result = _unwrap_type(str_or_none) diff --git a/tests/test_final_coverage_b.py b/tests/test_final_coverage_b.py index e8ed86cc..258bf44e 100644 --- a/tests/test_final_coverage_b.py +++ b/tests/test_final_coverage_b.py @@ -17,21 +17,19 @@ import asyncio import json import time -from dataclasses import dataclass, field from typing import Any, Dict, List, Optional -from unittest.mock import AsyncMock, MagicMock, PropertyMock, patch +from unittest.mock import AsyncMock, MagicMock, patch import pytest from selectools import Agent, AgentConfig from selectools.coherence import CoherenceResult -from selectools.policy import PolicyDecision, PolicyResult, ToolPolicy +from selectools.policy import ToolPolicy from selectools.providers.stubs import LocalProvider -from selectools.tools.base import Tool from selectools.tools.decorators import tool -from selectools.trace import AgentTrace, StepType, TraceStep +from selectools.trace import AgentTrace, StepType from selectools.types import Message, Role, ToolCall -from selectools.usage import AgentUsage, UsageStats +from selectools.usage import UsageStats # ── Helpers ────────────────────────────────────────────────────────────────── @@ -93,7 +91,7 @@ def test_sync_tool_timeout_fires(self): """Tool times out and agent reports TimeoutError.""" agent = _make_agent(tools=[slow_tool], tool_timeout_seconds=0.01) # Force the agent to call slow_tool directly via _execute_tool_with_timeout - result = agent.run("call slow_tool") + agent.run("call slow_tool") # The agent loop will just echo, but we can test the direct path # by calling the mixin method: with pytest.raises(TimeoutError, match="timed out"): @@ -625,8 +623,6 @@ def test_magentic_stall_replan(self): mock_result.usage = UsageStats(prompt_tokens=5, completion_tokens=3, total_tokens=8) mock_agent.arun = AsyncMock(return_value=mock_result) - call_count = {"n": 0} - # First call: not progressing, second: not progressing (triggers replan), # third: complete responses = [ @@ -721,7 +717,7 @@ def test_magentic_unknown_agent_fallback(self): strategy=SupervisorStrategy.MAGENTIC, max_rounds=5, ) - result = supervisor.run("task") + supervisor.run("task") # Agent should still execute using fallback to first agent assert mock_agent.arun.called @@ -813,7 +809,7 @@ def test_dynamic_routing_unknown_agent_fallback(self): strategy=SupervisorStrategy.DYNAMIC, max_rounds=5, ) - result = supervisor.run("task") + supervisor.run("task") # Falls back to "worker" then completes on _looks_complete("All done.") assert mock_agent.arun.called @@ -830,7 +826,7 @@ def test_dynamic_routing_empty_response(self): strategy=SupervisorStrategy.DYNAMIC, max_rounds=5, ) - result = supervisor.run("query") + supervisor.run("query") assert not mock_agent.arun.called @@ -1634,7 +1630,7 @@ async def _run(): return await agent._acall_provider(run_id="r1") asyncio.run(_run()) - captured = capsys.readouterr() + capsys.readouterr() # LocalProvider doesn't print verbose, but no crash def test_acall_provider_with_cache_hit(self): @@ -1726,7 +1722,7 @@ def flaky_complete(**kwargs): return original_complete(**kwargs) agent.provider.complete = flaky_complete - msg = agent._call_provider(run_id="r1") + agent._call_provider(run_id="r1") assert call_count["n"] == 2 diff --git a/tests/test_guardrails.py b/tests/test_guardrails.py index 5f94908f..8518f8b1 100644 --- a/tests/test_guardrails.py +++ b/tests/test_guardrails.py @@ -2,8 +2,6 @@ from __future__ import annotations -import json - import pytest from selectools.guardrails import ( diff --git a/tests/test_hardening.py b/tests/test_hardening.py index b7cd8274..714230d3 100644 --- a/tests/test_hardening.py +++ b/tests/test_hardening.py @@ -7,22 +7,16 @@ from __future__ import annotations -import asyncio -import time - import pytest -from selectools.exceptions import GraphExecutionError from selectools.orchestration.checkpoint import InMemoryCheckpointStore from selectools.orchestration.graph import AgentGraph, ErrorPolicy, GraphResult from selectools.orchestration.state import ( STATE_KEY_LAST_OUTPUT, GraphState, InterruptRequest, - MergePolicy, - Scatter, ) -from selectools.pipeline import Pipeline, Step, StepResult, branch, parallel, step +from selectools.pipeline import Pipeline, Step, branch, parallel, step # --------------------------------------------------------------------------- # Helpers diff --git a/tests/test_knowledge.py b/tests/test_knowledge.py index c88f0c97..82f664e0 100644 --- a/tests/test_knowledge.py +++ b/tests/test_knowledge.py @@ -15,11 +15,8 @@ from __future__ import annotations -import os from datetime import datetime, timedelta, timezone -from typing import Any, Dict, List, Optional - -import pytest +from typing import List from selectools.knowledge import KnowledgeMemory from selectools.toolbox.memory_tools import make_recall_tool, make_remember_tool diff --git a/tests/test_knowledge_backend.py b/tests/test_knowledge_backend.py index 574a4ac5..c4b80b94 100644 --- a/tests/test_knowledge_backend.py +++ b/tests/test_knowledge_backend.py @@ -8,7 +8,6 @@ import base64 import json -import os from typing import Optional import pytest diff --git a/tests/test_knowledge_backend_redis.py b/tests/test_knowledge_backend_redis.py index d609738a..87d36846 100644 --- a/tests/test_knowledge_backend_redis.py +++ b/tests/test_knowledge_backend_redis.py @@ -12,7 +12,7 @@ import pytest -from selectools.knowledge import KnowledgeBackend, KnowledgeMemory +from selectools.knowledge import KnowledgeMemory from selectools.knowledge_backends import RedisKnowledgeBackend # ====================================================================== diff --git a/tests/test_knowledge_backend_supabase.py b/tests/test_knowledge_backend_supabase.py index 183a2795..3c2c367a 100644 --- a/tests/test_knowledge_backend_supabase.py +++ b/tests/test_knowledge_backend_supabase.py @@ -12,7 +12,7 @@ import pytest -from selectools.knowledge import KnowledgeBackend, KnowledgeMemory +from selectools.knowledge import KnowledgeMemory from selectools.knowledge_backends import SupabaseKnowledgeBackend # ====================================================================== diff --git a/tests/test_knowledge_graph.py b/tests/test_knowledge_graph.py index d70c34ff..4e560e59 100644 --- a/tests/test_knowledge_graph.py +++ b/tests/test_knowledge_graph.py @@ -13,9 +13,7 @@ from __future__ import annotations import json -from typing import Any, Dict, List, Optional - -import pytest +from typing import Any, Dict, List from selectools.knowledge_graph import ( InMemoryTripleStore, diff --git a/tests/test_knowledge_stores.py b/tests/test_knowledge_stores.py index 48b5115d..77bffc3c 100644 --- a/tests/test_knowledge_stores.py +++ b/tests/test_knowledge_stores.py @@ -1,7 +1,6 @@ """Tests for knowledge memory enhancement (R3) — stores, entries, eviction.""" import os -import tempfile from datetime import datetime, timedelta, timezone import pytest diff --git a/tests/test_knowledge_stores_error_handling.py b/tests/test_knowledge_stores_error_handling.py index beb4b2fa..69f9a20a 100644 --- a/tests/test_knowledge_stores_error_handling.py +++ b/tests/test_knowledge_stores_error_handling.py @@ -8,8 +8,6 @@ from unittest.mock import MagicMock -import pytest - from selectools.knowledge import KnowledgeEntry from selectools.knowledge_store_redis import RedisKnowledgeStore from selectools.knowledge_store_supabase import SupabaseKnowledgeStore diff --git a/tests/test_mcp.py b/tests/test_mcp.py index 508f12cd..8f676df7 100644 --- a/tests/test_mcp.py +++ b/tests/test_mcp.py @@ -7,10 +7,8 @@ from __future__ import annotations -import json -from dataclasses import dataclass -from typing import Any, Dict, List, Optional -from unittest.mock import AsyncMock, MagicMock, patch +from typing import Dict +from unittest.mock import AsyncMock, MagicMock import pytest @@ -367,7 +365,6 @@ def test_lazy_server_import(self) -> None: class TestBackgroundLoop: def test_loop_runs_coroutine(self) -> None: - import asyncio from selectools.mcp._loop import _BackgroundLoop diff --git a/tests/test_mcp_coverage.py b/tests/test_mcp_coverage.py index 51520d97..667e7ad8 100644 --- a/tests/test_mcp_coverage.py +++ b/tests/test_mcp_coverage.py @@ -3,10 +3,9 @@ from __future__ import annotations import asyncio -import copy import time from dataclasses import dataclass -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List from unittest.mock import AsyncMock, MagicMock, patch import pytest diff --git a/tests/test_memory_boundary.py b/tests/test_memory_boundary.py index 26cb752b..322d6aaa 100644 --- a/tests/test_memory_boundary.py +++ b/tests/test_memory_boundary.py @@ -8,8 +8,6 @@ from __future__ import annotations -import pytest - from selectools.memory import ConversationMemory from selectools.types import Message, Role, ToolCall diff --git a/tests/test_memory_integration.py b/tests/test_memory_integration.py index 504c2fcf..24e25b2b 100644 --- a/tests/test_memory_integration.py +++ b/tests/test_memory_integration.py @@ -8,10 +8,6 @@ from __future__ import annotations import os -import tempfile -from unittest.mock import MagicMock, patch - -import pytest from selectools.agent import Agent, AgentConfig from selectools.entity_memory import EntityMemory diff --git a/tests/test_multi_agent_edge_cases.py b/tests/test_multi_agent_edge_cases.py index f81f13df..f75de79c 100644 --- a/tests/test_multi_agent_edge_cases.py +++ b/tests/test_multi_agent_edge_cases.py @@ -8,7 +8,6 @@ from __future__ import annotations import json -from typing import Any import pytest @@ -20,10 +19,10 @@ from selectools.orchestration.checkpoint import InMemoryCheckpointStore from selectools.orchestration.graph import ErrorPolicy from selectools.orchestration.state import STATE_KEY_LAST_OUTPUT, GraphState, InterruptRequest -from selectools.pipeline import Pipeline, Step, branch, parallel, step +from selectools.pipeline import Pipeline, Step, branch from selectools.providers.base import Provider from selectools.trace import StepType -from selectools.types import AgentResult, Message, Role, ToolCall +from selectools.types import Message, Role, ToolCall from selectools.usage import UsageStats # --------------------------------------------------------------------------- diff --git a/tests/test_multimodal.py b/tests/test_multimodal.py index 297635fe..1cc0863f 100644 --- a/tests/test_multimodal.py +++ b/tests/test_multimodal.py @@ -2,10 +2,6 @@ from __future__ import annotations -import base64 -import os -import tempfile - import pytest from selectools.types import ContentPart, Message, Role, image_message, text_content diff --git a/tests/test_orchestration_checkpoint.py b/tests/test_orchestration_checkpoint.py index 0ebe7d98..a53875ce 100644 --- a/tests/test_orchestration_checkpoint.py +++ b/tests/test_orchestration_checkpoint.py @@ -9,7 +9,6 @@ import pytest from selectools.orchestration.checkpoint import ( - CheckpointMetadata, FileCheckpointStore, InMemoryCheckpointStore, SQLiteCheckpointStore, @@ -81,7 +80,7 @@ def test_interrupted_flag_in_metadata(self): store = InMemoryCheckpointStore() state = _make_state() state.metadata["__pending_interrupt_key__"] = "node_a_0" - cid = store.save("g1", state, 1) + store.save("g1", state, 1) metas = store.list("g1") assert metas[0].interrupted is True @@ -166,7 +165,7 @@ def test_files_created_on_disk(self): with tempfile.TemporaryDirectory() as tmpdir: store = FileCheckpointStore(tmpdir) state = _make_state() - cid = store.save("my_graph", state, 1) + store.save("my_graph", state, 1) graph_dir = os.path.join(tmpdir, "my_graph") assert os.path.isdir(graph_dir) files = os.listdir(graph_dir) @@ -197,7 +196,7 @@ def test_interrupted_metadata_in_file(self): store = FileCheckpointStore(tmpdir) state = _make_state() state.metadata["__pending_interrupt_key__"] = "node_0" - cid = store.save("g1", state, 1) + store.save("g1", state, 1) metas = store.list("g1") assert metas[0].interrupted is True @@ -257,7 +256,7 @@ def test_interrupted_metadata(self): store = SQLiteCheckpointStore(db) state = _make_state() state.metadata["__pending_interrupt_key__"] = "node_0" - cid = store.save("g1", state, 1) + store.save("g1", state, 1) metas = store.list("g1") assert metas[0].interrupted is True diff --git a/tests/test_orchestration_evals.py b/tests/test_orchestration_evals.py index 4c148c78..b7123412 100644 --- a/tests/test_orchestration_evals.py +++ b/tests/test_orchestration_evals.py @@ -15,7 +15,6 @@ from __future__ import annotations import os -from typing import Any, Dict, List import pytest diff --git a/tests/test_orchestration_graph.py b/tests/test_orchestration_graph.py index cf870845..3a9f2e04 100644 --- a/tests/test_orchestration_graph.py +++ b/tests/test_orchestration_graph.py @@ -2,24 +2,18 @@ from __future__ import annotations -import asyncio - import pytest from selectools.exceptions import GraphExecutionError -from selectools.orchestration.graph import AgentGraph, ErrorPolicy, GraphResult -from selectools.orchestration.node import GraphNode +from selectools.orchestration.graph import AgentGraph, ErrorPolicy from selectools.orchestration.state import ( STATE_KEY_LAST_OUTPUT, - ContextMode, - GraphEvent, GraphEventType, GraphState, InterruptRequest, MergePolicy, Scatter, ) -from selectools.types import Message, Role # ------------------------------------------------------------------ # Test helpers @@ -1050,7 +1044,7 @@ class TestRoutingFramework: def test_update_routing_applies_patch_and_follows_edge(self): """update() from router applies state patch then follows static edge.""" - from selectools.orchestration.state import _Update, update + from selectools.orchestration.state import update def update_router(state: GraphState): return update({"injected": "by_router"}) @@ -1103,7 +1097,7 @@ async def interrupt_node(state: GraphState): result = graph.run("go", checkpoint_store=store) assert result.interrupted - final = graph.resume(result.interrupt_id, "yes", checkpoint_store=store) + graph.resume(result.interrupt_id, "yes", checkpoint_store=store) assert len(resume_events) == 1, f"on_graph_resume should fire once. Got: {resume_events}" def test_file_checkpoint_rejects_path_traversal(self): diff --git a/tests/test_orchestration_integration.py b/tests/test_orchestration_integration.py index bef40479..c4306c81 100644 --- a/tests/test_orchestration_integration.py +++ b/tests/test_orchestration_integration.py @@ -2,18 +2,13 @@ from __future__ import annotations -import pytest - from selectools.observer import AgentObserver, LoggingObserver, SimpleStepObserver from selectools.orchestration import ( STATE_KEY_LAST_OUTPUT, AgentGraph, - CheckpointStore, ContextMode, ErrorPolicy, FileCheckpointStore, - GraphEvent, - GraphEventType, GraphNode, GraphResult, GraphState, @@ -27,9 +22,6 @@ SubgraphNode, SupervisorAgent, SupervisorStrategy, - goto, - merge_states, - update, ) from selectools.trace import StepType @@ -159,7 +151,6 @@ def test_logging_observer_implements_all_graph_methods(self): def test_logging_observer_graph_methods_callable(self): """LoggingObserver graph methods call _emit without raising.""" - import logging obs = LoggingObserver() # Should not raise diff --git a/tests/test_orchestration_supervisor.py b/tests/test_orchestration_supervisor.py index b677e634..8f009592 100644 --- a/tests/test_orchestration_supervisor.py +++ b/tests/test_orchestration_supervisor.py @@ -2,12 +2,11 @@ from __future__ import annotations -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest from selectools.orchestration.graph import GraphResult, _merge_usage -from selectools.orchestration.state import STATE_KEY_LAST_OUTPUT, GraphState from selectools.orchestration.supervisor import ( ModelSplit, SupervisorAgent, @@ -257,7 +256,7 @@ async def test_max_rounds_respected(self): max_rounds=3, ) - result = await supervisor.arun("task") + await supervisor.arun("task") # With 1 agent, 3 rounds → called exactly 3 times assert a.arun.call_count == 3 @@ -295,7 +294,7 @@ async def test_routes_to_named_agent(self): max_rounds=2, ) - result = await supervisor.arun("research topic") + await supervisor.arun("research topic") assert researcher.arun.call_count >= 1 @pytest.mark.asyncio @@ -328,7 +327,7 @@ async def test_unknown_agent_falls_back_to_first(self): max_rounds=1, ) - result = await supervisor.arun("task") + await supervisor.arun("task") # Should fall back to "a" and call it assert a.arun.call_count >= 1 @@ -404,7 +403,7 @@ async def mock_acomplete(*args, **kwargs): observers=[ReplanObserver()], ) - result = await supervisor.arun("stuck task") + await supervisor.arun("stuck task") assert len(replan_fired) >= 1 @pytest.mark.asyncio diff --git a/tests/test_patterns.py b/tests/test_patterns.py index 9859bc66..3bcc9736 100644 --- a/tests/test_patterns.py +++ b/tests/test_patterns.py @@ -2,26 +2,20 @@ from __future__ import annotations -import asyncio from dataclasses import is_dataclass -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import AsyncMock, MagicMock import pytest from selectools.patterns import ( DebateAgent, - DebateResult, - DebateRound, PlanAndExecuteAgent, PlanStep, - ReflectionRound, ReflectiveAgent, - ReflectiveResult, Subtask, TeamLeadAgent, TeamLeadResult, ) -from selectools.types import Message, Role # --------------------------------------------------------------------------- # Helpers @@ -93,7 +87,7 @@ def test_run_fallback_when_plan_empty(self): writer = _make_agent("fallback content") agent = PlanAndExecuteAgent(planner=planner, executors={"writer": writer}) - result = agent.run("Write something") + agent.run("Write something") # Fallback: writer should still be called writer.arun.assert_called_once() @@ -255,7 +249,7 @@ def test_run_calls_each_agent_each_round(self): judge=judge, max_rounds=3, ) - result = da.run("Should we adopt microservices?") + da.run("Should we adopt microservices?") assert optimist.arun.call_count == 3 assert skeptic.arun.call_count == 3 @@ -270,7 +264,7 @@ def test_run_calls_judge_once(self): judge=judge, max_rounds=2, ) - result = da.run("topic") + da.run("topic") judge.arun.assert_called_once() @@ -413,7 +407,7 @@ def test_sequential_executes_in_order(self): team={"analyst": analyst, "writer": writer}, delegation_strategy="sequential", ) - result = agent.run("Investigate and report") + agent.run("Investigate and report") analyst.arun.assert_called_once() writer.arun.assert_called_once() diff --git a/tests/test_phase1_design_patterns.py b/tests/test_phase1_design_patterns.py index 608af988..03d1b704 100644 --- a/tests/test_phase1_design_patterns.py +++ b/tests/test_phase1_design_patterns.py @@ -10,7 +10,6 @@ import base64 from enum import Enum from typing import Any -from unittest.mock import MagicMock import pytest diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py index 2e1866b8..d6b475a2 100644 --- a/tests/test_pipeline.py +++ b/tests/test_pipeline.py @@ -2,8 +2,6 @@ from __future__ import annotations -import asyncio - import pytest from selectools.pipeline import Pipeline, Step, StepResult, branch, parallel, step diff --git a/tests/test_pipeline_coverage.py b/tests/test_pipeline_coverage.py index 071f58b2..0cde9de7 100644 --- a/tests/test_pipeline_coverage.py +++ b/tests/test_pipeline_coverage.py @@ -2,7 +2,6 @@ from __future__ import annotations -import asyncio from typing import Any, Dict, List import pytest @@ -10,7 +9,6 @@ from selectools.pipeline import ( Pipeline, Step, - StepResult, _ensure_step, _filter_kwargs, _get_type_hints, @@ -526,7 +524,7 @@ def test_call_with_plain_value(self): assert result == "HELLO" def test_call_with_graph_state_no_last_output(self): - from selectools.orchestration.state import STATE_KEY_LAST_OUTPUT, GraphState + from selectools.orchestration.state import GraphState pipeline = Pipeline(steps=[Step(lambda x: x.upper(), name="up")]) state = GraphState.from_prompt("hello world") diff --git a/tests/test_prompt_compression.py b/tests/test_prompt_compression.py index 08af19ec..4946c621 100644 --- a/tests/test_prompt_compression.py +++ b/tests/test_prompt_compression.py @@ -5,8 +5,6 @@ from typing import List, Optional, Tuple from unittest.mock import patch -import pytest - from selectools import Agent, AgentConfig, Message, Role, Tool, UsageStats from selectools.memory import ConversationMemory from selectools.observer import AgentObserver diff --git a/tests/test_property_based.py b/tests/test_property_based.py index 0567709e..50096386 100644 --- a/tests/test_property_based.py +++ b/tests/test_property_based.py @@ -11,7 +11,6 @@ from __future__ import annotations from typing import Any, Dict, List -from unittest.mock import Mock import pytest from hypothesis import given, settings diff --git a/tests/test_remaining_coverage.py b/tests/test_remaining_coverage.py index 5b2892c2..dae3b7e6 100644 --- a/tests/test_remaining_coverage.py +++ b/tests/test_remaining_coverage.py @@ -5,17 +5,13 @@ from __future__ import annotations -import asyncio -import copy import json import os import tempfile import time -import uuid -from dataclasses import dataclass -from typing import Any, Dict, List, Optional +from typing import Any from unittest import mock -from unittest.mock import AsyncMock, MagicMock, patch +from unittest.mock import MagicMock import pytest @@ -35,7 +31,6 @@ ToolValidationError, ) from selectools.providers.stubs import LocalProvider -from selectools.tools.base import Tool from selectools.tools.decorators import tool from selectools.trace import AgentTrace, StepType, TraceStep, trace_to_html, trace_to_json from selectools.types import Message, Role, ToolCall @@ -811,7 +806,7 @@ def supports_streaming(self): provider=provider, config=AgentConfig(model="test", max_iterations=5), ) - result = await agent.arun("Return a person", response_format=Person) + await agent.arun("Return a person", response_format=Person) assert call_count >= 2 @pytest.mark.asyncio @@ -1002,7 +997,7 @@ class TestSnapshotStore: def test_snapshot_save_and_compare(self): from selectools.evals.snapshot import SnapshotStore - from selectools.evals.types import CaseResult, CaseVerdict, TestCase + from selectools.evals.types import CaseVerdict, TestCase with tempfile.TemporaryDirectory() as tmpdir: store = SnapshotStore(tmpdir) diff --git a/tests/test_results.py b/tests/test_results.py index 72afc133..4c9b82e8 100644 --- a/tests/test_results.py +++ b/tests/test_results.py @@ -5,7 +5,7 @@ import asyncio import json from dataclasses import FrozenInstanceError, asdict, dataclass -from typing import Any, ClassVar, List, Optional, Tuple +from typing import Any, ClassVar, List, Tuple import pytest diff --git a/tests/test_security.py b/tests/test_security.py index 2ce63bc7..f0eef073 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -2,9 +2,7 @@ from __future__ import annotations -import pytest - -from selectools.security import ScreeningResult, screen_output +from selectools.security import screen_output class TestScreenOutput: diff --git a/tests/test_semantic_cache.py b/tests/test_semantic_cache.py index 636632cb..212d8ded 100644 --- a/tests/test_semantic_cache.py +++ b/tests/test_semantic_cache.py @@ -4,7 +4,6 @@ import threading import time -from typing import List from unittest.mock import MagicMock import pytest diff --git a/tests/test_serve_app_coverage.py b/tests/test_serve_app_coverage.py index 555679f5..9f43ce91 100644 --- a/tests/test_serve_app_coverage.py +++ b/tests/test_serve_app_coverage.py @@ -9,7 +9,6 @@ from __future__ import annotations -import hashlib import json import os import tempfile @@ -17,7 +16,6 @@ import time import urllib.error import urllib.request -from typing import Any, Dict, List from unittest import mock import pytest @@ -34,7 +32,6 @@ BuilderServer, _ai_build_fallback, _apply_pinned_ports, - _builder_run_mock, _check_graph_permission, _estimate_run_cost, _estimate_task_tier, @@ -49,7 +46,6 @@ _resolve_auth_token, _resolve_users, _route_experiment, - _run_builder_evals, _run_evals_on_run, _smart_route, create_app, @@ -550,25 +546,25 @@ class TestMakeProvider: def test_claude_model(self): with mock.patch("selectools.providers.anthropic_provider.AnthropicProvider") as mock_cls: mock_cls.return_value = mock.MagicMock() - result = _make_provider("claude-sonnet-4-6", "sk-ant-fake") + _make_provider("claude-sonnet-4-6", "sk-ant-fake") mock_cls.assert_called_once_with(api_key="sk-ant-fake") def test_gemini_model(self): with mock.patch("selectools.providers.gemini_provider.GeminiProvider") as mock_cls: mock_cls.return_value = mock.MagicMock() - result = _make_provider("gemini-2.0-flash", "fake-key") + _make_provider("gemini-2.0-flash", "fake-key") mock_cls.assert_called_once_with(api_key="fake-key") def test_llama_model(self): with mock.patch("selectools.providers.ollama_provider.OllamaProvider") as mock_cls: mock_cls.return_value = mock.MagicMock() - result = _make_provider("llama-3.1", "fake-key") + _make_provider("llama-3.1", "fake-key") mock_cls.assert_called_once() def test_openai_default(self): with mock.patch("selectools.providers.openai_provider.OpenAIProvider") as mock_cls: mock_cls.return_value = mock.MagicMock() - result = _make_provider("gpt-4o-mini", "sk-fake") + _make_provider("gpt-4o-mini", "sk-fake") mock_cls.assert_called_once_with(api_key="sk-fake") @@ -842,7 +838,7 @@ def test_login_page_bypasses_auth(self, server): def test_builder_redirects_without_auth(self, server): req = urllib.request.Request(f"{server}/builder") try: - resp = _open_no_redirect(req) + _open_no_redirect(req) # If no redirect, check it returned login redirect or 302 assert False, "Expected 302 redirect" except urllib.error.HTTPError as e: @@ -856,7 +852,7 @@ def test_invoke_redirects_without_auth(self, server): headers={"Content-Type": "application/json"}, ) try: - resp = _open_no_redirect(req) + _open_no_redirect(req) assert False, "Expected 302 redirect" except urllib.error.HTTPError as e: assert e.code == 302 @@ -869,7 +865,7 @@ def test_login_correct_token(self, server): headers={"Content-Type": "application/json"}, ) try: - resp = _open_no_redirect(req) + _open_no_redirect(req) assert False, "Expected 302 redirect" except urllib.error.HTTPError as e: assert e.code == 302 diff --git a/tests/test_serve_cli.py b/tests/test_serve_cli.py index 5c81cd2b..1e68f10c 100644 --- a/tests/test_serve_cli.py +++ b/tests/test_serve_cli.py @@ -5,7 +5,6 @@ import argparse import os import sys -from io import StringIO from unittest.mock import MagicMock, patch import pytest diff --git a/tests/test_sessions_dynamodb.py b/tests/test_sessions_dynamodb.py index cfa4f922..0c24974a 100644 --- a/tests/test_sessions_dynamodb.py +++ b/tests/test_sessions_dynamodb.py @@ -9,7 +9,7 @@ from __future__ import annotations from decimal import Decimal -from typing import Any, Dict, List, Optional +from typing import Any, Dict, Optional from unittest.mock import MagicMock, patch import pytest diff --git a/tests/test_sessions_edge_cases.py b/tests/test_sessions_edge_cases.py index 4b474ab1..b1caf706 100644 --- a/tests/test_sessions_edge_cases.py +++ b/tests/test_sessions_edge_cases.py @@ -14,11 +14,9 @@ import os import time -import pytest - from selectools.memory import ConversationMemory from selectools.sessions import JsonFileSessionStore, SQLiteSessionStore -from selectools.types import Message, Role, ToolCall +from selectools.types import Message, Role def _memory_with_messages(*contents: str) -> ConversationMemory: diff --git a/tests/test_sessions_redis.py b/tests/test_sessions_redis.py index 08fda0c4..cee1b05b 100644 --- a/tests/test_sessions_redis.py +++ b/tests/test_sessions_redis.py @@ -9,7 +9,7 @@ import json import time -from typing import Any, Dict, Optional +from typing import Dict, Optional from unittest.mock import MagicMock, patch import pytest diff --git a/tests/test_sessions_supabase.py b/tests/test_sessions_supabase.py index 2b12cd65..5ff52f6c 100644 --- a/tests/test_sessions_supabase.py +++ b/tests/test_sessions_supabase.py @@ -8,7 +8,6 @@ from __future__ import annotations -import sys from datetime import datetime, timezone from typing import Any, Dict, List, Optional from unittest.mock import MagicMock, patch @@ -18,7 +17,7 @@ from selectools.memory import ConversationMemory from selectools.sessions import SessionMetadata, SupabaseSessionStore from selectools.types import Message, Role, ToolCall -from selectools.sessions import _validate_namespace + # ====================================================================== # Fake Supabase client # ====================================================================== @@ -494,21 +493,21 @@ def test_session_id_at_limit_passes(self) -> None: def test_empty_namespace_raises(self) -> None: store = self._store_without_supabase() with pytest.raises(ValueError, match="must not be empty"): - _validate_namespace("") + store._key("sid", namespace="") def test_null_byte_in_namespace_raises(self) -> None: store = self._store_without_supabase() with pytest.raises(ValueError, match="null bytes"): - _validate_namespace("bad\x00ns") + store._key("sid", namespace="bad\x00ns") def test_namespace_too_long_raises(self) -> None: store = self._store_without_supabase() with pytest.raises(ValueError, match="too long"): - _validate_namespace("n" * 513) + store._key("sid", namespace="n" * 513) def test_none_namespace_passes(self) -> None: store = self._store_without_supabase() - _validate_namespace(None) # must not raise + store._key("sid", namespace=None) # must not raise def test_save_empty_session_id_raises(self) -> None: client = FakeSupabaseClient() diff --git a/tests/test_starlette_app.py b/tests/test_starlette_app.py index 4b22113e..f6986cf1 100644 --- a/tests/test_starlette_app.py +++ b/tests/test_starlette_app.py @@ -1,7 +1,5 @@ """Tests for the Starlette ASGI builder app.""" -import json - import pytest starlette = pytest.importorskip("starlette", reason="starlette not installed") diff --git a/tests/test_structured_config.py b/tests/test_structured_config.py index f2262014..ee9e5314 100644 --- a/tests/test_structured_config.py +++ b/tests/test_structured_config.py @@ -2,8 +2,6 @@ from __future__ import annotations -import pytest - from selectools import ( AgentConfig, BudgetConfig, @@ -124,15 +122,7 @@ class TestImports: def test_all_config_groups_importable_from_selectools(self): from selectools import ( BudgetConfig, - CoherenceConfig, - CompressConfig, - GuardrailsConfig, - MemoryConfig, RetryConfig, - SessionConfig, - SummarizeConfig, - ToolConfig, - TraceConfig, ) assert RetryConfig is not None diff --git a/tests/test_structured_tool_results.py b/tests/test_structured_tool_results.py index 6f95ce8c..b565e704 100644 --- a/tests/test_structured_tool_results.py +++ b/tests/test_structured_tool_results.py @@ -5,7 +5,7 @@ import pytest -from selectools.tools.base import Tool, ToolParameter +from selectools.tools.base import Tool def _make_tool(func): diff --git a/tests/test_summarize_on_trim.py b/tests/test_summarize_on_trim.py index 7ddfdbb0..4bf9255f 100644 --- a/tests/test_summarize_on_trim.py +++ b/tests/test_summarize_on_trim.py @@ -13,16 +13,14 @@ from __future__ import annotations import os -from typing import Any, Dict, List, Optional, Tuple - -import pytest +from typing import Any, Dict, List, Optional from selectools.agent import Agent, AgentConfig from selectools.memory import ConversationMemory from selectools.observer import AgentObserver from selectools.sessions import JsonFileSessionStore from selectools.tools import Tool -from selectools.types import Message, Role, ToolCall +from selectools.types import Message, Role from selectools.usage import UsageStats diff --git a/tests/test_terminal_actions.py b/tests/test_terminal_actions.py index 964c477e..d742f3ef 100644 --- a/tests/test_terminal_actions.py +++ b/tests/test_terminal_actions.py @@ -7,14 +7,13 @@ from __future__ import annotations -import asyncio from typing import List import pytest from selectools import Agent, AgentConfig from selectools.tools import Tool, ToolParameter, tool -from selectools.types import Message, Role, ToolCall +from selectools.types import ToolCall # --------------------------------------------------------------------------- # Helpers diff --git a/tests/test_token_estimation.py b/tests/test_token_estimation.py index ace4c6dc..8b98eaea 100644 --- a/tests/test_token_estimation.py +++ b/tests/test_token_estimation.py @@ -1,7 +1,5 @@ """Tests for pre-execution token estimation (R6).""" -import json - from selectools.token_estimation import TokenEstimate, estimate_run_tokens, estimate_tokens from selectools.tools.base import Tool from selectools.types import Message, Role diff --git a/tests/test_trace.py b/tests/test_trace.py index 04f55503..94354b9e 100644 --- a/tests/test_trace.py +++ b/tests/test_trace.py @@ -10,9 +10,6 @@ import json import os import tempfile -from typing import Any, Dict, List - -import pytest from selectools.trace import AgentTrace, TraceStep diff --git a/tests/test_trace_html.py b/tests/test_trace_html.py index 06753222..b05f1c85 100644 --- a/tests/test_trace_html.py +++ b/tests/test_trace_html.py @@ -1,9 +1,5 @@ """Tests for trace_to_html.""" -import time - -import pytest - from selectools import trace_to_html from selectools.trace import AgentTrace, StepType, TraceStep diff --git a/tests/test_trace_store.py b/tests/test_trace_store.py index dc3de5a8..4c4aa74d 100644 --- a/tests/test_trace_store.py +++ b/tests/test_trace_store.py @@ -2,10 +2,7 @@ from __future__ import annotations -import os -import tempfile from datetime import datetime, timedelta, timezone -from typing import List import pytest @@ -15,7 +12,6 @@ SQLiteTraceStore, TraceFilter, TraceStore, - TraceSummary, ) from selectools.trace import AgentTrace, StepType, TraceStep @@ -433,7 +429,7 @@ def test_iter_entries_skips_blank_lines(self, tmp_path): def test_parent_dir_created(self, tmp_path): nested = tmp_path / "deep" / "nested" / "dir" - store = JSONLTraceStore(str(nested / "traces.jsonl")) + JSONLTraceStore(str(nested / "traces.jsonl")) assert nested.exists() def test_round_trip_preserves_step_data(self, tmp_path): diff --git a/tests/test_v016_regression.py b/tests/test_v016_regression.py index c121786c..cc9d4675 100644 --- a/tests/test_v016_regression.py +++ b/tests/test_v016_regression.py @@ -9,8 +9,6 @@ import os import time -import pytest - from selectools.entity_memory import Entity, EntityMemory from selectools.knowledge import KnowledgeMemory from selectools.memory import ConversationMemory diff --git a/tests/test_v019_features.py b/tests/test_v019_features.py index a312c7f8..4ddb0614 100644 --- a/tests/test_v019_features.py +++ b/tests/test_v019_features.py @@ -2,7 +2,6 @@ from __future__ import annotations -import asyncio import os import tempfile import warnings @@ -258,7 +257,7 @@ def consume_str(x: str) -> str: with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") - pipeline = produce_str | consume_str + produce_str | consume_str type_warnings = [x for x in w if "type mismatch" in str(x.message)] assert len(type_warnings) == 0 @@ -273,6 +272,6 @@ def consume_str(x: str) -> str: with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") - pipeline = produce_int | consume_str + produce_int | consume_str type_warnings = [x for x in w if "type mismatch" in str(x.message)] assert len(type_warnings) == 1 diff --git a/tests/test_visual_builder.py b/tests/test_visual_builder.py index a2d1b78c..52ceb979 100644 --- a/tests/test_visual_builder.py +++ b/tests/test_visual_builder.py @@ -1,6 +1,5 @@ """Tests for the visual agent builder (v0.20.0).""" -import io import json import threading import time @@ -12,7 +11,6 @@ from selectools.providers.stubs import LocalProvider from selectools.serve.app import ( AgentRouter, - AgentServer, BuilderServer, _builder_run_mock, _run_builder_evals, @@ -230,7 +228,7 @@ def test_eval_assertion_in_mk_node(self): def test_not_empty_eval_in_client_evals(self): """_clientRunEvals must include not_empty check.""" ci = BUILDER_HTML.find("function _clientRunEvals(") - ce = BUILDER_HTML.find("}", ci + 10) + BUILDER_HTML.find("}", ci + 10) # Find closing brace of function (nested, so find a reasonable range) assert "not_empty" in BUILDER_HTML[ci : ci + 800] @@ -1116,8 +1114,6 @@ def test_ai_build_route_exists(self): server = BuilderServer(port=0) # Use a real port for testing import socket - from http.server import HTTPServer - from socketserver import TCPServer sock = socket.socket() sock.bind(("", 0)) @@ -1815,10 +1811,9 @@ def _make_server(self, token=None): def _request(self, server, path="/builder", method="GET", body=None, cookie=None): """Fire a single request against a BuilderServer running in a thread.""" from http.server import HTTPServer - from urllib.parse import urlparse results = {} - httpd = HTTPServer(("127.0.0.1", 0), type("H", (), {})()) # dummy — replaced below + HTTPServer(("127.0.0.1", 0), type("H", (), {})()) # dummy — replaced below # Spin up the real server on a random port actual_port = [0] @@ -1826,9 +1821,6 @@ def _request(self, server, path="/builder", method="GET", body=None, cookie=None def run(): s = server # patch port - import types - - from selectools.serve.app import BuilderServer _auth = s.auth_token @@ -1848,7 +1840,6 @@ class TH(socketserver.ThreadingMixIn, HTTPServer): results["port"] = actual_port[0] # Simpler: use urllib directly against a real running instance - import time _port = [None] _stop = threading.Event() @@ -1869,11 +1860,9 @@ def _serve(): from urllib.parse import urlparse as _up from selectools.serve.app import ( - BUILDER_HTML, LOGIN_HTML, LOGIN_HTML_ERROR, _make_session_cookie, - _resolve_auth_token, ) class H(BaseHTTPRequestHandler): @@ -1997,7 +1986,7 @@ def http_error_302(self, req, fp, code, msg, headers): def test_no_auth_builder_accessible(self): """Without auth token, /builder returns 200.""" - from selectools.serve.app import BUILDER_HTML, BuilderServer + from selectools.serve.app import BuilderServer srv = BuilderServer(port=0, auth_token=None) r = self._request(srv, "/builder") @@ -2036,7 +2025,6 @@ def test_login_page_has_form(self): def test_login_correct_token_sets_cookie(self): """POST /login with correct token returns 302 + Set-Cookie header.""" - import json from selectools.serve.app import BuilderServer @@ -2047,7 +2035,6 @@ def test_login_correct_token_sets_cookie(self): def test_login_wrong_token_stays(self): """POST /login with wrong token returns 200 (error page, not redirect).""" - import json from selectools.serve.app import BuilderServer @@ -2603,7 +2590,6 @@ class TestBuilderAuthSSO: def test_resolve_users_from_env(self): """_resolve_users() reads BUILDER_USERS env var.""" - import json as _json import os from selectools.serve.app import _resolve_users diff --git a/tests/tools/test_browser_tools.py b/tests/tools/test_browser_tools.py index 5d21066d..5e9ddc09 100644 --- a/tests/tools/test_browser_tools.py +++ b/tests/tools/test_browser_tools.py @@ -77,7 +77,7 @@ def test_screenshot_blocks_internal_targets( self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path ) -> None: page = MagicMock() - browser = _install_fake_playwright(monkeypatch, page, patch_ssrf=False) + _install_fake_playwright(monkeypatch, page, patch_ssrf=False) result = browser_screenshot.function("http://127.0.0.1/", str(tmp_path / "p.png")) assert "Error" in result page.goto.assert_not_called() diff --git a/tests/tools/test_db_tools.py b/tests/tools/test_db_tools.py index e627e2c8..ff84f54a 100644 --- a/tests/tools/test_db_tools.py +++ b/tests/tools/test_db_tools.py @@ -10,11 +10,8 @@ import os import sqlite3 import tempfile -from pathlib import Path from unittest.mock import MagicMock, patch -import pytest - from selectools.toolbox import db_tools # ============================================================================= diff --git a/tests/tools/test_discord_tools.py b/tests/tools/test_discord_tools.py index bef5f1e0..92a45de4 100644 --- a/tests/tools/test_discord_tools.py +++ b/tests/tools/test_discord_tools.py @@ -8,7 +8,7 @@ import sys import types -from typing import Any, Dict, Optional +from typing import Any, Optional from unittest.mock import MagicMock import pytest diff --git a/tests/tools/test_github_tools.py b/tests/tools/test_github_tools.py index bf493a83..5dbeb595 100644 --- a/tests/tools/test_github_tools.py +++ b/tests/tools/test_github_tools.py @@ -12,8 +12,6 @@ from io import BytesIO from unittest.mock import MagicMock, patch -import pytest - from selectools.toolbox import github_tools diff --git a/tests/tools/test_notion_tools.py b/tests/tools/test_notion_tools.py index 9d39e8a7..2fadcf4a 100644 --- a/tests/tools/test_notion_tools.py +++ b/tests/tools/test_notion_tools.py @@ -73,7 +73,7 @@ def test_create_success(self, monkeypatch: pytest.MonkeyPatch) -> None: 200, {"id": "page-123", "url": "https://notion.so/page-123"} ) ) - fake = _install_fake_requests(monkeypatch, post=post) + _install_fake_requests(monkeypatch, post=post) result = notion_create_page.function( "parent-id", "My Page", content="line one\nline two", api_key=_KEY ) diff --git a/tests/tools/test_search_tools.py b/tests/tools/test_search_tools.py index a9a17e32..a6d057e0 100644 --- a/tests/tools/test_search_tools.py +++ b/tests/tools/test_search_tools.py @@ -10,8 +10,6 @@ from io import BytesIO from unittest.mock import MagicMock, patch -import pytest - from selectools.toolbox import search_tools diff --git a/tests/tools/test_tool_loader.py b/tests/tools/test_tool_loader.py index 71a3aafe..093e880c 100644 --- a/tests/tools/test_tool_loader.py +++ b/tests/tools/test_tool_loader.py @@ -2,15 +2,13 @@ from __future__ import annotations -import os -import tempfile from pathlib import Path from typing import TYPE_CHECKING, List from unittest.mock import MagicMock import pytest -from selectools.tools import Tool, ToolLoader, tool +from selectools.tools import Tool, ToolLoader from selectools.tools.base import ToolParameter if TYPE_CHECKING: @@ -388,7 +386,6 @@ def test_same_stem_files_in_different_dirs_both_load(self, tmp_path: Path) -> No def test_reload_file_targets_correct_module(self, tmp_path: Path) -> None: """reload_file must only remove the specific file's module, not a same-stem sibling.""" - import sys dir_a = tmp_path / "dir_a" dir_b = tmp_path / "dir_b" @@ -408,7 +405,7 @@ def test_reload_file_targets_correct_module(self, tmp_path: Path) -> None: " return 'B:' + x\n" ) - tools_a = ToolLoader.from_file(str(dir_a / "plugin.py")) + ToolLoader.from_file(str(dir_a / "plugin.py")) tools_b = ToolLoader.from_file(str(dir_b / "plugin.py")) # Reload A — B's module must remain in sys.modules diff --git a/tests/tools/test_toolbox.py b/tests/tools/test_toolbox.py index acadac25..482ec9bb 100644 --- a/tests/tools/test_toolbox.py +++ b/tests/tools/test_toolbox.py @@ -441,9 +441,6 @@ def test_get_current_time_utc_without_pytz_returns_time(self) -> None: The parameter name 'timezone' was shadowing the imported datetime.timezone class, causing 'UTC'.utc AttributeError instead of returning the current time. """ - import sys - import types - import unittest.mock as mock # Test UTC timezone works (pytz not needed for UTC) from selectools.toolbox.datetime_tools import get_current_time diff --git a/tests/tools/test_toolbox_coverage.py b/tests/tools/test_toolbox_coverage.py index 68de73e3..371095ec 100644 --- a/tests/tools/test_toolbox_coverage.py +++ b/tests/tools/test_toolbox_coverage.py @@ -11,13 +11,9 @@ from __future__ import annotations -import csv import json -import tempfile -from io import StringIO from pathlib import Path from types import SimpleNamespace -from typing import Generator from unittest import mock import pytest