Skip to content

Fix the simulation gateway's Pyright errors - #866

Merged
anth-volk merged 3 commits into
mainfrom
pyright-gateway
Oct 21, 2026
Merged

anth-volk merged 3 commits into
mainfrom
pyright-gateway

Conversation

@anth-volk

@anth-volk anth-volk commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #865

Same-Repository Draft PR Check

  • This PR is a draft.
  • This PR is from a branch in PolicyEngine/policyengine-sim-api, not a personal fork.

Summary

Second in the Pyright stack, on top of #864. Fixes all 81 of the simulation gateway's Pyright errors without changing behaviour. The gateway's baseline (rules/baselines/pyright-gateway.txt) goes from 81 entries to 0; the stack's top PR deletes it and makes sim.quality.pyright-gateway enforced.

Commit Errors fixed Baseline after
Open the gateway's spans with the typed span scope 72 9
Type the gateway's batch status and routing state as they are 7 2
Narrow the gateway smoke app's routes to Starlette Routes 2 0

What changed

  • Spans. Each of the 35 with runtime.span(...) blocks in endpoints.py becomes with scopes.span(runtime, ...) (Run Pyright in CI for every package, in its own locked environment #864's helper). It returns the same scope object, typed as not suppressing exceptions, so Pyright no longer reports the 66 variables assigned inside a span as possibly unbound, or the 6 handlers that return from inside one as missing a return.
  • Budget-window submit status. The response passed seed_state.status (any batch status) where BudgetWindowBatchSubmitResponse.status accepts only "submitted". A new batch's seed state is always created submitted (create_initial_batch_state), and storing it (put_batch_job_seed) doesn't change it, so the response now says "submitted".
  • Routing state. _version_map_from_state was annotated with a VersionRoutingState TypedDict, but its callers pass the plain dict read from the routing-state Modal Dict, and the helpers it calls (_routing_state_routes, _routing_state_latest) take a dict and check each field's type. It now takes a dict, and the TypedDict, which nothing else used, is removed.
  • Smoke app. hasattr(route, "methods") doesn't narrow Starlette's BaseRoute, so Pyright rejected route.methods and route.path. The smoke now keeps routes that are Starlette Routes (FastAPI's APIRoute is one) with methods. For the gateway app this is the same 12 METHOD path routes as before (checked by building the app both ways).

Commits (red, then green)

Each red is the Pyright check against the baseline with that commit's entries removed, run on the code before the fix.

  1. Red: 72 errors the shrunk baseline doesn't list. Green: check passes with 9; gateway tests 260 passed.
  2. Red: the 7 argument-type errors. Green: check passes with 2; gateway tests 260 passed, including the OpenAPI golden-file test.
  3. Red: the 2 smoke-app errors. Green: check passes with 0; same 12 routes.

Suppressions added

None.

Real bugs found

None.

Self-review

review-code on this PR's diff, run by a separate agent, found no bugs. Code-quality findings, all declined:

  • Type the routing-state helpers as Mapping[str, object] instead of dict. Declined: _version_map_from_state now takes the same dict the module's _routing_state_* helpers already take. Changing them all is a separate refactor of the module's routing-state typing.
  • The gateway baseline stays as an empty file under a ratcheted rule. Declined: the stack's plan deletes the baselines and enforces the rules in one PR, Enforce Pyright for the simulation gateway and executor #875. The guard still blocks any increase in the meantime.
  • No unit test covers the smoke app's route filter. Declined: the Modal image smoke runs it. I checked locally that the old and new filters give the same 12 routes for the real app.

Environment variables

No CI, image or deployment configuration changes. smoke_app.py runs in the Modal image smoke; it now imports starlette.routing.Route at module level, which the gateway environment and image already install with FastAPI. It reads no new environment variables.

Testing

  • python -m scripts.rules pyright projects/policyengine-simulation-gateway: passes with 0 errors.
  • Gateway unit tests: 260 passed.
  • Quality guards and rendered rules views: pass.
  • Executor unit tests, which exercise the gateway app: 1552 passed, 22 skipped.

This PR is above the bottom of a stack, so its CI runs only CI complete, which fails by design until #864 merges and this PR is rebased onto main.

🤖 Generated with Claude Code

anth-volk and others added 3 commits October 22, 2026 00:33
Each `with runtime.span(...)` in the gateway's endpoints becomes
`with scopes.span(runtime, ...)`, which returns the same scope typed as
not suppressing exceptions. Pyright no longer reports the variables
assigned inside a span as possibly unbound (66 errors), or the handlers
that return from inside one as missing a return (6). The gateway's
baseline drops from 81 entries to 9.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two argument types Pyright rejected, with no behaviour change:

- The budget-window submit response passed the seed state's status,
  typed as any batch status, where the response accepts only
  "submitted". A new batch's seed state is always created submitted and
  storing it doesn't change it, so the response now says "submitted".
- `_version_map_from_state` took a VersionRoutingState TypedDict, but
  callers pass the plain dict read from the routing-state Modal Dict, and
  the helpers it calls take a dict and check each field's type. It now
  takes a dict, and the TypedDict, used nowhere else, is gone.

The gateway's baseline drops from 9 entries to 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The in-image smoke listed `METHOD path` for every route with a
`methods` attribute, which Pyright can't narrow from BaseRoute, so it
rejected `route.methods` and `route.path`. It now keeps the routes that
are Starlette Routes (FastAPI's APIRoute is one) with methods. For the
gateway app that is the same 12 routes as before.

The gateway's baseline is now empty: no Pyright errors remain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@anth-volk
anth-volk marked this pull request as ready for review October 21, 2026 21:36
@anth-volk
anth-volk requested a review from a team as a code owner October 21, 2026 21:36
@anth-volk
anth-volk merged commit 5ec2fee into main Oct 21, 2026
22 checks passed
@anth-volk
anth-volk deleted the pyright-gateway branch October 21, 2026 21:36
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.

Fix the simulation gateway's 81 Pyright errors

1 participant