style: apply ruff's automatic fixes and formatter

Mechanical only, and separated from the judgment calls that follow so the
reviewable changes are not buried in a 98-file whitespace diff.

227 automatic fixes: 60 blank lines carrying whitespace, 60 unsorted import
blocks, 34 Optional[X] to X | None, 28 unused imports, 16 deprecated typing
imports, 12 datetime.timezone.utc to datetime.UTC, and assorted smaller
modernisations. Then `ruff format` over src and tests: 98 files reformatted,
35 already conforming.

No file among the unused-import findings defines __all__ or is an __init__.py,
so nothing here removes a re-export.

`make test`: 658 passed, unchanged from HEAD.

Two things observed while verifying, neither addressed here:

`pytest tests/` cannot collect — tests/e2e/test_orchestration_e2e.py uses an
`e2e` marker that is not registered, and the config is strict about markers.
This fails identically at HEAD, so it predates this change; `make test` passes
because it ignores tests/e2e, tests/integration and tests/contracts.

test_tatlock_tool_call_logging_calculator is flaky. It failed once in a full run
with these changes and passed on the next, passes in isolation with them, and
fails in isolation at HEAD. It is order- or timing-dependent, not a regression
from this commit — established by running the full suite both ways rather than
by reasoning about which change could have caused it.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-11 17:25:18 +02:00
co-authored by Claude
parent 57fa6c13fc
commit 78066fab1b
103 changed files with 1601 additions and 1749 deletions
+53 -66
View File
@@ -6,7 +6,9 @@ Tests:
- Stop sequence detection and enforcement
- Max tokens enforcement
"""
import json
import pytest
from fastapi.testclient import TestClient
from httpx import AsyncClient
@@ -15,11 +17,11 @@ from pydantic import ValidationError
from src.responses.schemas import ResponseRequest
from src.responses.streaming import StreamingCoordinator
# ============================================================================
# Parameter Validation Tests
# ============================================================================
@pytest.mark.unit
def test_temperature_validation():
"""Test temperature parameter validation."""
@@ -27,9 +29,7 @@ def test_temperature_validation():
valid_temps = [0.0, 0.5, 1.0, 1.5, 2.0]
for temp in valid_temps:
request = ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
temperature=temp
model="lorem-tester", input=[{"role": "user", "content": "Hello"}], temperature=temp
)
assert request.temperature == temp
@@ -38,7 +38,7 @@ def test_temperature_validation():
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
temperature=-0.1 # Too low
temperature=-0.1, # Too low
)
assert "temperature" in str(exc_info.value).lower()
@@ -46,7 +46,7 @@ def test_temperature_validation():
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
temperature=2.1 # Too high
temperature=2.1, # Too high
)
assert "temperature" in str(exc_info.value).lower()
@@ -55,12 +55,12 @@ def test_temperature_validation():
def test_reasoning_effort_validation():
"""Test reasoning.effort parameter validation."""
# Valid effort levels
valid_efforts = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh']
valid_efforts = ["none", "minimal", "low", "medium", "high", "xhigh"]
for effort in valid_efforts:
request = ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
reasoning={"effort": effort, "summary": "auto"}
reasoning={"effort": effort, "summary": "auto"},
)
assert request.reasoning["effort"] == effort
@@ -69,7 +69,7 @@ def test_reasoning_effort_validation():
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
reasoning={"effort": "invalid", "summary": "auto"}
reasoning={"effort": "invalid", "summary": "auto"},
)
assert "reasoning.effort" in str(exc_info.value)
@@ -78,12 +78,12 @@ def test_reasoning_effort_validation():
def test_reasoning_summary_validation():
"""Test reasoning.summary parameter validation."""
# Valid summary values
valid_summaries = ['auto', 'off']
valid_summaries = ["auto", "off"]
for summary in valid_summaries:
request = ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
reasoning={"effort": "medium", "summary": summary}
reasoning={"effort": "medium", "summary": summary},
)
assert request.reasoning["summary"] == summary
@@ -92,7 +92,7 @@ def test_reasoning_summary_validation():
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
reasoning={"effort": "medium", "summary": "invalid"}
reasoning={"effort": "medium", "summary": "invalid"},
)
assert "reasoning.summary" in str(exc_info.value)
@@ -102,26 +102,20 @@ def test_max_output_tokens_validation():
"""Test max_output_tokens parameter validation."""
# Valid values
request = ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
max_output_tokens=100
model="lorem-tester", input=[{"role": "user", "content": "Hello"}], max_output_tokens=100
)
assert request.max_output_tokens == 100
# None is valid (unlimited)
request = ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
max_output_tokens=None
model="lorem-tester", input=[{"role": "user", "content": "Hello"}], max_output_tokens=None
)
assert request.max_output_tokens is None
# Invalid: zero or negative
with pytest.raises(ValidationError) as exc_info:
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
max_output_tokens=0
model="lorem-tester", input=[{"role": "user", "content": "Hello"}], max_output_tokens=0
)
assert "max_output_tokens" in str(exc_info.value)
@@ -129,7 +123,7 @@ def test_max_output_tokens_validation():
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
max_output_tokens=-10
max_output_tokens=-10,
)
assert "max_output_tokens" in str(exc_info.value)
@@ -141,9 +135,7 @@ def test_stop_sequences_validation():
for num_seqs in range(1, 5):
stop_seqs = [f"stop{i}" for i in range(num_seqs)]
request = ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
stop=stop_seqs
model="lorem-tester", input=[{"role": "user", "content": "Hello"}], stop=stop_seqs
)
assert request.stop == stop_seqs
@@ -152,7 +144,7 @@ def test_stop_sequences_validation():
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
stop=["stop1", "stop2", "stop3", "stop4", "stop5"] # 5 sequences
stop=["stop1", "stop2", "stop3", "stop4", "stop5"], # 5 sequences
)
assert "4 stop sequences" in str(exc_info.value)
@@ -161,7 +153,7 @@ def test_stop_sequences_validation():
ResponseRequest(
model="lorem-tester",
input=[{"role": "user", "content": "Hello"}],
stop=["stop1", ""] # Empty string
stop=["stop1", ""], # Empty string
)
assert "non-empty" in str(exc_info.value).lower()
@@ -170,6 +162,7 @@ def test_stop_sequences_validation():
# Stop Sequence Enforcement Tests
# ============================================================================
@pytest.mark.unit
def test_stop_sequence_detection_helper():
"""Test stop sequence detection helper method."""
@@ -181,26 +174,17 @@ def test_stop_sequence_detection_helper():
assert text == "Hello world"
# Stop sequence not present
found, text = coordinator._check_stop_sequence(
"Hello world",
["STOP", "END"]
)
found, text = coordinator._check_stop_sequence("Hello world", ["STOP", "END"])
assert found is False
assert text == "Hello world"
# Stop sequence found
found, text = coordinator._check_stop_sequence(
"Hello STOP this should not appear",
["STOP"]
)
found, text = coordinator._check_stop_sequence("Hello STOP this should not appear", ["STOP"])
assert found is True
assert text == "Hello "
# Multiple stop sequences, first one wins
found, text = coordinator._check_stop_sequence(
"Hello STOP this END that",
["STOP", "END"]
)
found, text = coordinator._check_stop_sequence("Hello STOP this END that", ["STOP", "END"])
assert found is True
assert text == "Hello "
@@ -216,7 +200,7 @@ async def test_stop_sequence_in_streaming(async_client: AsyncClient):
"model": "lorem-tester",
"input": [{"role": "user", "content": "Generate long text"}],
"stop": ["dolor"], # Common word in lorem ipsum
"stream": True
"stream": True,
}
chunks_received = []
@@ -251,6 +235,7 @@ async def test_stop_sequence_in_streaming(async_client: AsyncClient):
# Max Tokens Enforcement Tests
# ============================================================================
@pytest.mark.unit
def test_max_tokens_check_helper():
"""Test max tokens check helper method."""
@@ -296,7 +281,7 @@ async def test_max_tokens_in_streaming(async_client: AsyncClient):
"model": "lorem-tester",
"input": [{"role": "user", "content": "Generate text"}],
"max_output_tokens": 5, # Very low limit
"stream": True
"stream": True,
}
chunks_received = []
@@ -340,6 +325,7 @@ async def test_max_tokens_in_streaming(async_client: AsyncClient):
# Combined Features Test
# ============================================================================
@pytest.mark.unit
def test_combined_validation(client: TestClient):
"""Test combined parameter validation in actual request."""
@@ -351,7 +337,7 @@ def test_combined_validation(client: TestClient):
"max_output_tokens": 100,
"stop": ["STOP", "END"],
"reasoning": {"effort": "high", "summary": "auto"},
"stream": False
"stream": False,
}
response = client.post("/v1/responses", json=request_data)
@@ -368,7 +354,7 @@ def test_invalid_combined_parameters(client: TestClient):
"model": "lorem-tester",
"input": [{"role": "user", "content": "Hello"}],
"temperature": 3.0, # Too high
"stream": False
"stream": False,
}
response = client.post("/v1/responses", json=request_data)
@@ -382,6 +368,7 @@ def test_invalid_combined_parameters(client: TestClient):
# Streaming Delta Calculation Tests (No Duplication)
# ============================================================================
@pytest.mark.unit
@pytest.mark.asyncio
async def test_streaming_delta_calculation_no_duplication():
@@ -392,8 +379,10 @@ async def test_streaming_delta_calculation_no_duplication():
This test prevents the duplication bug where the same text was
streamed multiple times because we weren't computing deltas correctly.
"""
from collections.abc import AsyncGenerator
from typing import Any
from src.agents.base import AgentInterface, OutputItem
from typing import AsyncGenerator, Any
# Create a mock agent that simulates PydanticAI's behavior
# (yielding accumulated text, not deltas)
@@ -406,7 +395,7 @@ async def test_streaming_delta_calculation_no_duplication():
temperature: float = 1.0,
max_tokens: int | None = None,
stop: list[str] | None = None,
**kwargs: Any
**kwargs: Any,
) -> AsyncGenerator[OutputItem, None]:
"""
Simulate PydanticAI streaming behavior:
@@ -430,12 +419,8 @@ async def test_streaming_delta_calculation_no_duplication():
type="message",
id=msg_id,
role="assistant",
content=[{
"type": "output_text",
"text": text,
"annotations": []
}],
status="in_progress"
content=[{"type": "output_text", "text": text, "annotations": []}],
status="in_progress",
)
# Final message
@@ -443,12 +428,10 @@ async def test_streaming_delta_calculation_no_duplication():
type="message",
id=msg_id,
role="assistant",
content=[{
"type": "output_text",
"text": "Hello world how are you",
"annotations": []
}],
status="completed"
content=[
{"type": "output_text", "text": "Hello world how are you", "annotations": []}
],
status="completed",
)
async def supports_tools(self) -> bool:
@@ -462,7 +445,9 @@ async def test_streaming_delta_calculation_no_duplication():
# Register the mock agent
import time
from src.agents.registry import ModelRegistry
ModelRegistry.MODELS["mock-streaming"] = {
"agent_class": MockStreamingAgent,
"description": "Mock streaming agent for testing",
@@ -473,9 +458,7 @@ async def test_streaming_delta_calculation_no_duplication():
try:
# Create a test request
request = ResponseRequest(
model="mock-streaming",
input=[{"role": "user", "content": "Test"}],
stream=True
model="mock-streaming", input=[{"role": "user", "content": "Test"}], stream=True
)
# Stream the response
@@ -512,8 +495,10 @@ async def test_streaming_with_multiple_message_items():
Test that coordinator handles multiple message OutputItems correctly,
only streaming the delta between each one.
"""
from collections.abc import AsyncGenerator
from typing import Any
from src.agents.base import AgentInterface, OutputItem
from typing import AsyncGenerator, Any
class MockMultiMessageAgent(AgentInterface):
async def generate_response(
@@ -524,7 +509,7 @@ async def test_streaming_with_multiple_message_items():
temperature: float = 1.0,
max_tokens: int | None = None,
stop: list[str] | None = None,
**kwargs: Any
**kwargs: Any,
) -> AsyncGenerator[OutputItem, None]:
"""Yield multiple in_progress messages with accumulated text."""
# First chunk
@@ -533,7 +518,7 @@ async def test_streaming_with_multiple_message_items():
id="msg_1",
role="assistant",
content=[{"type": "output_text", "text": "The answer is", "annotations": []}],
status="in_progress"
status="in_progress",
)
# Second chunk (more text accumulated)
@@ -542,7 +527,7 @@ async def test_streaming_with_multiple_message_items():
id="msg_1",
role="assistant",
content=[{"type": "output_text", "text": "The answer is 42", "annotations": []}],
status="in_progress"
status="in_progress",
)
# Final chunk
@@ -551,7 +536,7 @@ async def test_streaming_with_multiple_message_items():
id="msg_1",
role="assistant",
content=[{"type": "output_text", "text": "The answer is 42", "annotations": []}],
status="completed"
status="completed",
)
async def supports_tools(self) -> bool:
@@ -565,7 +550,9 @@ async def test_streaming_with_multiple_message_items():
# Register mock agent
import time
from src.agents.registry import ModelRegistry
ModelRegistry.MODELS["mock-multi"] = {
"agent_class": MockMultiMessageAgent,
"description": "Mock multi-message agent for testing",
@@ -577,7 +564,7 @@ async def test_streaming_with_multiple_message_items():
request = ResponseRequest(
model="mock-multi",
input=[{"role": "user", "content": "What is the answer?"}],
stream=True
stream=True,
)
coordinator = StreamingCoordinator()