"""Keyset paging for lists that load as you scroll (#5211): a cursor round-trips, a mangled one starts over, and a page says whether another follows.""" from datetime import datetime, timezone from types import SimpleNamespace as NS from sqlalchemy import Column, DateTime, MetaData, String, Table, select from sqlalchemy.dialects import postgresql from steward.core.paging import cursor, keyset, next_page, parse_cursor AT = datetime(2026, 10, 7, 3, 0, 5, 123456, tzinfo=timezone.utc) def test_a_cursor_round_trips_and_a_mangled_one_starts_over(): assert parse_cursor(cursor(AT, "0190ab|cd")) == (AT, "0190ab|cd") # an id may hold the separator assert parse_cursor(None) is None and parse_cursor("") is None assert parse_cursor("not a cursor") is None and parse_cursor("yesterday|x") is None def test_a_page_says_whether_another_follows(): rows = [NS(at=AT, id=str(i)) for i in range(5)] page, after = next_page(rows, lambda r: (r.at, r.id), size=3) assert [r.id for r in page] == ["0", "1", "2"] and after == cursor(AT, "2") page, after = next_page(rows[:3], lambda r: (r.at, r.id), size=3) assert len(page) == 3 and after is None # exactly a page: the end def test_the_query_reads_one_row_past_the_page_older_than_the_cursor(): t = Table("t", MetaData(), Column("at", DateTime(timezone=True)), Column("id", String)) first = str(keyset(select(t), t.c.at, t.c.id, None, size=10).compile(dialect=postgresql.dialect())) assert "WHERE" not in first and "ORDER BY t.at DESC, t.id DESC" in first and "LIMIT" in first later = str(keyset(select(t), t.c.at, t.c.id, cursor(AT, "x"), size=10) .compile(dialect=postgresql.dialect())) assert "WHERE (t.at, t.id) < (" in later