Repository navigation
Remove the None presets and checks around Stage 12 span and operation blocks - #965
Merged
Merged
Conversation
…scopes The Stage 12 Modal functions in v2_app.py and the segment runner in stage12_runtime/fanout.py set a variable to None before a span or operation block and check it after the block. The next commit removes those presets and checks, which only satisfied Pyright before policyengine-observability 3.0.4. These tests run every block involved and pass on the current code. - The existing v2_app tests run the four functions with a recording runtime whose operation is a generator context manager. Two new parametrized tests run them with the observability runtime the services build (OpenTelemetry disabled), through its real operation scope: each function returns its calculation's result, and an error raised in the block reaches the caller unchanged, never as the "returned no result" RuntimeError. - The segment runner already had tests for its dispatch and wait blocks succeeding and failing. A new test makes the merge block fail, and four tests run the runner with the real runtime: a successful run, and an error raised in each of the dispatch, wait and merge blocks, which reaches the caller unchanged. - conftest.py gains a real_observability_runtime fixture that builds that runtime, with Google Cloud logging unset, and shuts it down afterwards. The dispatch-failure setup moves into a helper the old and new dispatch tests share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… blocks Before policyengine-observability 3.0.4, Pyright read the span and operation scopes as possibly suppressing the exception raised in their block. #712 therefore set each value a block assigns to None before the block and raised a RuntimeError after it when the value was still None. 3.0.4 annotates the scopes' __exit__ and __aexit__ as returning Literal[False], and they return False on every path, so the block either assigns its value or its exception reaches the caller. None of the assigned values can be None either: - v2_app.py: run_single_simulation_segment_us returns calculate_segment(...).model_dump(mode="python"), a dict; run_single_simulation_us and run_single_simulation_uk return run_single_simulation(...), and coordinate_report returns coordinate_report(...), both typed dict[str, Any], and every path of each returns a dict or raises. Each function now returns from inside its operation block (ruff's RET504 rejects assigning and then returning); the operation still ends, and the runtime still shuts down, before the function returns. - fanout.py: the dispatched call is the FunctionCall that modal 1.4.2's Function.spawn creates and returns on every path (it raises for a generator function, and the segment function is not one), so _require_call, the only check of it, is removed with the preset; _collect returns a list or raises; and merge_segment_results returns a SimulationCalculation, now from inside the merge span. The removed RuntimeErrors could not be raised, so behaviour is unchanged and there is no failing test to write: the tests added in the previous commit, which run each block through the real runtime scopes, pass before and after. Pyright still reports no errors in the executor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 #964
Removes the
Nonepresets andNonechecks that #712 put around Stage 12 span and operation blocks so Pyright, reading policyengine-observability's scopes as possibly suppressing an exception, would not report their values as possibly unbound. Since #959, every package uses 3.0.4, whose scopes are annotated as returningLiteral[False]from__exit__and__aexit__and returnFalseon every path, so each block either assigns its value or its exception reaches the caller.What is removed, and why each check could not fail
src/modal/v2_app.pyrun_single_simulation_segment_usresult = None, "Stage 12 segment calculation returned no result"calculate_segment(...).model_dump(mode="python"), a dictsrc/modal/v2_app.pyrun_single_simulation_usresult = None, "Stage 12 US simulation returned no result"run_single_simulation(...), typeddict[str, Any]; every path returns a dict or raisessrc/modal/v2_app.pyrun_single_simulation_ukresult = None, "Stage 12 UK simulation returned no result"src/modal/v2_app.pycoordinate_reportresult = None, "Stage 12 report coordinator returned no result"stage12_runtime.coordinate_report(...), typeddict[str, Any]; every path returns a dict or raisesstage12_runtime/fanout.pyStage12SegmentRunner.run, dispatch spancall = Noneand_require_call, "Stage 12 segment dispatch returned no call"FunctionCallthat modal 1.4.2'sFunction.spawncreates and returns on every path (it raises for a generator function, and the segment function is not one)stage12_runtime/fanout.pyStage12SegmentRunner.run, wait spanpayloads: list[object] | None = None, "Stage 12 segment wait returned no payloads"_collect(...), typedlist[object]; returns a list or raisesstage12_runtime/fanout.pyStage12SegmentRunner.run, merge spanmerged: SimulationCalculation | None = None, "Stage 12 segment merge returned no calculation"merge_segment_results(...), which returns aSimulationCalculationThe four Modal functions and the merge now return from inside their block, because ruff's RET504 rejects assigning a value only to return it. The scope still ends, and each Modal function's runtime still shuts down, before the function returns.
A search of the executor, gateway and entrypoint
srcdirectories for any value set toNonebefore a span, operation or otherwithblock and used after it found one other:setup_gcp_credentialssetscreds_file = Nonebefore anExitStackblock that leaves it unassigned when credentials are already configured or absent. That check is reachable and stays.Tests
Removing unreachable code changes no behaviour, so there is no failing test to write first. The first commit adds tests that run every block involved, and they pass before and after the removal:
RuntimeError;Checks
uv run --frozen pytest tests/inprojects/policyengine-simulation-executor: 1889 passed, 22 skipped, 3 deselected at both commits.python -m scripts.rules pyright --sync projects/policyengine-simulation-executor: no errors at both commits.ruff format --check projects/*/src libs/*/srcandruff check .pass.python scripts/run_quality_guards.py,python -m scripts.rules guard --base-ref origin/mainandpython -m unittest discover -s scripts/rules/tests -t .pass;python -m scripts.rules renderleaves no diff.🤖 Generated with Claude Code