Skip to content

docs: fix resource-doc drift (live-data, portfolio, structured-targets) + LiveDataResource docstring - #358

Merged
TexasCoding merged 2 commits into
mainfrom
r3/W0-A
May 22, 2026
Merged

TexasCoding merged 2 commits into
mainfrom
r3/W0-A

Conversation

@TexasCoding

Copy link
Copy Markdown
Owner

Summary

Four documentation drift fixes against kalshi/resources/: three resource
reference pages were out-of-sync with the implementation they document, and
the LiveDataResource.get_typed docstring did not explain that the _typed
suffix refers to the legacy URL form, not Python typing.

Issues closed

Behavioral changes

None. Docs and docstring text only.

Tests

None — docs-only PR. ruff check and mypy pass on kalshi/resources/live_data.py.

Source

Round-3 independent audit closure plan, wave W0.

…s) + LiveDataResource docstring

Three resource reference pages had drifted from their implementations,
and the LiveDataResource.get_typed docstring did not explain that the
_typed suffix refers to the legacy URL form rather than to Python
typing — readers scanning autocomplete were likely to pick get_typed
over get for the wrong reason.

docs/resources/live-data.md: corrected three quick-reference endpoint
paths to include the /milestone segment and the /batch suffix, and
fixed the batch() snippet to iterate the returned list[LiveData]
directly (the prior .live_data attribute access raised AttributeError
on first use).

docs/resources/portfolio.md: removed the stale warning claiming
positions_all() does not exist — it shipped in v2.4 (#269) on both
sync and async resources. The page now shows the iterator usage and
lifts the event_positions caveat from the method docstring, keeping
the manual cursor loop as the documented fallback for callers that
need the event view.

docs/resources/structured-targets.md: rewrote the 404 paragraph to
match reality — the resource calls plain _get() and 404 propagates
as KalshiNotFoundError; the StructuredTarget | None return reflects
the spec-optional envelope field (200 with structured_target=null),
not a 404 coalesce. The snippet now uses try/except with the rare
soft-not-found branch.

kalshi/resources/live_data.py: expanded the get_typed docstring on
both sync and async classes to state up front that get_typed and get
return the same LiveData with the same annotations, and that the
only difference is the URL form. No rename — that would be breaking.

Closes #318, #319, #320, #336
@TexasCoding TexasCoding added the documentation Improvements or additions to documentation label May 22, 2026
@claude

claude Bot commented May 22, 2026

Copy link
Copy Markdown

Code Review — PR #358: docs: fix resource-doc drift

Summary: Docs-only PR fixing four documentation/docstring drift issues. No behavioral changes.


Factual Accuracy (verified against implementation)

live-data.md ✅

  • Endpoint paths corrected: /live_data/milestone/{milestone_id}, /live_data/batch, /live_data/milestone/{milestone_id}/game_stats all match kalshi/resources/live_data.py exactly.
  • Batch snippet now iterates the returned list[LiveData] directly — correct. batch() returns GetLiveDatasResponse.model_validate(data).live_datas, a bare list, not a response object with a .live_data attribute.

portfolio.md ✅

  • positions_all() exists at portfolio.py:105 — stale "does not exist" claim correctly removed.
  • event_positions omission rationale lifted verbatim from the method's docstring (lines 119–123) — accurate.
  • Severity downgrade from !!! warning → !!! note is appropriate: the original warning was about absent functionality that now exists.

structured-targets.md ✅

  • _base_client.py:88-89 maps 404 → KalshiNotFoundError (raised, not caught). The new doc accurately reflects this.
  • GetStructuredTargetResponse.structured_target: StructuredTarget | None = None confirms None is only possible on a 200 with a null field.

live_data.py docstrings ✅

  • Both sync (get_typed at line ~48) and async (get_typed at line ~142) updated consistently.
  • Clarification about _typed suffix is accurate and eliminates a genuine autocomplete trap.

Suggestions

Minor — structured-targets.md snippet verbosity:
The three-outcome try/except/else/if/else structure is technically correct but produces three nesting levels for a rare edge case. An alternative that reads slightly more flatly:

from kalshi.errors import KalshiNotFoundError

try:
    t = client.structured_targets.get("st_abc")
except KalshiNotFoundError:
    print("not found")
    t = None

if t is None:
    print("soft-not-found (200 with null body)")
else:
    print(t.name, t.target_type)

Not a blocker — the current form is unambiguous and the comment explains the nested check. Either way works.

Minor — portfolio.md version pin:
The note says positions_all() "shipped in v2.4". Confirm this is accurate in the CHANGELOG before merging; if the version is wrong it becomes its own drift issue. (Assuming it's right given the PR description references #269.)


Testing

No tests needed — docs and docstring text only. The PR description correctly notes ruff check and mypy pass on the modified .py file.


Overall: Approve. All factual claims verified against the implementation. The corrections are accurate, the rationale in the portfolio note matches the source docstring exactly, and the get_typed clarification eliminates a real user confusion point. The minor verbosity note in the structured-targets snippet is optional.

@TexasCoding

Copy link
Copy Markdown
Owner Author

Round-2 review addressed in cb6680e:

Deferring as non-blocking: structured-targets.md try/except snippet verbosity — current form is unambiguous, the bot agreed either reading works.

@claude

claude Bot commented May 22, 2026

Copy link
Copy Markdown

Code Review

Summary: Docs-only PR fixing four documentation drift issues across three resource reference pages and one docstring. All changes verified against the live implementation.


Accuracy check: all four changes verified correct

docs/resources/live-data.md

  • All three corrected endpoint paths match the implementation exactly:
    • GET /live_data/milestone/{milestone_id} → live_data.py:37
    • GET /live_data/batch → live_data.py:103
    • GET /live_data/milestone/{milestone_id}/game_stats → live_data.py:111
  • The batch snippet fix (iterating entries directly instead of resp.live_data) is correct — batch() returns list[LiveData], not a wrapper object.

docs/resources/portfolio.md

  • positions_all() exists (portfolio.py:105, portfolio.py:327), confirmed in CHANGELOG.md under 2.5.0 — 2026-05-21.
  • The event_positions exclusion rationale in the new admonition is lifted verbatim from the method's own docstring — accurate and internally consistent.
  • Changing !!! warning → !!! note is the right call; the old warning implied something was broken, not just non-obvious.

docs/resources/structured-targets.md

  • _base_client.py:88-89 confirms a 404 raises KalshiNotFoundError, not None.
  • structured_targets.py:92 confirms None comes only from GetStructuredTargetResponse.model_validate(data).structured_target on a 200 response — exactly what the new text says.

kalshi/resources/live_data.py

  • Identical expansion applied to both sync (line 48) and async (line 142) get_typed — consistent with the repo's dual-transport pattern. Content accurately describes both returning LiveData and the URL-form distinction.

Issues

PR description contains a version error

The PR body says: "removed the stale claim that positions_all() does not exist (it shipped in v2.4 via #269)"

The CHANGELOG and the diff itself both say v2.5.0 — #269 landed in the 2.5.0 release, not v2.4. The code change is correct; the PR description is not. This is cosmetic (the description doesn't land in the repo), but worth correcting for traceability.


Minor suggestions

structured-targets.md snippet complexity

The new snippet nests a if t is None inside an else clause, with a comment noting this is "rare." This is technically correct, but for a reference doc the extra branch may confuse readers more than it helps — the comment itself says it's a server-side oddity. Consider simplifying to just the try/except pattern with a prose callout for the None edge case, rather than making callers write two-level branching:

# In practice, None is only returned if the server responds 200 with
# {"structured_target": null} — extremely rare. Most callers can ignore it.
try:
    t = client.structured_targets.get("st_abc")
except KalshiNotFoundError:
    print("not found")
else:
    print(t.name, t.target_type)  # t is None only on server soft-not-found

This is a minor readability nit — the current version is not wrong.


Verdict

All four corrections are accurate and improve the documentation. No behavioral changes. The PR description version error is worth a follow-up note but doesn't block merge. No test changes needed (docs only).

Approve with minor notes.

@TexasCoding
TexasCoding merged commit 183c2ad into main May 22, 2026
5 checks passed
@TexasCoding
TexasCoding deleted the r3/W0-A branch May 22, 2026 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

1 participant