Source code for pybdl.api.utils.rate_limiter_decorators

"""Decorators for rate-limiting functions."""

import functools
from collections.abc import Awaitable, Callable
from typing import Any, TypeVar

from pybdl.api.utils.rate_limiter_async import AsyncRateLimiter
from pybdl.api.utils.rate_limiter_sync import RateLimiter

T = TypeVar("T")
R = TypeVar("R")


[docs] def rate_limit( quotas: dict[int, int | tuple], is_registered: bool, **limiter_kwargs: Any, ) -> Callable[[Callable[..., T]], Callable[..., T]]: """ Decorator for rate-limiting functions. Args: quotas: Dictionary of {period_seconds: limit or (anon_limit, reg_limit)}. is_registered: Whether the user is registered (affects quota). ``**limiter_kwargs``: Additional arguments to pass to RateLimiter (e.g., max_delay, raise_on_limit). Returns: Decorator function. Example:: @rate_limit(quotas={60: 100}, is_registered=True, max_delay=30) def fetch_dataset(dataset_id): return api.get(f"/datasets/{dataset_id}") """ limiter = RateLimiter(quotas, is_registered, **limiter_kwargs) def decorator(func: Callable[..., T]) -> Callable[..., T]: @functools.wraps(func) def wrapper(*args: Any, **kwargs: Any) -> T: limiter.acquire() return func(*args, **kwargs) return wrapper return decorator
[docs] def async_rate_limit( quotas: dict[int, int | tuple], is_registered: bool, **limiter_kwargs: Any, ) -> Callable[[Callable[..., Awaitable[T]]], Callable[..., Awaitable[T]]]: """ Decorator for rate-limiting async functions. Args: quotas: Dictionary of {period_seconds: limit or (anon_limit, reg_limit)}. is_registered: Whether the user is registered (affects quota). ``**limiter_kwargs``: Additional arguments to pass to AsyncRateLimiter (e.g., max_delay, raise_on_limit). Returns: Decorator function. Example:: @async_rate_limit(quotas={60: 100}, is_registered=True) async def async_fetch_dataset(dataset_id): return await api.get(f"/datasets/{dataset_id}") """ limiter = AsyncRateLimiter(quotas, is_registered, **limiter_kwargs) def decorator(func: Callable[..., Awaitable[T]]) -> Callable[..., Awaitable[T]]: @functools.wraps(func) async def wrapper(*args: Any, **kwargs: Any) -> T: await limiter.acquire() return await func(*args, **kwargs) return wrapper return decorator