Repository navigation
Conversation
export_reviews read one page and left the continuation loop to the caller. iter_export_pages follows X-Proofline-Export-Next-Cursor on both clients with the same dataset, window, format and grouping, bounded by max_pages (1..1000, default 100). A repeated or empty cursor is refused as invalid pagination, a settled horizon that changes between pages as an invalid response, and an exhausted bound raises pagination-limit instead of stopping silently. A cursor resumes an interrupted export. Export windows accept timezone-aware datetimes as well as RFC3339 strings; naive datetimes raise ValueError before any request, as does an empty cursor on either method. Both facades build the export request through one helper, so dataset, format, cursor and window validation live in one place, and ExportTime joins the public exports. The README keeps the single-page example and documents the iterator below it.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Who this helps
Anyone pulling the
reviews,findings,finding_outcomes,finding_validationsor
spenddatasets into a warehouse or a report.export_reviewsreads one page andthe README asked callers to loop on
next_cursorby hand with the same dataset,window, format and grouping. The TypeScript SDK and the CLI leave that loop to the
user as well, and the CLI README warns that partial output must never be treated as
complete. The Python SDK already owns this shape for reviews through
iter_reviews,so exports now get the same treatment.
What changed
iter_export_pagesonProoflineClientandAsyncProoflineClientyieldsExportPageobjects until the server omitsX-Proofline-Export-Next-Cursor.max_pages(1..1000, default 100). Exhausting the bound with a cursorleft raises
urn:proofline:sdk:pagination-limitinstead of stopping silently.urn:proofline:sdk:invalid-pagination.A settled horizon that changes between pages raises
urn:proofline:sdk:invalid-responsebefore that page is yielded, so rows from twosnapshots are never mixed.
cursorresumes an interrupted export. An empty cursor is aValueErroron bothexport_reviewsand the iterator, before any request.from_timeandto_timeaccept timezone-awaredatetimevalues as well asRFC3339 strings on both methods. Naive datetimes raise
ValueErrorbefore anyrequest.
ExportTimeis exported for annotations.export_requesthelper inproofline/exports.py, so dataset, format, cursor and window validation live inone place.
export_reviewsexample and documents theiterator's behaviour with its own example below it, without describing arguments,
like the rest of the file.
scripts/contracts.pyallows the new helper name.Decisions
ExportPagekeeps the page text and settled horizon, which arow stream would drop; rows are
page.rowsaway. One method keeps the publicsurface and the contracts allow-list small.
max_pagesis the only bound. Server pages are capped at 5000 rows or 1000groups and the transport caps a response at 8 MiB, so a page count bounds bytes
and rows; a row bound would have to raise mid-page.
group_bycheck. The server is the authorityon both.
malformed responses, so callers need no new vocabulary. Horizon drift carries
status 0 like the other SDK-detected malformed responses. The shared
pagination-limit detail now reads "Pagination reached the configured bound." for
both pagers; no test or document depended on the old wording.
exports.py, pagination policy inclient.py. Timeserialization and request building sit next to
decode_export. The bound, theseen cursors and the frozen horizon live in one
_ExportPagerstate object, sothe sync and async drivers are the same short loop and the policy is written
once. It shares the review pager's error constructors. New code reads top-down:
each function is followed by the functions it calls, so the iterator precedes
the single-page method it drives, the request builder precedes the time
serializer, and the pager closes the module after the classes that drive it.
Verification
python3 scripts/check.pypasses end to end: client regeneration check, operationand vocabulary contracts, ruff lint and format, mypy under the project
configuration, pytest (95 tests), wheel and sdist build, and the install smoke
test for both artifacts.
finding_outcomespages with the query repeated and the cursor URL-encoded onpage two, a single page, a repeated cursor, an empty cursor from the server, a
resume cursor that repeats, horizon drift, the
max_pagesbound, a 404 on pagetwo after the first page was yielded, aware datetimes serialized to
Zonexport_reviewsdirectly, andValueErrorwith zero requests for a bad bound,an empty cursor, a naive
from_timeorto_time, an unknown dataset and anunknown format on both methods.
inverted bounds, a yield moved ahead of the horizon check, a forgotten resume
cursor, parameters no longer sent) is killed in full by these tests, with
sync-only and async-only mutants failing only their own mode.