Skip to content

Commit 0666938

Browse files
TexasCodingclaude
andcommitted
review(#135 pass 3): fix stale docstring + add async unbounded test
Per third-pass bot review on PR #135: - _validate_max_pages docstring: "None (use default cap)" was stale after dropping the 1000-page default. Now reads "None (unbounded — iterates until the server returns no cursor)". - TestMaxPagesNoneIsUnbounded: added test_async_iterates_past_1000_pages as the async counterpart to test_sync_iterates_past_1000_pages. Prevents the cap regression from silently re-appearing in only one of the two code paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ff41a18 commit 0666938

2 files changed

Lines changed: 27 additions & 3 deletions

File tree

kalshi/resources/_base.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ def _check_request_exclusive(request: Any, **kwargs: Any) -> None:
4747
def _validate_max_pages(max_pages: int | None) -> None:
4848
"""Reject ``max_pages <= 0`` at the public ``*_all()`` boundary.
4949
50-
``None`` (use default cap) and positive integers are valid. Zero or
51-
negative would silently produce an empty iterator deep inside
52-
``_list_all``; surfacing the misuse here is friendlier.
50+
``None`` (unbounded — iterates until the server returns no cursor) and
51+
positive integers are valid. Zero or negative would silently produce an
52+
empty iterator deep inside ``_list_all``; surfacing the misuse here is
53+
friendlier.
5354
"""
5455
if max_pages is not None and max_pages <= 0:
5556
raise ValueError(

tests/test_base_helpers.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,3 +438,26 @@ def responder(request: httpx.Request) -> httpx.Response:
438438
resource = SyncResource(SyncTransport(test_auth, test_config))
439439
items = list(resource._list_all("/things", _Item, "items"))
440440
assert len(items) == total, f"Expected {total} items, got {len(items)} (cap leaked?)"
441+
442+
@respx.mock
443+
@pytest.mark.asyncio
444+
async def test_async_iterates_past_1000_pages(
445+
self, test_auth: KalshiAuth, test_config: KalshiConfig,
446+
) -> None:
447+
# Async counterpart — same 1010-page proof, prevents the regression
448+
# from silently re-appearing in only one of the two code paths.
449+
total = 1010
450+
call_counter = {"n": 0}
451+
452+
def responder(request: httpx.Request) -> httpx.Response:
453+
call_counter["n"] += 1
454+
n = call_counter["n"]
455+
cursor = str(n) if n < total else ""
456+
return httpx.Response(
457+
200, json={"items": [{"id": f"i{n}"}], "cursor": cursor},
458+
)
459+
460+
respx.get("https://test.kalshi.com/trade-api/v2/things").mock(side_effect=responder)
461+
resource = AsyncResource(AsyncTransport(test_auth, test_config))
462+
items = [item async for item in resource._list_all("/things", _Item, "items")]
463+
assert len(items) == total, f"Expected {total} items, got {len(items)} (cap leaked?)"

0 commit comments

Comments
 (0)