chore: require python 3.12 and adopt PEP 695 type parameters

The telemetry write budget needs asyncio.timeout, whose uncancel accounting
was only fixed after 3.11.1 — pinning the floor at 3.12 removes that hazard
instead of working around it.

Raising ruff's target-version turns on UP047, so gather_bounded,
_anext_within and stream_with_liveness_timeouts move to def f[T](...) and
the two module-level TypeVars go away. That syntax is a SyntaxError on
3.11, so it can only land together with the version bump.
This commit is contained in:
2026-08-24 08:14:45 -04:00
parent 59a4bc3d14
commit 157a27f3bb
5 changed files with 15 additions and 19 deletions
+3 -5
View File
@@ -13,7 +13,7 @@ import hashlib
import json
import random
import time
from typing import TYPE_CHECKING, Any, Literal, TypeVar
from typing import TYPE_CHECKING, Any, Literal
from polygateway.backends.memory.breaker import InMemoryGate
from polygateway.backends.memory.cache import InMemoryCache
@@ -63,8 +63,6 @@ if TYPE_CHECKING:
SourceConfig,
)
_T = TypeVar("_T")
def _guard_thinking(
sources: list[SourceConfig],
@@ -442,7 +440,7 @@ def _build_structured(
return None, None
async def gather_bounded(aws: Iterable[Awaitable[_T]], *, concurrency: int) -> list[_T]:
async def gather_bounded[T](aws: Iterable[Awaitable[T]], *, concurrency: int) -> list[T]:
"""有界并发 gather(D5 便利函数,替代 VT 手搓 semaphore+gather 样板)。
语义与 `asyncio.gather` 默认一致: 结果保序、首个异常上抛;仅增加并发上限。
@@ -451,7 +449,7 @@ async def gather_bounded(aws: Iterable[Awaitable[_T]], *, concurrency: int) -> l
raise ValueError("concurrency 必须 ≥ 1")
sem = asyncio.Semaphore(concurrency)
async def _run(aw: Awaitable[_T]) -> _T:
async def _run(aw: Awaitable[T]) -> T:
async with sem:
return await aw
+7 -9
View File
@@ -14,13 +14,11 @@ from __future__ import annotations
import asyncio
import contextlib
import time
from typing import TYPE_CHECKING, TypeVar
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import AsyncIterator
_T = TypeVar("_T")
class StreamLivenessTimeout(Exception): # noqa: N818 — 三项目冻结的公共名
"""流活性超时异常。
@@ -38,14 +36,14 @@ class StreamLivenessTimeout(Exception): # noqa: N818 — 三项目冻结的公
super().__init__(f"流活性超时({kind}, elapsed={elapsed_s:.1f}s)")
async def _anext_within(
it: AsyncIterator[_T],
async def _anext_within[T](
it: AsyncIterator[T],
timeout_s: float,
*,
kind: str,
start: float,
first: bool,
) -> _T:
) -> T:
"""限时取下一项;本层 deadline 触发抛 StreamLivenessTimeout(kind)。
上游自抛的 TimeoutError 用 cm.expired() 区分,原样上抛不误吞。
@@ -59,13 +57,13 @@ async def _anext_within(
raise StreamLivenessTimeout(kind, time.monotonic() - start, not first) from None
async def stream_with_liveness_timeouts(
source: AsyncIterator[_T],
async def stream_with_liveness_timeouts[T](
source: AsyncIterator[T],
*,
ttft_s: float,
inter_token_s: float,
total_s: float,
) -> AsyncIterator[_T]:
) -> AsyncIterator[T]:
"""逐项产出 source,并施加三层活性超时。
关键实现: 超时**只包裹单次 __anext__**,绝不包裹 yield——否则总时长