def paginate(items, page=0, max_per_page=10):
    if not page:
        page = 0
    start = page * max_per_page
    stop = start + max_per_page

    count = None
    if hasattr(items, '__len__'):
        count = len(items)
        if count and start >= count:
            from trac.util.translation import _
            raise TracError(_("Page %(page)s is out of range.", page=page))

    try: # Try slicing first for better performance
        retval = items[start:stop]
    except TypeError: # Slicing not supported, so iterate through the whole list
        retval = []
        idx = -1 # Needed if items = []
        for idx, item in enumerate(items):
            if start <= idx < stop:
                retval.append(item)
            # If we already obtained the total number of items via `len()`,
            # we can break out of the loop as soon as we've got the last item
            # for the requested page
            if count is not None and idx >= stop:
                break
        if count is None:
            count = idx + 1

    return retval, count, int(ceil(float(count) / max_per_page))
Simple generic pagination.
dataset/ETHPy150Open edgewall/trac/trac/util/presentation.py/paginate