Repository navigation
Conversation
anth-volk
added this pull request to stack #867
October 21, 2026 15:50
This was referenced Oct 21, 2026
anth-volk
force-pushed
the
pyright-apis-integ
branch
from
October 21, 2026 16:21
5a3235e to
aae9888
Compare
anth-volk
force-pushed
the
pyright-apis-integ
branch
2 times, most recently
from
October 21, 2026 16:59
78deee9 to
66759a5
Compare
anth-volk
force-pushed
the
pyright-apis-integ
branch
2 times, most recently
from
October 21, 2026 21:37
354d6dd to
317d690
Compare
anth-volk
force-pushed
the
pyright-apis-integ
branch
from
October 21, 2026 22:33
317d690 to
7bad005
Compare
anth-volk
force-pushed
the
pyright-apis-integ
branch
from
October 22, 2026 13:22
7bad005 to
695214c
Compare
The generated sync_detailed of each endpoint that declares bearer authentication accepts only an AuthenticatedClient, but the integration tests pass a plain Client against local services, which run without authentication (4 Pyright errors). endpoint_calls has one function per such endpoint (submit and poll, for annual and budget-window runs). Each takes either client and sends exactly what sync_detailed sends: the endpoint module's _get_kwargs, through the client's own httpx client, parsed by its _build_response. The headers the tests send don't change. A new test records the requests through an httpx mock transport and checks it: with an AuthenticatedClient each function sends sync_detailed's exact request, and with a plain Client the same request without Authorization. The two polling tests that stubbed sync_detailed now stub endpoint_calls. apis-integ now has no Pyright errors, and its baseline is empty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As for the gateway and executor: the bad fixture, the integration tests' real report from main at ceb30e1, now fails with every error new and no baseline, and the good fixture is a clean report recorded from the fixed tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The integration tests have no Pyright errors, so sim.quality.pyright-apis-integ moves from ratcheted to enforced and its empty baseline goes. Every package's Pyright rule is now enforced; the type-checking skill keeps the baseline mechanism for a future upgrade or package that needs one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With every Pyright rule enforced, the type-checking skill describes ratcheting one again for a future upgrade or package. It now says that needs a [rule.downgrade] reason, which the guard requires for a move from enforced to ratcheted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
pyright-apis-integ
branch
from
October 22, 2026 17:16
695214c to
7bd5fb9
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #876
Same-Repository Draft PR Check
PolicyEngine/policyengine-sim-api, not a personal fork.Summary
Top of the Pyright stack, on top of #875. Fixes apis-integ's 4 Pyright errors without changing a request the integration tests send, then makes
sim.quality.pyright-apis-integenforced and deletes the last Pyright baseline. After this PR every package's Pyright rule is enforced with zero errors.This PR is separate from #875 on purpose. It depends on the generated client's underscore-prefixed functions (see "Trade-off"). If that's not acceptable, dropping this PR leaves the stack consistent, with apis-integ ratcheted at 4.
The errors
The generated client types the four endpoints that declare bearer authentication (
POST /simulate/economy/comparison,GET /jobs/{job_id},POST /simulate/economy/budget-windowandGET /budget-window-jobs/{batch_job_id}) assync_detailed(*, client: AuthenticatedClient, ...). The tests'clientfixture isClient | AuthenticatedClient: a plainClient, with noAuthorizationheader, when no access token is configured, as in CI against local services.The fix
tests/simulation/endpoint_calls.pyhas one function per such endpoint. Each takes either client and runs exactly the three statements of the generatedsync_detailed:_get_kwargsand_build_responsealready acceptAuthenticatedClient | Client, so nothing is cast or suppressed. The call sites inconftest.pyandtest_calculate.pyuse these functions. The two polling tests that replacedsync_detailedwith a stub now replaceendpoint_calls.job_status.test_endpoint_calls.py(8 tests) records each request through an httpx mock transport:AuthenticatedClient, each function sends the same method, URL, headers and body as the endpoint's ownsync_detailed;Client, the same request withoutAuthorization.So the headers the tests send don't change, and a generator change that broke the equivalence would fail that test.
Trade-off, and the other options
_get_kwargsand_build_responseare private to the generated endpoint modules. openapi-python-client's templates have emitted them for a long time, but a generator upgrade could rename them;test_endpoint_calls.pywould then fail. The alternatives I considered:AuthenticatedClient, with an empty token when none is configuredAuthorization: Bearer(empty token) to local services that run without authenticationAuthenticatedClientthat adds no headercastor# pyright: ignoreCommits (red, then green)
Call the authenticated endpoints with either client in the integ tests. Red: with the baseline emptied, the check reported the 4 errors. Green: 0 errors. The apis-integ tests that need no running services pass (25), including the 8 new request-recording tests. The rest need the local services, as in
test-integration.Prove the apis-integ Pyright rule as an enforced rule. Red: the rewritten proof failed against the ratchet fixtures. Green: the bad fixture is the real pre-fix report; the good fixture is a clean report recorded from the fixed tests.
Enforce Pyright for apis-integ, and drop the last Pyright baseline. Red: deleting the baseline made the guard fail with
baseline file ... does not exist. Green: guard, rules-tool tests andpython -m scripts.rules pyrightpass, with all eight packages enforced.Say that ratcheting a Pyright rule again needs a downgrade reason. Docs only, from the review.
Suppressions added
None. (
test_calculate.pyalready usedcast("Client", object())in two unit tests; that's unchanged.)Real bugs found
None.
Self-review
review-codeon this PR's diff, run by a separate agent, found no bugs. It confirmed against the generated modules that the plain-Clientpath sends the requestsync_detailedsent before. Findings:test-integration. Kept, as set out above under "Trade-off". This PR exists separately so it can be dropped.[rule.downgrade] reason, which Run Pyright in CI for every package, in its own locked environment #864's guard requires (commit 4). With no ratcheted rules,--write-baselinenow says there is nothing to write (Run Pyright in CI for every package, in its own locked environment #864).Environment variables
No CI, image or deployment changes. The integration tests read
SIMULATION_INTEG_TEST_*settings as before; nothing new.Testing
python -m scripts.rules pyright: all eight packages pass, all enforced.This PR is above the bottom of the stack, so its CI runs only
CI complete, which fails by design until the PRs below merge.🤖 Generated with Claude Code