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.1.tar.gz (35.3 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.1-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hawkapi_pagination-0.1.1.tar.gz
  • Upload date:
  • Size: 35.3 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.1.tar.gz
Algorithm Hash digest
SHA256 1234e97f41e9af3f35cf36eceab1bee4e1bdf6daa01e8ab60836d14e9920b35a
MD5 967e260dd103f535ee9360ee2bcf9794
BLAKE2b-256 a2bca734852fb9386cc4411b0f2b7d0275b44a688797385a5c253566a4b55ed3

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for hawkapi_pagination-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1ee336580ade9cba82939292ff2e81a1f8d73157a778b74beff2977b1b1bdb19
MD5 e8fac33e2daec91f442a2b73935ec4a1
BLAKE2b-256 5ed265a2b0eea00cd13933cde58c26d12a4c5b24b5e5165d3383460a3292eb71

See more details on using hashes here.

Provenance

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