Source code for pinecone.models.pagination

"""Pagination types for lazy iteration over paginated API results."""

from __future__ import annotations

from collections.abc import AsyncGenerator, Awaitable, Callable, Generator
from typing import Generic, TypeVar

T = TypeVar("T")


[docs] class Page(Generic[T]): """A single page of results from a paginated API."""
[docs] def __init__( self, *, items: list[T], pagination_token: str | None, ) -> None: self.items = items self.pagination_token = pagination_token
@property def has_more(self) -> bool: """True if more pages are available.""" return self.pagination_token is not None def __repr__(self) -> str: return f"Page(items={self.items!r}, pagination_token={self.pagination_token!r})"
[docs] class Paginator(Generic[T]): """Lazy iterator over paginated API results (sync). Fetches pages on demand. Supports item-level iteration, page-level access via :meth:`pages`, bulk collection via :meth:`to_list`, and resumption via the :attr:`pagination_token` property. Args: fetch_page: Callable that takes an optional pagination token and returns a :class:`Page`. initial_token: Token to start pagination from. ``None`` starts from the beginning. limit: Maximum number of items to yield across all pages. ``None`` yields all items. Examples: .. code-block:: python paginator = pc.assistants.list() for assistant in paginator: print(assistant.name) Collect all results into a list: .. code-block:: python all_assistants = pc.assistants.list().to_list() """
[docs] def __init__( self, *, fetch_page: Callable[[str | None], Page[T]], initial_token: str | None = None, limit: int | None = None, ) -> None: self._fetch_page = fetch_page self._initial_token = initial_token self._limit = limit self._pagination_token: str | None = initial_token
@property def pagination_token(self) -> str | None: """Token for the next page, or ``None`` if all pages have been fetched.""" return self._pagination_token def __iter__(self) -> Generator[T, None, None]: count = 0 token: str | None = self._initial_token while True: page = self._fetch_page(token) self._pagination_token = page.pagination_token for item in page.items: if self._limit is not None and count >= self._limit: return yield item count += 1 if page.pagination_token is None: return token = page.pagination_token
[docs] def pages(self) -> Generator[Page[T], None, None]: """Iterate over pages rather than individual items. When ``limit`` is set, yields full pages until the remaining budget is exhausted, then yields a truncated final page and stops. Returns: :class:`~collections.abc.Generator` yielding :class:`Page` objects. Each page has an ``items`` list and an optional ``pagination_token``. Examples: .. code-block:: python for page in pc.assistants.list().pages(): for assistant in page.items: print(assistant.name) """ count = 0 token: str | None = self._initial_token while True: page = self._fetch_page(token) self._pagination_token = page.pagination_token if self._limit is not None: remaining = self._limit - count if remaining <= 0: return if len(page.items) > remaining: yield Page(items=page.items[:remaining], pagination_token=None) return count += len(page.items) yield page if page.pagination_token is None: return token = page.pagination_token
[docs] def to_list(self) -> list[T]: """Fetch all items across all pages into a list. Returns: list of all items. Examples: .. code-block:: python all_assistants = pc.assistants.list().to_list() """ return list(self)
def __repr__(self) -> str: has_more = self._pagination_token is not None parts = [f"has_more={has_more!r}"] if self._limit is not None: parts.append(f"limit={self._limit!r}") return f"Paginator({', '.join(parts)})"
[docs] class AsyncPaginator(Generic[T]): """Async lazy iterator over paginated API results. Fetches pages on demand. Supports item-level async iteration, page-level access via :meth:`pages`, bulk collection via :meth:`to_list`, and resumption via the :attr:`pagination_token` property. Args: fetch_page: Async callable that takes an optional pagination token and returns a :class:`Page`. initial_token: Token to start pagination from. ``None`` starts from the beginning. limit: Maximum number of items to yield across all pages. ``None`` yields all items. Examples: .. code-block:: python paginator = async_pc.assistants.list() async for assistant in paginator: print(assistant.name) Collect all results into a list: .. code-block:: python paginator = async_pc.assistants.list() all_assistants = await paginator.to_list() """
[docs] def __init__( self, *, fetch_page: Callable[[str | None], Awaitable[Page[T]]], initial_token: str | None = None, limit: int | None = None, ) -> None: self._fetch_page = fetch_page self._initial_token = initial_token self._limit = limit self._pagination_token: str | None = initial_token
@property def pagination_token(self) -> str | None: """Token for the next page, or ``None`` if all pages have been fetched.""" return self._pagination_token async def __aiter__(self) -> AsyncGenerator[T, None]: count = 0 token: str | None = self._initial_token while True: page = await self._fetch_page(token) self._pagination_token = page.pagination_token for item in page.items: if self._limit is not None and count >= self._limit: return yield item count += 1 if page.pagination_token is None: return token = page.pagination_token
[docs] async def pages(self) -> AsyncGenerator[Page[T], None]: """Iterate over pages rather than individual items. When ``limit`` is set, yields full pages until the remaining budget is exhausted, then yields a truncated final page and stops. Returns: :class:`~collections.abc.AsyncGenerator` yielding :class:`Page` objects. Each page has an ``items`` list and an optional ``pagination_token``. Examples: .. code-block:: python async for page in async_pc.assistants.list().pages(): for assistant in page.items: print(assistant.name) """ count = 0 token: str | None = self._initial_token while True: page = await self._fetch_page(token) self._pagination_token = page.pagination_token if self._limit is not None: remaining = self._limit - count if remaining <= 0: return if len(page.items) > remaining: yield Page(items=page.items[:remaining], pagination_token=None) return count += len(page.items) yield page if page.pagination_token is None: return token = page.pagination_token
[docs] async def to_list(self) -> list[T]: """Fetch all items across all pages into a list. Returns: list of all items. Examples: .. code-block:: python paginator = async_pc.assistants.list() all_assistants = await paginator.to_list() """ return [item async for item in self]
def __repr__(self) -> str: has_more = self._pagination_token is not None parts = [f"has_more={has_more!r}"] if self._limit is not None: parts.append(f"limit={self._limit!r}") return f"AsyncPaginator({', '.join(parts)})"