pypaginate

pypaginate — Universal pagination toolkit for Python.

Input type determines output type (Elysia-style inference):

from pypaginate import paginate, OffsetParams

page = paginate(users, OffsetParams(page=1, limit=20))
page.total  # int — auto-inferred as OffsetPage

from pypaginate import CursorParams

page = await paginate(query, CursorParams(after="abc"), backend=backend)
page.next_cursor  # str | None — auto-inferred as CursorPage

Submodules

Exceptions

ConfigurationError

Raised when pagination configuration is invalid.

FilterError

Raised when filtering operations fail.

FilterValidationError

Raised when filter specification validation fails.

PaginationError

Base exception for all pypaginate errors.

SearchError

Raised when search operations fail.

SearchQueryError

Raised when search query processing fails.

SortError

Raised when sort operations fail.

ValidationError

Raised when generic validation fails.

Classes

CursorPage

Cursor pagination result.

CursorParams

Cursor pagination input.

Dataset

An in-memory dataset queried by one-call filter + sort + paginate.

FilterGroup

Composite filter for nested AND/OR expressions.

FilterLogic

Logical operator for combining filter conditions.

FilterSpec

Declarative filter specification.

FuzzyMode

Fuzzy matching strategy for search.

NullsPosition

Where to place NULL values in sorted results.

OffsetPage

Offset pagination result.

OffsetParams

Offset pagination input.

OverflowStrategy

How to handle page numbers exceeding total pages.

SearchFieldMode

How to match search terms against fields.

SearchSpec

Declarative search specification.

SortDirection

Sort direction for ordering.

SortSpec

Declarative sort specification.

Functions

And(→ FilterGroup)

Create an AND group of filter conditions.

Or(→ FilterGroup)

Create an OR group of filter conditions.

paginate(…)

Universal pagination entry point.

Package Contents

exception pypaginate.ConfigurationError(message: str, *, details: dict[str, Any] | None = None)

Bases: PaginationError

Raised when pagination configuration is invalid.

exception pypaginate.FilterError(message: str, *, field: str | None = None, details: dict[str, Any] | None = None)

Bases: PaginationError

Raised when filtering operations fail.

exception pypaginate.FilterValidationError(message: str, *, field: str | None = None, details: dict[str, Any] | None = None)

Bases: FilterError

Raised when filter specification validation fails.

exception pypaginate.PaginationError

Bases: Exception

Base exception for all pypaginate errors.

exception pypaginate.SearchError(message: str, *, details: dict[str, Any] | None = None)

Bases: PaginationError

Raised when search operations fail.

exception pypaginate.SearchQueryError(message: str, *, details: dict[str, Any] | None = None)

Bases: SearchError

Raised when search query processing fails.

exception pypaginate.SortError(message: str, *, details: dict[str, Any] | None = None)

Bases: PaginationError

Raised when sort operations fail.

exception pypaginate.ValidationError(message: str, *, field: str | None = None, details: dict[str, Any] | None = None)

Bases: PaginationError

Raised when generic validation fails.

class pypaginate.CursorPage

Bases: BasePage[ItemT]

Cursor pagination result.

No total, no page — those are offset-only concepts.

classmethod create(items: list[ItemT], params: pypaginate.domain.params.CursorParams, *, next_cursor: str | None = None, previous_cursor: str | None = None) Any

Build from cursor pagination results.

Parameters:
  • items – Items for this page.

  • params – Cursor parameters used.

  • next_cursor – Cursor for the next page.

  • previous_cursor – Cursor for the previous page.

Returns:

CursorPage or FastCursorPage (if msgspec installed).

class pypaginate.CursorParams(/, **data: Any)

Bases: BaseParams

Cursor pagination input.

Example:

CursorParams(limit=20, after="abc123")
CursorParams(limit=20, before="xyz789")
class pypaginate.Dataset(items: collections.abc.Sequence[ItemT])

Bases: Generic[ItemT]

An in-memory dataset queried by one-call filter + sort + paginate.

paginate(params: pypaginate.domain.params.OffsetParams, *, filters: collections.abc.Sequence[pypaginate.domain.specs.FilterSpec] | None = None, sorting: collections.abc.Sequence[pypaginate.domain.specs.SortSpec] | None = None, search: pypaginate.domain.specs.SearchSpec | None = None) pypaginate.domain.pages.OffsetPage[ItemT]

Filter, then sort, then offset-paginate; return an OffsetPage.

Uses the native one-call pipeline when available and the query is natively supported (no search); otherwise the pure-Python backends. Both paths produce the same page. Multiple filters are combined with AND (mirroring the in-memory filter backend); grouped filters are not accepted here — use the backend API for those.

class pypaginate.FilterGroup(/, **data: Any)

Bases: pydantic.BaseModel

Composite filter for nested AND/OR expressions.

Use And() and Or() builder functions instead of constructing directly.

Example:

And(
    Or(FilterSpec(field="a", value=1), FilterSpec(field="b", value=2)),
    Or(FilterSpec(field="c", value=3), FilterSpec(field="d", value=4)),
)
# = (a=1 OR b=2) AND (c=3 OR d=4)
model_config

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class pypaginate.FilterLogic(*args, **kwds)

Bases: enum.Enum

Logical operator for combining filter conditions.

class pypaginate.FilterSpec(/, **data: Any)

Bases: pydantic.BaseModel

Declarative filter specification.

Example:

FilterSpec(field="age", operator="gte", value=18)
FilterSpec(field="name", operator="contains", value="john")
model_config

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class pypaginate.FuzzyMode(*args, **kwds)

Bases: enum.Enum

Fuzzy matching strategy for search.

class pypaginate.NullsPosition(*args, **kwds)

Bases: enum.Enum

Where to place NULL values in sorted results.

class pypaginate.OffsetPage

Bases: BasePage[ItemT]

Offset pagination result.

All fields are non-optional — clean serialization.

classmethod create(items: list[ItemT], total: int, params: pypaginate.domain.params.OffsetParams) Any

Build from offset pagination results.

Parameters:
  • items – Items for this page.

  • total – Total item count across all pages.

  • params – Offset parameters used.

Returns:

OffsetPage or FastOffsetPage (if msgspec installed).

class pypaginate.OffsetParams(/, **data: Any)

Bases: BaseParams

Offset pagination input.

Example:

OffsetParams(page=2, limit=20)
clamp(total: int) Self

Clamp page number to valid bounds.

Parameters:

total – Total number of items available.

Returns:

New params clamped to valid range, or self if valid.

property offset: int

Zero-based offset for database queries.

class pypaginate.OverflowStrategy(*args, **kwds)

Bases: enum.Enum

How to handle page numbers exceeding total pages.

class pypaginate.SearchFieldMode(*args, **kwds)

Bases: enum.Enum

How to match search terms against fields.

class pypaginate.SearchSpec(/, **data: Any)

Bases: pydantic.BaseModel

Declarative search specification.

Example:

SearchSpec(query="john doe", fields=("name", "email"))
SearchSpec(query="jhn", fields=("name",), fuzzy=FuzzyMode.FUZZY)
SearchSpec(query="alice", fields=("name", "bio"), weights={"name": 2.0})
model_config

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

class pypaginate.SortDirection(*args, **kwds)

Bases: enum.Enum

Sort direction for ordering.

class pypaginate.SortSpec(/, **data: Any)

Bases: pydantic.BaseModel

Declarative sort specification.

Example:

SortSpec(field="name")
SortSpec(field="created_at", direction=SortDirection.DESC)
model_config

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

pypaginate.And(*conditions: FilterSpec | FilterGroup) FilterGroup

Create an AND group of filter conditions.

pypaginate.Or(*conditions: FilterSpec | FilterGroup) FilterGroup

Create an OR group of filter conditions.

pypaginate.paginate(source: collections.abc.Sequence[ItemT], params: pypaginate.domain.params.OffsetParams, *, overflow: pypaginate.domain.enums.OverflowStrategy = ...) pypaginate.domain.pages.OffsetPage[ItemT]
pypaginate.paginate(source: object, params: pypaginate.domain.params.OffsetParams, *, backend: pypaginate.domain.protocols.SyncPaginationBackend[ItemT], overflow: pypaginate.domain.enums.OverflowStrategy = ...) pypaginate.domain.pages.OffsetPage[ItemT]
pypaginate.paginate(source: object, params: pypaginate.domain.params.OffsetParams, *, backend: pypaginate.domain.protocols.PaginationBackend[ItemT], overflow: pypaginate.domain.enums.OverflowStrategy = ...) collections.abc.Awaitable[pypaginate.domain.pages.OffsetPage[ItemT]]
pypaginate.paginate(source: object, params: pypaginate.domain.params.CursorParams, *, backend: pypaginate.domain.protocols.CursorBackend[ItemT]) collections.abc.Awaitable[pypaginate.domain.pages.CursorPage[ItemT]]

Universal pagination entry point.

The return type is automatically inferred from the params type: - OffsetParamsOffsetPage - CursorParamsCursorPage

Parameters:
  • source – Data source (Sequence for in-memory, or query).

  • params – OffsetParams or CursorParams.

  • backend – Optional backend. Auto-detected from source if None.

  • overflow – How to handle out-of-range pages (offset only).

Returns:

OffsetPage for sync, Awaitable[OffsetPage|CursorPage] for async.

Raises:
  • TypeError – If source is not a Sequence and no backend given.

  • TypeError – If cursor params used with a sync backend.