Skip to content

release: 3.0.1 — spec sync 3.18.0 → 3.19.0 (#383)#384

Merged
TexasCoding merged 1 commit into
mainfrom
chore/spec-sync-383
May 26, 2026
Merged

release: 3.0.1 — spec sync 3.18.0 → 3.19.0 (#383)#384
TexasCoding merged 1 commit into
mainfrom
chore/spec-sync-383

Conversation

@TexasCoding

Copy link
Copy Markdown
Owner

Summary

OpenAPI spec sync from v3.18.0 → v3.19.0. Single additive request-side constraint upstream: GET /structured_targets gained maxItems: 2000 on the ids query param. Mirror it at the SDK boundary so an oversize filter fails fast with a clear ValueError instead of paying a network round trip for a 400.

No endpoint, channel, or response-model changes. Regenerated kalshi/_generated/models.py is byte-identical to the v3.18.0 output (request-param constraints don't surface in response models).

Spec checksums match the upstream snapshot from the spec-drift workflow:

  • specs/openapi.yaml: 5eaeca6bb64b2ff0aa4f63f9e13381da5a8f6d8f9b34328408499a0503a3085d
  • specs/asyncapi.yaml: 6ff8a7f34b74964838ed81518567c4ab650bafa82e1ab91eacffb352722e73f4 (unchanged)

Changes

  • kalshi/resources/structured_targets.py: new module-level _MAX_IDS = 2000 constant + _validate_ids() helper, wired into all four entry points (sync/async × list/list_all). Follows the existing live_data.batch(milestone_ids, _MAX_BATCH=100) and markets.bulk_*(tickers, _MAX_BULK=100) precedent.
  • tests/test_structured_targets.py: new TestIdsCap class — 5 tests covering oversize rejection on sync+async list/list_all, plus a 2000-boundary acceptance test (the spec maxItems cap is inclusive).
  • specs/openapi.yaml: synced (version bump + the 1-line maxItems: 2000 addition).
  • pyproject.toml: version = "3.0.1".
  • kalshi/__init__.py: __version__ = "3.0.1" (also corrects a pre-existing stale value of 2.6.0).
  • CHANGELOG.md: new ## 3.0.1 — 2026-05-26 section.
  • README.md + docs/index.md: coverage banners bumped to "OpenAPI v3.19.0".

Test plan

  • uv run pytest tests/ --ignore=tests/integration -q — unit (2959 passed, 3 skipped)
  • uv run ruff check . — lint clean
  • uv run mypy kalshi/ — strict clean
  • If touching live endpoints: uv run pytest tests/integration/ against demo — N/A (client-side validator only; no wire-protocol change)
  • If adding a new endpoint: registered in tests/_contract_support.py::METHOD_ENDPOINT_MAP — N/A (no new endpoint; structured_targets.list/list_all/get already mapped)

Notes for reviewers

  • The 2000 boundary is inclusive (matches spec maxItems semantics). Tested at exactly 2000 and 2001 entries.
  • Async list_all is intentionally a plain def returning an AsyncIterator, so _validate_ids fires synchronously at call time rather than on first iteration. Matches the existing _validate_max_pages placement in the same file.
  • _validate_ids is a small module-private helper rather than four inlined len(ids) > 2000 checks — same cost, one source of truth, one error message that callers can match against in their own tests.

Issue links

Closes #383

Single additive request-side constraint upstream: GET /structured_targets
gained `maxItems: 2000` on the `ids` query param. Mirrored at the SDK
boundary so an oversize filter fails fast with a clear `ValueError`
instead of paying a network round trip for a 400. No endpoint, channel,
or response-model changes; regenerated `kalshi/_generated/models.py` is
byte-identical to the v3.18.0 output.

Closes #383
@claude

claude Bot commented May 26, 2026

Copy link
Copy Markdown

Code Review — PR #384: spec sync 3.18.0 → 3.19.0

Overall this is a clean, minimal, well-scoped PR. The implementation follows existing project patterns correctly. A few small items below.


What the PR does

Syncs specs/openapi.yaml to v3.19.0. The only functional change upstream was maxItems: 2000 on the ids query param for GET /structured_targets. The SDK mirrors this at the call boundary via a new _validate_ids() helper, so oversize filters fail fast with a clear ValueError rather than a 400 round trip.


Issues

1. Multi-line comment block violates project style (structured_targets.py:22–26)

CLAUDE.md says: "Never write multi-line comment blocks — one short line max." The 3-line block on _MAX_IDS should be condensed:

# Spec v3.19.0: GET /structured_targets ids param gained maxItems: 2000.
_MAX_IDS = 2000

The why is clear from one line; the extra explanation repeats the PR description.

2. Boundary test is only on sync.list — minor coverage gap

test_list_allows_boundary exercises resource.list(ids=[...2000...]). Since _validate_ids is shared by all four entry points, a validator bug would be caught, but testing the boundary on async_resource.list_all too would be cheap and complete the matrix. This is especially relevant for async_resource.list_all since it's the one entry point where the call is sync-at-surface (plain def) and the eager-fire behavior is explicitly called out as intentional.

3. Inconsistent validation ordering between list and list_all

In sync/async list: _validate_ids_validate_limit.
In sync/async list_all: _validate_max_pages_validate_ids_validate_limit.

The list_all-specific _validate_max_pages naturally comes first, but _validate_ids should follow immediately after (before _validate_limit) to be consistent with list. It does — so this is fine functionally. Just noting the ordering for clarity.


Observations (non-blocking)

  • Stale __version__ corrected: kalshi/__init__.py had 2.6.0 while pyproject.toml was at 3.0.0. Good catch fixing it here, but worth adding a CI check (e.g., assert __version__ == importlib.metadata.version("kalshi-sdk")) to prevent drift going forward.

  • _validate_ids placement in list_all is correct: Firing the validator in the plain-def body (before the generator is resumed) rather than inside the generator ensures the ValueError surfaces at call time. The comment in test_async_list_all_rejects_oversize_ids explains this well.

  • No METHOD_ENDPOINT_MAP / drift test changes needed: Confirmed — this only adds a client-side constraint on an existing kwarg, not a new kwarg or endpoint.

  • test_list_allows_boundary mock: The @respx.mock + module-level respx.get(...) pattern is correct and consistent with other tests in this file.


Summary

Two actionable items:

  1. Collapse the 3-line comment on _MAX_IDS to one line (project style rule).
  2. Consider adding a boundary-acceptance test for async_resource.list_all to complete the matrix.

Everything else looks good. The implementation is minimal, the tests cover all four call paths for the rejection case, and the PR follows the live_data.batch / markets.bulk_* precedent cleanly.

@TexasCoding
TexasCoding merged commit 892943c into main May 26, 2026
5 checks passed
@TexasCoding
TexasCoding deleted the chore/spec-sync-383 branch May 26, 2026 02:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spec drift 2026-05-25: openapi 3.18.0 → 3.19.0

1 participant