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
+33 -13
View File
@@ -4,12 +4,14 @@ Structured logging configuration using structlog.
Deeply integrates with FastAPI/uvicorn's built-in logging to provide
seamless structured logs across the entire application stack.
"""
import logging
import logging.config
import sys
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from datetime import datetime, timezone
from typing import Any, AsyncIterator
from datetime import UTC, datetime
from typing import Any
import structlog
from structlog.types import EventDict, Processor
@@ -19,7 +21,7 @@ from .config import config
def add_timestamp(logger: Any, method_name: str, event_dict: EventDict) -> EventDict:
"""Add ISO 8601 timestamp to log entries."""
event_dict["timestamp"] = datetime.now(timezone.utc).isoformat()
event_dict["timestamp"] = datetime.now(UTC).isoformat()
return event_dict
@@ -41,11 +43,28 @@ def extract_from_record(logger: Any, method_name: str, event_dict: EventDict) ->
# Extract custom fields from record
for key, value in record.__dict__.items():
if key not in {
"name", "msg", "args", "created", "filename", "funcName",
"levelname", "levelno", "lineno", "module", "msecs",
"message", "pathname", "process", "processName", "relativeCreated",
"thread", "threadName", "exc_info", "exc_text", "stack_info",
"taskName"
"name",
"msg",
"args",
"created",
"filename",
"funcName",
"levelname",
"levelno",
"lineno",
"module",
"msecs",
"message",
"pathname",
"process",
"processName",
"relativeCreated",
"thread",
"threadName",
"exc_info",
"exc_text",
"stack_info",
"taskName",
}:
event_dict[key] = value
@@ -164,7 +183,7 @@ def get_logger(name: str) -> structlog.stdlib.BoundLogger:
async def log_operation(
operation: str,
initial_context: dict[str, Any] | None = None,
logger_name: str = "tatlock.operations"
logger_name: str = "tatlock.operations",
) -> AsyncIterator[dict[str, Any]]:
"""
Context manager for automatic operation timing and logging.
@@ -187,21 +206,21 @@ async def log_operation(
context = initial_context or {}
context["operation"] = operation
start_time = datetime.now(timezone.utc)
start_time = datetime.now(UTC)
logger.info("operation_started", **context)
try:
yield context
# Success case
duration = (datetime.now(timezone.utc) - start_time).total_seconds()
duration = (datetime.now(UTC) - start_time).total_seconds()
context["duration_seconds"] = duration
context["success"] = True
logger.info("operation_completed", **context)
except Exception as e:
# Error case
duration = (datetime.now(timezone.utc) - start_time).total_seconds()
duration = (datetime.now(UTC) - start_time).total_seconds()
context["duration_seconds"] = duration
context["success"] = False
context["error"] = str(e)
@@ -228,7 +247,8 @@ def get_uvicorn_log_config() -> dict[str, Any]:
"()": structlog.stdlib.ProcessorFormatter,
"processors": [
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
structlog.processors.JSONRenderer() if config.log_format == "json"
structlog.processors.JSONRenderer()
if config.log_format == "json"
else structlog.dev.ConsoleRenderer(colors=True),
],
},