Repository navigation
docs+polish: env-vars NameError, stale docs, limits default, WS perf, cancel idempotency, events default; populate_by_name on WS; AwareDatetime on REST - #234
Conversation
Code Review — PR #234 (Wave 2-C: docs polish + AwareDatetime + populate_by_name)Overall this is a clean, well-scoped PR. The three code changes (events default, Issues1. Missing async test coverage for Two new tests were added to
Both the sync and async 2. Any caller who constructs a REST response model directly with a naive This isn't necessarily wrong to ship, but it should be in 3.
Minor nits
This matches the existing pattern in the file (same import style at lines 813, 690), so it's internally consistent — just noting it's unusual. Not a blocker. Test fixture parametrization coverage for
What's good
SummaryTwo things to address before merge:
|
… default, WS perf section, cancel idempotency, events default; populate_by_name on WS models; AwareDatetime on REST
- docs/environment-variables.md: switch retry example to KalshiConfig.demo(timeout=...) so the snippet runs without an extra import.
- Remove stale docs/AUDIT-resource-params.md (v0.7.0-era) and drop from mkdocs not_in_nav.
- docs/migration.md: drop incorrect 'predecessor referenced in project README' clause.
- docs/configuration.md: limits default = None; add Performance cross-link to docs/websockets.md.
- docs/websockets.md: new Performance section covering msg rates, queue sizing, overflow strategy, orderbook_delta CPU cost, orjson loader (matches w2-a ws_json_loads/ws_json_dumps), single-threaded recv impl.
- docs/resources/{orders,communications,api-keys,order-groups}.md cancel/delete methods: document 404 idempotency contract with KalshiNotFoundError example.
- docs/concepts.md: new 'Datetime semantics' section explaining AwareDatetime on REST and bare datetime on WS.
- events.get (sync + async): default with_nested_markets=None (was False) so default calls no longer emit ?with_nested_markets=false.
- All kalshi/ws/models/* (except orderbook_delta.py, W2-A's scope): add populate_by_name=True to model_config so SDK-name kwargs work.
- kalshi/models/* (communications, events, exchange, historical, incentive_programs, markets, milestones, multivariate, orders, portfolio, series, structured_targets): datetime fields -> pydantic.AwareDatetime; rejects naive datetimes at construction.
Closes #222
Refs #221 (P2 items 3/4; W2-A finishes items 1/2/5)
Refs #224
fc00aec to
4555610
Compare
Code Review — PR #234: Wave 2-C docs/polish + AwareDatetime + populate_by_nameOverviewWave 2-C of the audit umbrella (#224). Three bundled categories:
Overall the PR is well-scoped and the intent is clear. A few issues below, two of which are worth addressing before merge. Issues🔴 Discrepancy: The PR description states:
Please verify and update the PR description accordingly. 🔴 Breaking change: The P2.4 section describes this as a model hardening item, but it is a breaking change for any user who constructs SDK models directly (e.g., in their own tests or application code). Before this PR: Order(... created_time=datetime.now()) # workedAfter: Order(... created_time=datetime.now()) # ValidationErrorThis needs to appear in 🟡 Behavior change: Changing 🟡 Missing async tests for the The two new tests ( 🟡
🟡 Test coverage gap for
Positives
SummaryTwo items to fix before merge: the |
…sTimestamp alias, Decimal NaN reject (#292) * fix(ws): AwareDatetime in user_orders/communications payloads; document market_lifecycle seconds unit WS payload models predated #234's REST AwareDatetime rollout, so they accepted naive RFC3339 strings that REST callers couldn't. Align the two by retyping the datetime fields on UserOrdersPayload (4 fields) and the communications payloads (5 fields) to pydantic.AwareDatetime — a string without an offset now raises ValidationError at parse rather than silently producing a tz-unaware datetime that breaks arithmetic against tz-aware peers in MarketPosition/Settlement. MarketLifecyclePayload's *_ts fields are intentionally left as bare int. The AsyncAPI spec example payload uses Unix **seconds** (e.g. open_ts: 1694635200, 2023-09-13), not ms — so the lack of the _ts_ms suffix carried by sibling channels is correct. Added a comment so readers stop wondering. * fix(models): V1 CreateOrderRequest Literals; document required-nullable response fields; UnixSecondsTimestamp alias - V1 CreateOrderRequest tightens side/action/time_in_force/self_trade_prevention_type from bare str to the same Literal aliases V2 uses (SideLiteral, ActionLiteral, TimeInForceLiteral, SelfTradePreventionTypeLiteral). V1 keeps its yes/no side vocabulary (V2 is bid/ask). Caller passing side='foo' now fails at construction, matching V2 — closes the deprecation-window drift before V1 sunset (~May 2026). - portfolio.MarketPosition / historical.Trade keep total_traded, position, count as 'T | None' without default=None. The OpenAPI spec marks the underlying wire keys (total_traded_dollars, position_fp, count_fp) as **required**, so omission must still raise ValidationError — only the observed JSON null is admitted. Added docstring notes explaining the intentional non-default so the audit doesn't re-flag them. - types.UnixSecondsTimestamp: Annotated[int, …] alias for int64 Unix-seconds wire timestamps. Internal type-aid only (not re-exported via kalshi.__init__). Applied to Balance.updated_ts, Deposit.created_ts/finalized_ts, Withdrawal.created_ts/finalized_ts so the int-vs-AwareDatetime split is greppable when balances/positions are read side-by-side. - Drift checker (tests/test_contracts.py) now classifies pydantic AwareDatetime/NaiveDatetime and ForwardRef('datetime') as kind='datetime', matching what those models actually validate at runtime. * fix(types): reject non-finite Decimal at parse/serialize boundary `f"{Decimal('NaN'):f}"` returns the literal string `"NaN"`, and `_coerce_decimal` previously short-circuited on the `isinstance(value, Decimal)` branch — a caller doing arithmetic that produced NaN and then constructing a `CreateOrderRequest(yes_price=that_nan)` would ship `"NaN"` straight to a real-money order placement endpoint. `_coerce_decimal` now computes the Decimal first, then `is_finite()`- guards it, raising `ValueError` on NaN/+Inf/-Inf. One branch protects every DollarDecimal / FixedPointCount / MultiplierDecimal field at both parse and serialize. Closes #270
…e Literal (#331, #353) (#365) `OrderbookDeltaPayload.ts` was missed by the v2.5 #270 WS AwareDatetime sweep that closed the v2.4 #234 REST gap. Widen it to `AwareDatetime | None` so naive RFC3339 strings on the highest-volume WS channel raise `ValidationError` rather than silently passing as `str`, matching `user_orders` and `communications`. Narrow every WS message envelope's `type` field from bare `str` to its channel-specific `Literal[...]` across `OrderbookSnapshotMessage`, `OrderbookDeltaMessage`, `TickerMessage`, `FillMessage`, `UserOrdersMessage`, `MarketLifecycleMessage`, and `CommunicationsMessage`. The default-value form keeps no-arg construction ergonomics but constructing an envelope with a mismatched `type` string now raises `ValidationError`. This also unlocks `pydantic.Discriminator("type")` for the dispatcher's union without a follow-up wire-format change. Five `tests/ws/test_models.py` fixtures sent `"type": "user_orders"` (plural, channel name) where the wire `type` value per the dispatcher table is `"user_order"` (singular). Those fixtures are corrected to match the dispatch table that real frames go through. Closes #331, #353
Wave 2-C of audit umbrella. 7 P3 docs items + 2 P2 model items.
Changes
KalshiConfig.demo(timeout=...)); deleted staledocs/AUDIT-resource-params.md; dropped stalekalshi_python_async'referenced in project README' claim;docs/configuration.mdlimitsdefault cell corrected toNone; newdocs/websockets.mdPerformance section (queue sizing, orjson example, recv-loop threading); cancel/delete idempotency notes on orders / communications / api-keys / order-groups docs;events.get(with_nested_markets: bool | None = None)(wasbool = False).populate_by_name=Trueadded to every WS payloadmodel_config(exceptorderbook_delta.py— W2-A's scope).datetime→pydantic.AwareDatetimeon REST response-model timestamp fields across 12 modules; new datetime-semantics note indocs/concepts.md.Closes #222
Refs #221 (W2-A lands items 1/2/5)
Refs #224