release: bump version to 0.3.0

- Refactor Redis backend connection handling and pool management
- Update algorithm implementations with improved type annotations
- Enhance config loader validation with stricter Pydantic schemas
- Improve decorator and middleware error handling
- Expand example scripts with better docstrings and usage patterns
- Add new 00_basic_usage.py example for quick start
- Reorganize examples directory structure
- Fix type annotation inconsistencies across core modules
- Update dependencies in pyproject.toml
This commit is contained in:
2026-03-17 20:55:38 +00:00
parent 492410614f
commit f3453cb0fc
51 changed files with 6507 additions and 166 deletions

View File

@@ -19,7 +19,7 @@ class RedisBackend(Backend):
def __init__(
self,
client: Redis[bytes],
client: Redis,
*,
key_prefix: str = "fastapi_traffic",
) -> None:
@@ -57,7 +57,8 @@ class RedisBackend(Backend):
msg = "redis package is required for RedisBackend. Install with: pip install redis"
raise ImportError(msg) from e
client: Redis[bytes] = Redis.from_url(url, **kwargs)
client: Redis = Redis.from_url(url, **kwargs) # pyright: ignore[reportUnknownMemberType] # fmt: skip
# note: No type stubs for redis-py, so we ignore the type errors
instance = cls(client, key_prefix=key_prefix)
instance._owns_client = True
return instance
@@ -119,7 +120,11 @@ class RedisBackend(Backend):
pattern = f"{self._key_prefix}:*"
cursor: int = 0
while True:
cursor, keys = await self._client.scan(cursor, match=pattern, count=100)
cursor, keys = (
await self._client.scan( # pyright: ignore[reportUnknownMemberType]
cursor, match=pattern, count=100
)
)
if keys:
await self._client.delete(*keys)
if cursor == 0:
@@ -134,11 +139,7 @@ class RedisBackend(Backend):
async def ping(self) -> bool:
"""Check if Redis is reachable."""
try:
await self._client.ping()
return True
except Exception:
return False
return await self._client.ping() # pyright: ignore[reportUnknownMemberType, reportGeneralTypeIssues, reportUnknownVariableType, reportReturnType] # fmt: skip
async def get_stats(self) -> dict[str, Any]:
"""Get statistics about the rate limit storage."""
@@ -147,12 +148,20 @@ class RedisBackend(Backend):
cursor: int = 0
count = 0
while True:
cursor, keys = await self._client.scan(cursor, match=pattern, count=100)
cursor, keys = (
await self._client.scan( # pyright: ignore[reportUnknownMemberType]
cursor, match=pattern, count=100
)
)
count += len(keys)
if cursor == 0:
break
info = await self._client.info("memory")
info: dict[str, Any] = (
await self._client.info( # pyright: ignore[reportUnknownMemberType]
"memory"
)
)
return {
"total_keys": count,
"used_memory": info.get("used_memory_human", "unknown"),