6033967e6a
Ship Keystone auth, multi-service handlers (Yoga→Dalmatian), Compose/Helm packaging, API contract packs, and pytest/Pulumi coverage labs.
47 lines
1.3 KiB
Python
47 lines
1.3 KiB
Python
"""OpenStack-style limit/marker pagination helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Callable
|
|
|
|
from starlette.requests import Request
|
|
|
|
|
|
def parse_limit(request: Request, *, default: int = 0, maximum: int = 1000) -> int:
|
|
raw = request.query_params.get("limit")
|
|
if raw is None or raw == "":
|
|
return default
|
|
try:
|
|
value = int(raw)
|
|
except ValueError:
|
|
return default
|
|
if value <= 0:
|
|
return default
|
|
return min(value, maximum)
|
|
|
|
|
|
def paginate_rows(
|
|
rows: list[Any],
|
|
request: Request,
|
|
*,
|
|
id_attr: Callable[[Any], str],
|
|
default_limit: int = 0,
|
|
) -> tuple[list[Any], list[dict[str, str]]]:
|
|
"""Slice rows by marker/limit. Returns (page, link dicts for next)."""
|
|
|
|
marker = request.query_params.get("marker")
|
|
limit = parse_limit(request, default=default_limit)
|
|
start = 0
|
|
if marker:
|
|
for index, row in enumerate(rows):
|
|
if id_attr(row) == marker:
|
|
start = index + 1
|
|
break
|
|
page = rows[start:]
|
|
links: list[dict[str, str]] = []
|
|
if limit > 0 and len(page) > limit:
|
|
page = page[:limit]
|
|
last = page[-1]
|
|
links.append({"rel": "next", "href": f"?marker={id_attr(last)}&limit={limit}"})
|
|
return page, links
|