Fix mypy typecheck errors and FK format mismatch in test fixtures
Three categories of pre-existing CI failure on PR #42: 1. typecheck (mypy src/cartsnitch_api, 9 errors): - src/cartsnitch_api/config.py:89 — Settings() needs required secret args that only exist in env at runtime; suppress with type: ignore[call-arg] - src/cartsnitch_api/cache.py:38 — redis-py returns Any/bytes, normalize to str before returning from get() - src/cartsnitch_api/middleware/rate_limit.py:128,131,134 — three limiter globals were inferred as RedisSlidingWindow on the if branch then re-assigned InMemorySlidingWindow on else; declare them as RateLimitBackend up front - src/cartsnitch_api/middleware/rate_limit.py:181,187 — RateLimitBackend Protocol didn't declare max_requests even though both InMemorySlidingWindow and RedisSlidingWindow expose it; add max_requests: int to the Protocol 2. test (FK constraint on purchases.user_id): - tests/conftest.py:_create_test_user_and_session stored user_id as 32-char hex; test_e2e conftest reads it via raw SQL and wraps in uuid.UUID (36 chars) before passing to Purchase.user_id, so the FK never matched. Switch back to str(uuid.uuid4()) (36 chars) so the stored value and the FK bind value use the same format. 3. Verify lint + format clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -35,7 +35,10 @@ class CacheClient:
|
||||
async def get(self, key: str) -> str | None:
|
||||
if not self._client:
|
||||
return None
|
||||
return await self._client.get(key)
|
||||
result = await self._client.get(key)
|
||||
if result is None:
|
||||
return None
|
||||
return str(result)
|
||||
|
||||
async def set(self, key: str, value: str, ttl_seconds: int = 300) -> None:
|
||||
if not self._client:
|
||||
|
||||
@@ -86,4 +86,4 @@ class Settings(BaseSettings):
|
||||
return self
|
||||
|
||||
|
||||
settings = Settings()
|
||||
settings = Settings() # type: ignore[call-arg]
|
||||
|
||||
@@ -25,6 +25,8 @@ logger = logging.getLogger(__name__)
|
||||
class RateLimitBackend(Protocol):
|
||||
"""Protocol for rate limit backends."""
|
||||
|
||||
max_requests: int
|
||||
|
||||
async def is_allowed(self, key: str) -> tuple[bool, int, int]:
|
||||
"""Check if request is allowed. Returns (allowed, remaining, retry_after)."""
|
||||
|
||||
@@ -104,6 +106,9 @@ class RedisSlidingWindow:
|
||||
|
||||
_redis_client: Redis | None = None
|
||||
_use_redis = False
|
||||
_public_limiter: RateLimitBackend
|
||||
_auth_limiter: RateLimitBackend
|
||||
_auth_strict_limiter: RateLimitBackend
|
||||
|
||||
if settings.rate_limit_redis_enabled:
|
||||
try:
|
||||
|
||||
+2
-2
@@ -272,11 +272,11 @@ async def _create_test_user_and_session(
|
||||
Returns (user_dict, session_token). Better-Auth stores the raw token
|
||||
in the DB, so we insert it as-is.
|
||||
"""
|
||||
user_id = uuid.uuid4().hex
|
||||
user_id = str(uuid.uuid4())
|
||||
email = user_overrides.get("email", "test@example.com")
|
||||
display_name = user_overrides.get("display_name", "Test User")
|
||||
session_token = secrets.token_urlsafe(32)
|
||||
session_id = uuid.uuid4().hex
|
||||
session_id = str(uuid.uuid4())
|
||||
now = datetime.now(UTC).isoformat()
|
||||
expires = (datetime.now(UTC) + timedelta(days=7)).isoformat()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user