"""
byceps.database
~~~~~~~~~~~~~~~

Database utilities.

:Copyright: 2006-2018 Jochen Kupperschmidt
:License: Modified BSD, see LICENSE for details.
"""

import uuid

from flask_sqlalchemy import BaseQuery, Pagination, SQLAlchemy
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.orm import Query


db = SQLAlchemy(session_options={'autoflush': False})


db.JSONB = JSONB


class Uuid(UUID):

    def __init__(self):
        super().__init__(as_uuid=True)


db.Uuid = Uuid


def generate_uuid() -> uuid.UUID:
    """Generate a random UUID (Universally Unique IDentifier)."""
    return uuid.uuid4()


def paginate(query: Query, page: int, per_page: int) -> Pagination:
    """Return `per_page` items from page `page`."""
    if page < 1:
        page = 1

    if per_page < 1:
        raise ValueError('The number of items per page must be positive.')

    offset = (page - 1) * per_page

    items = query \
        .limit(per_page) \
        .offset(offset) \
        .all()

    item_count = len(items)
    if page == 1 and item_count < per_page:
        total = item_count
    else:
        total = query.order_by(None).count()

    # Intentionally pass no query object.
    return Pagination(None, page, per_page, total, items)

@@ -148,16 +148,53 @@
 s.%0A%22%22%22%0A%0A
+from typing import Callable, TypeVar%0A
 import u
@@ -351,16 +351,79 @@
 Query%0A%0A%0A
+F = TypeVar('F')%0AT = TypeVar('T')%0A%0AMapper = Callable%5B%5BF%5D, T%5D%0A%0A%0A
 db = SQL
@@ -767,16 +767,58 @@
 age: int
+,%0A             *, item_mapper: Mapper=None
 ) -%3E Pag
@@ -1244,16 +1244,16 @@
   else:%0A
-
         
@@ -1286,24 +1286,111 @@
 e).count()%0A%0A
+    if item_mapper is not None:%0A        items = %5Bitem_mapper(item) for item in items%5D%0A%0A
     # Intent

Allow to specify an item mapper function for pagination