feat!: adopt Python 3.15 and support BattlesnakeArena

- Require Python 3.15 in project metadata, runtime pin, and Docker stages.
- Use lazy imports for database backends and type-only dependencies.
- Defer benchmark dependencies until their code paths are used.
- Rely on deferred annotations and use Path.info for file discovery.
- Accept BattlesnakeArena alongside BattlesnakeEngine on game endpoints.
- Advance quart_common for Python 3.15 and multi-agent validation.
- Add pytest development dependencies and refresh the uv lockfile.
- Test lazy backend loading, import order, and fresh file discovery.
- Document the runtime requirements and locked uv workflow.

BREAKING CHANGE: Python 3.15 or newer is required; earlier runtimes cannot parse the lazy import syntax.
This commit is contained in:
2026-11-03 10:02:40 +01:00
parent f14d780f29
commit 5efab77248
35 changed files with 226 additions and 202 deletions
-2
View File
@@ -5,8 +5,6 @@ For outcome/win-rate tournaments use the local Battlesnake CLI. This harness is
fast enough for CI and detects move disagreements, crashes, and latency changes.
"""
from __future__ import annotations
import argparse
import json
import sys
+2 -5
View File
@@ -1,8 +1,5 @@
#!/usr/bin/env python3
"""Benchmark snake move latency against sampled states from gameplay SQLite."""
from __future__ import annotations
import argparse
from pathlib import Path
import sqlite3
@@ -15,8 +12,8 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from server.database.benchmark_states import (
_build_state, is_postgresql_source, load_postgresql_states,
)
from server.GameBoard import GameBoard
from snakes import SnakeBuilder
lazy from server.GameBoard import GameBoard
lazy from snakes import SnakeBuilder
def percentile(values: list[float], quantile: float) -> float:
ordered = sorted(values)
-3
View File
@@ -1,8 +1,5 @@
#!/usr/bin/env python3
"""Delete old low-quality replay payloads while preserving game results."""
from __future__ import annotations
import argparse
import asyncio
from datetime import datetime, timedelta, timezone
+3 -6
View File
@@ -1,10 +1,7 @@
#!/usr/bin/env python3
from __future__ import annotations
import argparse
from pathlib import Path
from typing import Iterable
from collections.abc import Iterable
from urllib.parse import urlencode
from urllib.request import urlopen
import shutil
@@ -84,14 +81,14 @@ def prune_output(output_root:Path, wanted_files:set[Path]) -> int:
return 0
for file_path in output_root.rglob("*"):
if not file_path.is_file():
if not file_path.info.is_file():
continue
if file_path not in wanted_files:
file_path.unlink()
removed += 1
for directory in sorted(
(p for p in output_root.rglob("*") if p.is_dir()), reverse=True
(p for p in output_root.rglob("*") if p.info.is_dir()), reverse=True
):
if any(directory.iterdir()):
continue
-3
View File
@@ -6,9 +6,6 @@ row IDs are regenerated, delta games are quality-rated, and all result rows are
kept even when their replay is excluded. The base can be replaced only after
verification and a timestamped backup.
"""
from __future__ import annotations
import argparse
from collections import Counter
from datetime import datetime, timezone
-3
View File
@@ -5,9 +5,6 @@ The source is always opened read-only. The destination is written separately,
verified, and can optionally replace the source after a timestamped backup is
created. No in-place schema rewrite is performed.
"""
from __future__ import annotations
import argparse
from datetime import datetime, timezone
import json
-3
View File
@@ -5,9 +5,6 @@ The source is opened read-only. Rows are copied in bounded batches through
temporary PostgreSQL tables, then inserted idempotently with ON CONFLICT. The
script verifies source/inserted row counts and never modifies the SQLite file.
"""
from __future__ import annotations
import argparse
import asyncio
from datetime import datetime
-3
View File
@@ -1,8 +1,5 @@
#!/usr/bin/env python3
"""Run paired seeded games through the official local Battlesnake rules engine."""
from __future__ import annotations
import argparse
import json
import os
-3
View File
@@ -1,7 +1,4 @@
"""Deterministic scenario corpus for the local snake arena."""
from __future__ import annotations
from copy import deepcopy
from tests.bench_best_battle_snake import build_game_state