Repository navigation
Refactor within ruff's complexity limits, then select every ruff rule (ALL) - #804
Merged
Merged
Conversation
anth-volk
added this pull request to stack #755
October 14, 2026 18:50
anth-volk
force-pushed
the
ruff-complexity
branch
3 times, most recently
from
October 14, 2026 21:06
96b676c to
358d65a
Compare
anth-volk
force-pushed
the
ruff-complexity
branch
3 times, most recently
from
October 15, 2026 14:06
257e32d to
c0bea9c
Compare
anth-volk
force-pushed
the
ruff-complexity
branch
from
October 15, 2026 15:09
c0bea9c to
4734c93
Compare
anth-volk
force-pushed
the
ruff-complexity
branch
from
October 15, 2026 16:06
4734c93 to
34998d7
Compare
anth-volk
force-pushed
the
ruff-complexity
branch
5 times, most recently
from
October 16, 2026 05:12
ed9692c to
78a8e6c
Compare
anth-volk
force-pushed
the
ruff-complexity
branch
2 times, most recently
from
October 16, 2026 06:06
ce079c6 to
0b1028a
Compare
anth-volk
force-pushed
the
ruff-complexity
branch
3 times, most recently
from
October 16, 2026 06:53
611b6e1 to
8e88dd1
Compare
2 tasks done
anth-volk
force-pushed
the
ruff-complexity
branch
from
October 19, 2026 12:28
8e88dd1 to
36ed6fd
Compare
… as one group #781 landed on main after this stack branched. PLR0913, which this PR enables, flags the segmented national runner's initializer once #781's job progress reporter sits beside its runtime. The two now travel as one SegmentedRunReporting, whose progress defaults to reporting nothing as before; run_segmented_national_impl and dispatch_run_simulation keep their signatures, and the previous commit's pins keep their assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#712 landed on main after this stack branched. PLR2004, which this PR enables, flags five magic values in its code; each is now a named constant, with no behaviour change: - the date-range period's two parts (_DATE_RANGE_PART_COUNT, the name simulation_runtime already uses); - the segment poll's consecutive-error limit (CONSECUTIVE_POLL_ERROR_LIMIT, as in segmented_national); - the national partition's 20 region groups (NATIONAL_PARTITION_GROUP_COUNT, next to US_REGION_GROUPS); - worker validation's cache years, artifact count and probe year, from the cache precompute's PRECOMPUTE_YEARS: one dataset per year and one baseline per US region group per year make the 63 artifacts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… method #712 landed on main after this stack branched. PLR0913, which this PR enables, flags its eleven-argument _observe_simulations. It becomes _ReportCoordination._observe_children, which takes the calls and descriptors and reads the child plans, store, runtime, progress, stage plan, clock, sleep and wait window from the coordination it belongs to. The polling, failure and timeout logic is unchanged, and #712's runtime tests cover every path through it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…one site #712 landed on main after this stack branched. PLR0913, which this PR enables, flags its seven-argument report_failure. The telemetry scope, default error code, attributes and segment index that say where a failure was caught now travel as one FailureSite; the error, runtime and progress stay separate. The coordinator's three calls, the worker's and the segment runner's pass the same values as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e group #712 landed on main after this stack branched. PLR0913, which this PR enables, flags Stage12SegmentRunner's nine-argument constructor. The Modal module, region groups, sleep and the two poll intervals that tests replace now travel as one SegmentRunnerSeams, whose defaults are the deployed ones; the simulation, app name, runtime and cancellation check stay separate. run_segmented_simulation passes nothing new. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s one group #712 landed on main after this stack branched. PLR0913, which this PR enables, flags its eight-argument build_stage12_simulation. The country module, region, dataset selection and loaded dataset the worker resolves in its own stages now travel as one ResolvedSimulationInputs. The builder reads the scoping strategy from the region, as _build_simulation already does, so it no longer takes the region code it only deleted. The SPM parameters, normalised policy and execution input stay separate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e group #712 landed on main after this stack branched. PLR0913, which this PR enables, flags the cache precompute's seven-argument run_precompute. Its five Modal function handles now travel as one CachePrecomputeFunctions, as the baseline precompute's PrecomputeFunctions already do; the bucket and echo stay separate. The Modal app's entrypoint passes the same five functions, and its secrets and environment are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ript #712 landed on main after this stack branched. PLR0913, which this PR enables, flags the six-argument ScriptedChildCall its runtime tests use. The result, wait error, cancel error and during-wait hook that script a call's outcome now travel as one ChildCallScript; the call ID and clock stay separate. Both constructions script the same outcomes as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#712 landed on main after this stack branched. Before its eight-return qualifying_cache_identity is split, pin the ineligible cases its tests did not reach: no or a non-region-group scoping strategy, a missing, empty or non-list region group, a non-state or non-text region code, and a scope without a cache key. Each gets no cache identity. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… and scope checks PLR0911 flags the eight returns of qualifying_cache_identity. It now asks three questions: is this a current-law baseline on the default dataset, what is its group of state regions, and what is the region-group scope's cache key. Each check is pure, so asking them in this order gives the same result; the previous commit's pins and #712's identity tests keep their assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… added #712 landed on main after this stack branched. Before its C901 verify_determinism_impl is split, pin what its tests did not reach: every kind of frame difference (an entity missing on one side, a column on only one side, a dtype change and a value change) in its sorted order, the rejection of a probe that is not a planned baseline, and that the stored baseline is downloaded only when it is not already in the data folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
C901 flags verify_determinism_impl. The comparison of cached and fresh frames moves into _frame_differences, which lists each difference in the same sorted order; the probe check, download, cache-hit check and pass record stay in verify_determinism_impl. The previous commit's pins keep their assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#712 landed on main after this stack branched. Before its C901 merge_segment_results is split, pin the checks its tests did not reach: a result set that omits a segment, a result naming another region group, segments with different entities or column dtypes, and an entity without its identifier. The serializer refuses frames without an identifier, so that pin decodes every segment to one directly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… merge steps C901 and PLR0912 flag merge_segment_results. It now indexes the results (rejecting an incomplete set or a duplicate index), decodes each planned segment in partition order (rejecting an omitted segment or one naming another role or region group), and merges each entity's frames (rejecting different entities, dtypes, a missing identifier or duplicate IDs), each in its own function. The checks and their order are unchanged, and the previous commit's pins keep their assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#712 landed on main after this stack branched and extended run_single_simulation, which C901 and PLR0915 now flag. Before it is split, pin the paths its tests did not reach: a simulation that is no longer active is refused, a claim another writer won stops the run as cancelled, and a failed status read in the cancellation check is logged by error type only and treated as not cancelled, so the run completes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ord steps C901 and PLR0915 flag run_single_simulation, which #712 extended with segmented calculation and cancellation. It now reads as its phases: claim the simulation (refusing one that is no longer active or that another writer claimed), build the cancellation check, write the input, calculate (segmented, standard or injected, always as a SimulationCalculation), write the artifact, and record success or failure, each phase but the writes in its own function. The order of reads, writes and reports is unchanged, and the previous commit's pins keep their assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#712 landed on main after this stack branched. Before its C901, PLR0912 and PLR0915 fetch_stage12_cache is split, pin what its two tests did not reach: each manifest rejection (no bucket or manifest, schema, bundle, year set, artifact list, artifact count and deployment digest), each artifact rejection (a non-object entry, a filename with a directory, a duplicate filename, a non-integer size and a same-size file with another digest, which leaves no partial file), and the storage client built with no credentials, a credentials object or credentials encoded as a string. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d file steps C901, PLR0912 and PLR0915 flag fetch_stage12_cache. It now validates the whole manifest first (schema, installed bundle and years; the artifact list and its counts; then the deployment digest), builds the storage client from the deployment's credentials only when none is given, and fetches each artifact through a partial file. The checks, their order and the environment variables it reads are unchanged; the module stays self-contained for the image build. The previous commit's pins keep their assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
None of the four callers (the entry app, the gateway app and its test factory, and the executor's FastAPI app) or the tests passes service_version, and build_runtime falls back to the package version when it is absent. Without it the function takes five arguments, so its PLR0913 suppression goes. Modal workers still pass service_version through init_process_observability. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The batch's reported version and its Modal app name always travel together: the gateway takes both from its route resolution, and the batch scheduler from its batch context. create_initial_batch_state now takes them as one frozen BatchRoute(version, app_name), so it has five arguments and needs no PLR0913 suppression. The stored batch state is unchanged. The gateway, the scheduler and the tests pass a BatchRoute. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The policyengine.py version, the model version and the route provenance are read only together, to decide whether a route with no SPM capability predates canonical SPM. resolve_spm_selection now takes them as one frozen SPMRouteVersions, so it has four arguments and needs no PLR0913 suppression. Its decisions are unchanged. The gateway, the executor and the tests pass an SPMRouteVersions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v2_app.py already imports policyengine_simulation_executor.stage12_runtime at module level, and that package's __init__ imports its submodules eagerly, so the four in-function imports of the same package loaded nothing new and each needed a PLC0415 suppression. The Modal function bodies now call stage12_runtime.<name> instead. Attribute lookups happen at call time, so tests that patch stage12_runtime.run_single_simulation or stage12_runtime.coordinate_report still take effect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Splitting fetch_artifacts into six functions gave each one its own in-function imports of json, logging, os and pathlib.Path, raising the module's PLC0415 suppressions from 7 to 14. Those modules are always importable in the image-build step: Modal imports this module from the function's mounted source package (the function is not serialized), and stage12_cache_image.py, which also runs before add_local_python_source, already imports json, os and pathlib at module level. The module now imports them, and typing.TYPE_CHECKING, at module level, which removes twelve suppressions. test_image_setup_module_stays_self_contained now allows module-level imports of standard-library modules only (sys.stdlib_module_names), and still rejects any import of the executor package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add both to banned-module-level-imports, so ruff keeps them out of module-level imports (TID253) and accepts their in-function imports without a PLC0415 suppression. That removes the two remaining suppressions in _image_setup.py. stage12_cache_image.py was the only application module that imported google.oauth2 at module level; the import moves into _storage_client, the one function that uses it. The storage-client test now patches google.oauth2.service_account.Credentials directly, as the image setup tests already do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
ruff-complexity
branch
from
October 20, 2026 14:08
eef2427 to
4330d43
Compare
anth-volk
marked this pull request as ready for review
October 20, 2026 16:37
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 #803
Same-Repository Draft PR Check
PolicyEngine/policyengine-sim-api, not a personal fork.Summary
Phase 1 step 1.8, group 8b, the last group: complexity refactors, then
select = ["ALL"]. Stacked on #802. This completes step 1.8.Every function over ruff's complexity limits is refactored, not suppressed. That includes PLR0913 (too many arguments): this PR adds no suppression. Each refactor is preceded by a commit that adds characterization tests pinning the current behaviour. Every commit passes ruff and the quality guards.
Suppression counts
BLE001instage12_runtime/coordination.py(3) andstage12_runtime/simulation.py(1);BLE001andTRY400(2) in the entry app's Stage 12 dispatch.PLC0415).src/modal/_image_setup.py, three insrc/modal/v2_app.py. All of them exist onmain.Changes
Contract and persistence libraries:
ComparisonReportRecord.validate_statekeeps its Pydantic signature and is split into report and comparison checks.create_initial_batch_statetakes the batch's version and Modal app name as one frozenBatchRoute(version, app_name), and has five arguments.resolve_spm_selectiontakes the route's policyengine version, model version and route provenance as one frozenSPMRouteVersions, and has four arguments.Observability library:
init_simulation_observabilitydropsservice_version. None of its four callers or the tests passed it, andbuild_runtimefalls back to the package version. Modal workers still pass a version throughinit_process_observability.Entry:
create_app(complexity 52, 144 statements) keeps every route's name, decorators, parameters and registration order. The shared behaviour moves into_EntryRuntime, and Stage 12 error logs still record only the error type.Gateway: active-state route resolution is split into pinned, latest and requested-version steps.
Executor: long argument lists become small frozen groups, including:
Stage 12 coordination (complexity over 10, 11 arguments, 109 statements) becomes a
_ReportCoordinationclass with claim, plan, dispatch, wait and aggregate phases. The Stage 12 parity checks are split by entity, column and report value. The image artifact fetch is split into freshness, credential and download steps.Executor imports:
src/modal/v2_app.pyalready importspolicyengine_simulation_executor.stage12_runtimeat module level, and that package's__init__imports its submodules eagerly.stage12_runtime.<name>. Tests that patchstage12_runtime.run_single_simulationorstage12_runtime.coordinate_reportstill take effect, because the attribute is looked up at call time.src/modal/_image_setup.pyimportsjson,logging,os,pathlib.Pathandtyping.TYPE_CHECKINGat module level.stage12_cache_image.py, which also runs beforeadd_local_python_source, already imports standard-library modules (json,os,pathlib,typing) at module level.test_image_setup_module_stays_self_containednow allows only standard-library modules at module level (sys.stdlib_module_names), and still rejects any import of the executor package.google.oauth2andpolicyengine_ukjoinbanned-module-level-imports, so their in-function imports need no suppression.stage12_cache_image.pywas the only application module importinggoogle.oauth2at module level; the import moves into_storage_client, which is the one function that uses it.google.oauth2.service_account.Credentialsdirectly.Code from Expose the certified dataset SHA-256 and assert the served identity at deploy #743, Gate releases on a numerical sentinel and make them reversible #744 and Release Stage 12 database sessions and keep original failures visible #789, which merged while this was in progress, is refactored the same way:
release_sentinel.check_deployment(JobPolling, a_Deploymentwith per-case and job-wait steps,HTTPStatus.OK).main: one command function per mode, with the same precedence. Its--helpoutput is byte-identical.restore_routing_plans.bundle_versionsandverify_dispatch.open_connection_with_retry(RetryTiming).Release Stage 12 database sessions and keep original failures visible #789's original-failure reporting and session release are kept inside the new coordination phases.
Rules tool: takes the Public API's group 8b refactor (Refactor tests, scripts and the rules tool, then select every ruff rule (ALL) policyengine-api#3934). Each repository owns its copy; this one is currently identical. Its tests went from 80 to 115.
ALL:ruff.tomlselects every rule, and ignores only the two that conflict withruff format(COM812,ISC001) and one of each mutually exclusive docstring pair (D203,D213).ALLfound nothing that wasn't already fixed.sim.quality.ruff-lintlistsALL.Noticed, not changed: in
release_sentinel, a job that fails but still returns an object result has its values compared anyway. The new tests pin that existing behaviour. It may be worth confirming it's intended.Commits added on 2026-10-20 (eef2427)
Rebase. Rebased onto #802 at 85f690c. Two commits had conflicts with #802's new commits:
Pass the resolved region to _build_simulation …(simulation_runtime.py): kept Enable ruff argument, idiom and pytest-style rules (ARG, B, C4, FBT, PERF, PLW, PT, PTH, RUF, SIM and others) #802'sExitStackstructure with this PR's_ENV_VALUE_PREVIEW_CHARSconstant.Pass the Stage 12 connection retry its clock, sleep and jitter as one timing(database_retry.py): keptRetryTimingwithout thePERF203suppression that Enable ruff argument, idiom and pytest-style rules (ARG, B, C4, FBT, PERF, PLW, PT, PTH, RUF, SIM and others) #802 removed.New commits:
Testing
At eef2427, each project in an environment synced with
uv sync --frozen --extra test --python 3.13:tests/goldenunchanged. The entry, executor and gateway OpenAPI dumps were byte-identical to the base when last compared, before this update; this update changes no route or schema.check --extend-select RUF100 .(withALL) gives 0 findings, andformat --check projects/*/src libs/*/srcpasses.scripts/run_quality_guards.py, with the baseruff-idioms-arguments, passes.src/modal/app.pyis untouched._image_setup.py):POLICYENGINE_VERSION,POLICYENGINE_US_VERSIONorPOLICYENGINE_UK_VERSION,POLICYENGINE_BUNDLE_RECEIPTandPOLICYENGINE_DATA_FOLDERcome from the image environment:.env(VERSION_ENV)insrc/modal/app.py, applied before the fetch layer.GOOGLE_APPLICATION_CREDENTIALS_JSONcomes from thegcp-credentialsModal secret (environmentmain) attached to that layer.stage12_cache_image.py):GOOGLE_APPLICATION_CREDENTIALS_JSONcomes from thestage12-evaluation-gcp-credentialsModal secret attached to the cache layer.STAGE12_CACHE_MANIFEST_DIGESTcomes from the deploy workflow'sstage12_cachestep.STAGE12_BUNDLE_MANIFEST_SHA256andPOLICYENGINE_DATA_FOLDERcome from the image environment.MODAL_ENVIRONMENT, unchanged, falling back tolocal. The repository doesn't set it for these functions, so its provider is unverified: it is expected from the Modal runtime.SIMULATION_TEST_AUTH_*values come from theSIMULATION_ENTRYPOINT_*secrets throughsecrets: inherit.RELEASE_PAYLOADis set from thecheck-policyengine-updates.ymlstepenv:.gcp-credentialsinmainandstaging;stage12-evaluation-gcp-credentialsinmain,stagingandtesting). Which keys they hold wasn't checked.CI completeruns until the PRs below merge.🤖 Generated with Claude Code