Skip to content

Commit 7ee8dc9

Browse files
fix(api): resolve mypy strict errors in rate limiter and health check
- rate_limit: make the decorator generic over the handler return type so endpoints returning a response model (e.g. TokenResponse) type-check - main: drop now-unused redis ping type:ignore (redis 8 ships py.typed) Co-Authored-By: First Fluke <our.first.fluke@gmail.com>
1 parent 9b668a4 commit 7ee8dc9

2 files changed

Lines changed: 10 additions & 6 deletions

File tree

apps/api/src/lib/rate_limit.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from collections.abc import Awaitable, Callable
77
from dataclasses import dataclass, field
88
from functools import wraps
9-
from typing import TYPE_CHECKING, cast
9+
from typing import TYPE_CHECKING, TypeVar, cast
1010

1111
from fastapi import HTTPException, Request, status
1212
from fastapi.responses import Response
@@ -19,6 +19,10 @@
1919

2020
logger = get_logger(__name__)
2121

22+
# Return type of the decorated endpoint (e.g. a Pydantic response model),
23+
# preserved so the rate limiter does not narrow handler return types to Response.
24+
R = TypeVar("R")
25+
2226

2327
@dataclass
2428
class RateLimitConfig:
@@ -224,7 +228,7 @@ def rate_limit(
224228
requests: int = 100,
225229
window: int = 60,
226230
key_func: Callable[[Request], str] | None = None,
227-
) -> Callable[[Callable[..., Awaitable[Response]]], Callable[..., Awaitable[Response]]]:
231+
) -> Callable[[Callable[..., Awaitable[R]]], Callable[..., Awaitable[R]]]:
228232
"""
229233
Rate limit decorator for FastAPI endpoints.
230234
@@ -243,10 +247,10 @@ async def get_resource():
243247
actual_key_func = key_func or default_key_func
244248

245249
def decorator(
246-
func: Callable[..., Awaitable[Response]],
247-
) -> Callable[..., Awaitable[Response]]:
250+
func: Callable[..., Awaitable[R]],
251+
) -> Callable[..., Awaitable[R]]:
248252
@wraps(func)
249-
async def wrapper(*args: object, **kwargs: object) -> Response:
253+
async def wrapper(*args: object, **kwargs: object) -> R:
250254
# Find request in args/kwargs
251255
request: Request | None = None
252256
for arg in args:

apps/api/src/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ async def check_redis() -> ServiceStatus | None:
172172
import redis.asyncio as redis
173173

174174
client = redis.from_url(settings.REDIS_URL)
175-
await client.ping() # type: ignore[misc]
175+
await client.ping()
176176
await client.aclose()
177177
latency = (time.perf_counter() - start) * 1000
178178
return ServiceStatus(status="healthy", latency_ms=round(latency, 2))

0 commit comments

Comments
 (0)