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.0.tar.gz (34.9 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.0-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hawkapi_pagination-0.1.0.tar.gz
  • Upload date:
  • Size: 34.9 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.0.tar.gz
Algorithm Hash digest
SHA256 a1743f89384271f39f045261a502014eddc85b65c365e3d2d90495e78b6095a1
MD5 367040bd9428f351f482f5f4ae526d93
BLAKE2b-256 080a69a51fe058aaa3b71f184714e8eca1ad69debfce8b4506abff9f9668b3c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for hawkapi_pagination-0.1.0.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.0-py3-none-any.whl.

File metadata

File hashes

Hashes for hawkapi_pagination-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 31bf347ec0573b84e36d051edc953d9fd952658a230a9f895c0674d46c6b7563
MD5 5e8d32e4b212c299d3f034adf0bb9ac2
BLAKE2b-256 3aa6dc7794a57f019966d331b956ef0842e0962c6ec3ddc0875834398948153f

See more details on using hashes here.

Provenance

The following attestation bundles were made for hawkapi_pagination-0.1.0-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