fix: spec drift — settlement_sources on Event + lifecycle strike fields (#451)#452
Conversation
The live v3.21.0 spec gained fields after #449 synced it, redding the nightly strict contract run (#451): - EventData.settlement_sources (spec-required, nullable) → Event.settlement_sources, typed NullableList[SettlementSource] so a JSON null coerces to []. Mirrors EventMetadata/Series. SettlementSource moved above Event so the forward ref resolves under `from __future__ import annotations`. event_dict() fixture gains the required key. - marketLifecycleV2Payload.{strike_type,cap_strike,custom_strike} → MarketLifecyclePayload (all optional; present only on metadata_updated). specs/openapi.yaml: the freshly-fetched live spec also *transiently* dropped CreateOrder / BatchCreateOrders / AmendOrder (104→101 ops), which would red the body-drift tests for those endpoints. That is an upstream publishing glitch, not a real API change — so the committed openapi was kept at its known-good 104-op state and settlement_sources added surgically to EventData. specs/asyncapi.yaml was synced normally (additive strike fields + WS error-doc refinements; no dropped channels). Verified: ruff clean, mypy clean, strict nightly contract suite (-W error::UserWarning) green, full unit suite 4315 passed / 3 skipped. Closes #451 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Code Review — fix/spec-drift-451Summary: Minimal, well-targeted spec-drift fix. Two new field groups are added faithfully against the live v3.21.0/asyncapi specs, contract tests pass (676 / 4315), and the decision to hold the openapi.yaml at the known-good 104-operation state rather than import a transient breakage is the right call and well-documented. ✅ What's done well
|
Addresses the PR #452 review (claude[bot]): add unit coverage for the new fields rather than relying on the contract suite alone. - TestEventSettlementSources: null -> [] coercion, typed SettlementSource list parsing, and required-key enforcement. - TestMarketLifecycleStrikeFields: the asyncapi 'between' example (strike_type + floor_strike + cap_strike + custom_strike) and the default-None path on non-metadata events. - Tighten the Event.settlement_sources comment: only Series mirrors the nullable shape; EventMetadata's field is a plain list (not nullable). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the review — addressed in 1577e81. ① Missing unit tests — fixed. Added two test classes:
③ Comment precision — fixed. Reworded to "same nullable shape as ② No default = de-facto breaking — acknowledged. ④ Nit (comment length) — kept the 4-liner. The "between/greater/less → floor/cap interpretation" detail earns its space, and you flagged it as non-blocking. Local: ruff + mypy clean, new tests green, affected suites ( |
Code Review: PR 452 — Spec drift fix (settlement_sources + lifecycle strike fields)OverviewClean, targeted spec drift fix. Changes are minimal, well-explained, and consistent with existing SDK conventions. The PR description is thorough about the upstream publishing glitch; not importing the transiently-broken spec state was the right call. Positives
Issues1. Breaking change not flagged in changelog (medium)
Suggestion: add 2.
3. The spec documents 4.
Summary
Recommend merging after addressing item 1. Items 2–4 can be tracked as follow-up issues. Reviewed by Claude Sonnet 4.6 |
Minor bump covering the two changes merged since 4.1.0: - #452 (closes #451): additive response fields reconciling in-place upstream spec drift — Event.settlement_sources and WS MarketLifecyclePayload strike_type / cap_strike / custom_strike. - #448: cryptography dependency ceiling widened <49 -> <50. Additive-minor per the 4.1.0 precedent (MarginPosition.subaccount, also a spec-required response field, shipped in a minor with the same direct- construction note). No breaking changes. Bumps pyproject.toml + kalshi.__version__ to 4.2.0 and adds the CHANGELOG entry. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Resolves the nightly strict contract failures in #451. The live OpenAPI/AsyncAPI specs gained fields after #449 synced them, redding
pytest tests/test_contracts.py -W error::UserWarning:EventDatasettlement_sources(required, nullable)kalshi.models.events.EventmarketLifecycleV2Payloadstrike_type,cap_strike,custom_strikekalshi.ws.models.market_lifecycle.MarketLifecyclePayloadChanges
Event.settlement_sources→NullableList[SettlementSource]. Spec marks itrequired+nullable: true, so the SDK field is required (passestest_required_drift) but coerces a JSONnull→[](matchesEventMetadata.settlement_sources/Series.settlement_sources).SettlementSourcewas moved aboveEventso the forward reference resolves underfrom __future__ import annotations. The centralevent_dict()fixture gains the now-required key.MarketLifecyclePayloadgainsstrike_type: str | None,cap_strike: DollarDecimal | None,custom_strike: dict | None— all optional (present only onmetadata_updated), mirroring the existingfloor_strikehandling.Spec handling note⚠️
The freshly-fetched live
openapi.yamlalso transiently droppedCreateOrder/BatchCreateOrders/AmendOrder(104 → 101 operations) — this reds the body-drift tests for those endpoints (KeyError: path '…/amend' not found). That is an upstream publishing glitch, not a real API change, so I did not import it. The committedopenapi.yamlwas kept at its known-good 104-operation state andsettlement_sourceswas added toEventDatasurgically.asyncapi.yamlwas synced normally (additive strike fields + WS error-doc refinements; no dropped channels).If a future nightly still reds on the order-endpoint drop, that's a separate upstream-flap issue (the drift workflow may want to tolerate transient operation removals).
Verification
uv run ruff check .— cleanuv run mypy kalshi/— cleanuv run pytest tests/test_contracts.py -W error::UserWarning(nightly strict) — 676 passeduv run pytest tests/ --ignore=tests/integration— 4315 passed, 3 skippedCloses #451
🤖 Generated with Claude Code