Skip to main content

Pagination helpers for HawkAPI — cursor + offset, Page[T] response model, SQLAlchemy integration

Project description

hawkapi-pagination

Pagination helpers for HawkAPI. Offset and cursor strategies. Page[T] / CursorPage[T] response envelopes. SQLAlchemy integration. In-memory iterable pagination.

Install

pip install hawkapi-pagination
pip install 'hawkapi-pagination[sqlalchemy]'   # adds SQLAlchemy + hawkapi-sqlalchemy helpers

Offset pagination

from hawkapi import Depends, HawkAPI
from hawkapi_sqlalchemy import get_session
from hawkapi_pagination import Page, OffsetParams, pagination_params, paginate_query
from sqlalchemy import select


@app.get("/items")
async def list_items(
    params: OffsetParams = Depends(pagination_params),
    session = Depends(get_session),
) -> Page[Item]:
    return await paginate_query(session, select(Item), params)

The route accepts ?page=N&size=M. Defaults: page=1, size=50, max_size=200. Out-of-range values are clamped (size > max_sizemax_size) or rejected (page < 1 raises 400).

Page[T] shape:

{ "items": [...], "total": 137, "page": 1, "size": 50, "pages": 3 }

Skipping the COUNT

For large tables where SELECT COUNT(*) is expensive:

page = await paginate_query(session, stmt, params, include_total=False)
# page.total == -1, page.pages == -1

Clients can detect "more pages" by comparing len(items) to size.

Cursor pagination

Cursor pagination is the right choice for large tables that change under you (offset pages skip/duplicate rows when items are inserted/deleted between requests). The cursor is an HMAC-signed opaque token bound to:

  • the endpoint path (replay across routes rejected),
  • a TTL (default 1 hour),
  • a direction (asc / desc).
from hawkapi_pagination import CursorPage, CursorParams, cursor_params, paginate_cursor


@app.get("/items")
async def list_items(
    params: CursorParams = Depends(cursor_params),
    session = Depends(get_session),
) -> CursorPage[Item]:
    return await paginate_cursor(
        session,
        select(Item),
        order_by=Item.id,         # MUST be unique + sortable (PK is the usual choice)
        params=params,
        cursor_secret="stable secret, ≥32 chars",
        endpoint="/items",
        direction="asc",
    )

CursorPage[T] shape:

{ "items": [...], "next_cursor": "eyJrI...", "prev_cursor": "" }

When next_cursor is "", there are no more pages. Send the cursor back as ?cursor=... for the next call.

In-memory iterables

from hawkapi_pagination import paginate_iterable


page = await paginate_iterable(some_list, params)
# Works with sync iterables AND async generators.

Security notes

  • Cursor signing — HMAC-SHA256 over the JSON payload + hmac.compare_digest for verification.
  • Endpoint binding — a cursor minted for /api/items cannot be used at /api/users. Always pass an endpoint string that is stable across requests for the same route.
  • TTL — default 1 hour. Override per route via ttl= to paginate_cursor.
  • max_size cap — every params class enforces it; clients cannot ask for an unbounded page. Default 200.
  • Negative-int guardpage < 1 and size < 1 raise ValueError (which HawkAPI surfaces as 400).

Development

git clone https://github.com/Hawk-API/hawkapi-pagination.git
cd hawkapi-pagination
uv sync --extra dev
uv run pytest -q
uv run ruff check . && uv run ruff format --check .
uv run pyright src/

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hawkapi_pagination-0.1.2.tar.gz (35.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hawkapi_pagination-0.1.2-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file hawkapi_pagination-0.1.2.tar.gz.

File metadata

  • Download URL: hawkapi_pagination-0.1.2.tar.gz
  • Upload date:
  • Size: 35.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hawkapi_pagination-0.1.2.tar.gz
Algorithm Hash digest
SHA256 b54b29a1c55b8f889ee33b369571d8b20917643476d3549b9545aa8fe7737224
MD5 5a1d6b3f2a442402628fca46d0d7e646
BLAKE2b-256 5bf896ffb43a1678ec7275f627ae755dc59b322a82af1e24e537e4dc3563e02e

See more details on using hashes here.

Provenance

The following attestation bundles were made for hawkapi_pagination-0.1.2.tar.gz:

Publisher: release.yml on Hawk-API/hawkapi-pagination

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hawkapi_pagination-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for hawkapi_pagination-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7e11f4018e5f8913eab19580d8973475de8dd065fdcf8c323b39bfb5a894486d
MD5 f766e52758c329cc3fb3e040c02d3caa
BLAKE2b-256 6152dd0c76614e38a047d2c6a72dab027872382e8a6b004738a207064646810a

See more details on using hashes here.

Provenance

The following attestation bundles were made for hawkapi_pagination-0.1.2-py3-none-any.whl:

Publisher: release.yml on Hawk-API/hawkapi-pagination

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page