Repository navigation
Split the gateway endpoints and their tests under the file-length limit - #930
Merged
Merged
Conversation
2 tasks done
anth-volk
force-pushed
the
file-length-split-gateway-endpoints
branch
from
October 27, 2026 13:45
1781f17 to
7aa565f
Compare
anth-volk
force-pushed
the
file-length-split-gateway-endpoints
branch
from
October 27, 2026 13:55
7aa565f to
1781f17
Compare
The gateway's endpoints.py (1,454 lines) and test_endpoints.py (1,801 lines) were over the file-length limits. The code moves, unchanged, into: - routes_common.py: the router, the logger, and the request and observability-header helpers every route module uses - route_resolution.py: resolving a request's app from the active routing state - modal_routing.py: Modal reads of job metadata, the routing state and the legacy version Dicts, and resolve_route - bundle_payloads.py: the release bundle a route serves - job_creation_routes.py, job_status_routes.py and version_routes.py: the routes, each with the helpers only it uses endpoints.py re-exports every public name. Importing the three route modules registers their routes on the router in the original order, so the OpenAPI document is byte-for-byte the same, golden file included. The routes keep logging under the policyengine_simulation_gateway.endpoints logger, now named explicitly in routes_common.py. Private helpers another module now uses are public, with a docstring where they had none: active_routing_state, bind_observability_id, build_policyengine_bundle, bundle_identities, bundle_payload, is_modal_job_not_found, job_metadata_store, observability_headers, optional_modal_dict, policyengine_version_from_app_name, record_not_found, resolve_from_active_state, routing_state_bundles, routing_state_latest, routing_state_routes, and _runtime as observability_runtime. The tests move to test_endpoints.py, test_simulation_submission.py, test_simulation_datasets.py, test_simulation_job_status.py and test_budget_window_endpoints.py, with the shared expected responses in fixtures/gateway_responses.py; all 78 keep their names and bodies. Patches now target the module that looks each name up: the Modal fakes in the gateway fixture and the executor's budget-window fixture patch modal in each of the four modules that read it, and the executor's SPM and job-progress tests patch the route module the request runs through. The import isolation fixture also clears the new modules, so importing endpoints re-runs all of the endpoint code as before. The file-length baseline drops both files (count 12 to 10). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
file-length-split-gateway-endpoints
branch
from
October 27, 2026 14:48
1781f17 to
17f9fb0
Compare
anth-volk
marked this pull request as ready for review
October 27, 2026 16:16
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 #929
Same-Repository Draft PR Check
PolicyEngine/policyengine-sim-api, not a personal fork.Summary
Third of nine stacked PRs; it builds on #927. It splits the gateway's
endpoints.pyandtest_endpoints.pywithout changing behaviour, and removes both from the file-length baseline (count 12 to 10).Source:
src/policyengine_simulation_gateway/endpoints.py(1,454 lines)The code moves verbatim. A script compared every top-level statement of the old module with the new modules: all 64 appear exactly once, unchanged apart from the renames below and the logger line, in their original order.
routes_common.pyroute_resolution.pyRouteResolution,SUPPORTED_ROUTE_KINDS, and resolving a request's app from the active routing statemodal_routing.pyresolve_routeandget_app_namebundle_payloads.pyjob_creation_routes.pyPOST /simulate/economy/comparisonand the budget-window submission, with the helpers only they usejob_status_routes.pyGET /jobs/{job_id}and the budget-window status route, with the helpers only they useversion_routes.py/versions,/versions/{kind},/healthand/pingendpoints.py__all__policyengine_simulation_gateway.endpoints. Since__name__in the new module would differ,routes_common.pynames that logger explicitly; this is the one statement that isn't a verbatim move.Renames
Private names another module now uses are public, each with a one-line docstring where it had none (ruff requires one):
_active_routing_state,_bind_observability_id,_build_policyengine_bundle,_bundle_identities,_bundle_payload,_is_modal_job_not_found,_job_metadata_store,_observability_headers,_optional_modal_dict,_policyengine_version_from_app_name,_record_not_found,_resolve_from_active_state,_routing_state_bundles,_routing_state_latestand_routing_state_routesdrop their underscore;_runtimeisobservability_runtime, since the routes already have local variables namedruntime.Tests:
tests/test_endpoints.py(1,801 lines)tests/test_endpoints.pyTestGetAppName,TestVersionEndpointstests/test_simulation_submission.pyTestSubmitSimulationEndpoint: routing, spawning and observability idstests/test_simulation_datasets.pyTestSubmitSimulationEndpoint: dataset and bundle checkstests/test_simulation_job_status.pyTestSubmitSimulationEndpoint: pollingtests/test_budget_window_endpoints.pyTestBudgetWindowBatchEndpointsfixtures/gateway_responses.pyOBSERVABILITY_ID,LOCAL_AREA_BREAKDOWN_RESULT,expected_bundle(with a docstring added, asfixtures/takes the full ruff rules)TestSubmitSimulationEndpointkeeps its name in each of the three files that hold its tests. A script compared every method and top-level statement of the old file with the new files: all appear exactly once and unchanged.modalis read in four modules (job_creation_routes,job_status_routes,modal_routing,version_routes), checked by a script that lists, for every patch, the modules that read the name:mock_modalfixture and the executor'sbudget_window_semi_integration_clientfixture patchmodalin all four, in place ofendpoints;tests/test_job_progress.py::TestStageReportingFailuresAreHarmless::test__unreadable_store_drops_stage_fieldspatchesget_job_progressinjob_status_routes, where the status route reads it;tests/test_canonical_spm.py,test_gateway_poll_returns_structured_400patchesjob_metadata_storeandmodalinjob_status_routes;test_gateway_submission_uses_registry_capability_before_spawnpatchesresolve_route,build_policyengine_bundle,modalandjob_metadata_storeinjob_creation_routes; andtest_versions_http_retains_capability_contract_versionpatchesactive_routing_stateinversion_routes. Each is the module the request in that test runs through.test_gateway_poll_returns_structured_400, the fakemodalhas onlyFunctionCall. Before, the status route's check for a Modal not-found error readmodal.exceptionfrom the same fake, found none, and treated the error as not a Modal one. That check now lives inmodal_routing, so it reads the realmodal.exception, whose not-found classes the test'sSPMInputErroris not an instance of. The result, and the test, are the same.tests/test_active_state_routes.pyimportsresolve_from_active_statefromroute_resolution, and the executor'stest_as_of_presence_survives_budget_parentimports_build_budget_window_parent_payloadand_resolve_request_spmfromjob_creation_routes, where they now live.fixtures/package_imports.py: the import isolation fixture also clears the new modules fromsys.modules, sotest_gateway_endpoints_import_does_not_import_policyengine_bundlestill re-imports all of the endpoint code.Environment variables
No change: the moved code reads the same variables, in the same functions, and no workflow, image or deployment file changes.
Testing
uv run --frozen pytest tests: 268 passed, includingtest_openapi_golden.py.test_canonical_spm.pyandtest_budget_window_scheduler.py, which drive the gateway: 67 passed; the full executor suite is run again on this branch.python scripts/run_quality_guards.pyandpython -m scripts.rules guard --base-ref origin/file-length-split-version-registry: passed;python -m scripts.rules renderleaves no diff.Only the lowest PR in the stack runs full CI, so this PR's
CI completecheck fails by design until the PRs below it merge.🤖 Generated with Claude Code