Source code for openapi.pagination.pagination
import os
from dataclasses import dataclass, fields
from typing import (
Dict,
List,
NamedTuple,
Optional,
Sequence,
Tuple,
Type,
TypeVar,
Union,
)
from aiohttp import web
from yarl import URL
from openapi.json import dumps
MAX_PAGINATION_LIMIT: int = int(os.environ.get("MAX_PAGINATION_LIMIT") or 100)
DEF_PAGINATION_LIMIT: int = int(os.environ.get("DEF_PAGINATION_LIMIT") or 50)
T = TypeVar("T")
def from_filters_and_dataclass(data_class: Type[T], data: dict) -> T:
params = {}
for field in fields(data_class):
if field.name in data:
params[field.name] = data.pop(field.name)
return data_class(**params)
def fields_no_sign(fields: Sequence[str]) -> Tuple[str, ...]:
return tuple(field[1:] if field.startswith("-") else field for field in fields)
def fields_flip_sign(fields: Sequence[str]) -> Tuple[str, ...]:
return tuple(flip_field_sign(field) for field in fields)
def flip_field_sign(field: str) -> str:
return field[1:] if field.startswith("-") else f"-{field}"
[docs]class PaginatedData(NamedTuple):
"""Named tuple containing paginated data and methods for retrieving
links to previous or next data in the pagination
"""
url: URL
"""Base url"""
data: list
"""Paginated list of data"""
pagination: Pagination
"""Pagination dataclass which created the data"""
total: Optional[int] = None
"""Total number of records (supported by limit/offset pagination only)"""
[docs] def json_response(self, headers: Optional[Dict[str, str]] = None, **kwargs):
"""Create a JSON response with link header"""
headers = headers or {}
links = self.header_links()
if links:
headers["Link"] = links
if self.total is not None:
headers["X-Total-Count"] = str(self.total)
kwargs.setdefault("dumps", dumps)
return web.json_response(
self.pagination.get_data(self.data), headers=headers, **kwargs
)