Source code for reminix.client.utils.pagination

"""Pagination utilities for cursor-based pagination"""

from __future__ import annotations

from typing import AsyncGenerator, Awaitable, Callable, Generic, Optional, TypeVar

T = TypeVar("T")


[docs] class PaginatedResponse(Generic[T]): """Response from a paginated API endpoint"""
[docs] def __init__( self, data: list[T], next_cursor: Optional[str] = None, has_more: bool = False, ): """ Initialize a paginated response. Args: data: List of items in this page next_cursor: Cursor for the next page (if available) has_more: Whether there are more pages available """ self.data = data self.next_cursor = next_cursor self.has_more = has_more
[docs] async def paginate_all( fetch_page: Callable[[Optional[str]], Awaitable[PaginatedResponse[T]]], initial_cursor: Optional[str] = None, ) -> AsyncGenerator[T, None]: """ Iterator helper for auto-pagination. Automatically fetches all pages using cursor-based pagination. Args: fetch_page: Async function that fetches a page given an optional cursor initial_cursor: Optional initial cursor to start from Yields: Individual items from all pages Example:: async def fetch_events(cursor: Optional[str] = None): response = await client.request("GET", "/events", params={"cursor": cursor}) return PaginatedResponse( data=response["data"], next_cursor=response.get("nextCursor"), has_more=response.get("hasMore", False), ) async for event in paginate_all(fetch_events): print(event.id) """ cursor: Optional[str] = initial_cursor has_more = True while has_more: response = await fetch_page(cursor) for item in response.data: yield item cursor = response.next_cursor has_more = response.has_more and cursor is not None
[docs] async def collect_all( fetch_page: Callable[[Optional[str]], Awaitable[PaginatedResponse[T]]], initial_cursor: Optional[str] = None, ) -> list[T]: """ Collect all items from paginated endpoint into a list. Args: fetch_page: Async function that fetches a page given an optional cursor initial_cursor: Optional initial cursor to start from Returns: List of all items from all pages Example:: async def fetch_events(cursor: Optional[str] = None): response = await client.request("GET", "/events", params={"cursor": cursor}) return PaginatedResponse( data=response["data"], next_cursor=response.get("nextCursor"), has_more=response.get("hasMore", False), ) all_events = await collect_all(fetch_events) """ items: list[T] = [] async for item in paginate_all(fetch_page, initial_cursor): items.append(item) return items