Repository navigation
Conversation
anth-volk
added this pull request to stack #3917
October 14, 2026 13:55
anth-volk
force-pushed
the
ruff-structure-imports
branch
3 times, most recently
from
October 14, 2026 18:08
a346195 to
0f717e8
Compare
anth-volk
force-pushed
the
ruff-structure-imports
branch
8 times, most recently
from
October 15, 2026 00:06
5b47c96 to
b5f847b
Compare
anth-volk
force-pushed
the
ruff-structure-imports
branch
from
October 15, 2026 15:21
b5f847b to
551bc44
Compare
anth-volk
force-pushed
the
ruff-structure-imports
branch
2 times, most recently
from
October 15, 2026 17:21
015e6fc to
428c6f9
Compare
anth-volk
force-pushed
the
ruff-structure-imports
branch
3 times, most recently
from
October 16, 2026 06:45
eb79057 to
ccc3096
Compare
Tests deliberately reach into private members, pytest test directories aren't packages, and tests often import inside a test after patching the environment. Application code still gets every rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The route modules use `from __future__ import annotations`, and FastAPI resolves string annotations against module globals only, so the query dependencies move from per-router closures to module-level Annotated aliases. The OpenAPI documents are byte-identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rename the purely internal names: the outcome bounds and labels in the decile impact helpers, the rules tool's BaseUnavailableError and its tests' assert_violation helper, a test's list of uncalculated variables, the PostgreSQL UUID import, and the tests' SQLAlchemy TimeoutError imports (now PoolTimeoutError, so they no longer shadow the builtin). Keep, with reasons, the Reform subclass name that policyengine-core uses as the reform key, the gRPC stubs' Export methods, and the three private accesses that have no public accessor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
policyengine_api is a namespace package (its routes and libs directories included), and .github, dashboard/experiments, the two Alembic environments and rules/fixtures hold scripts and fixtures that are never imported as packages. Listing them in ruff's namespace-packages changes no other rule's result, except N999 on the hyphenated .github/find-api-model-versions.py, which keeps its name because update-policyengine-package.sh runs it by that path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move four imports out of functions: request_context now reads get_runtime through the observability package it already imports, the simulation entrypoint imports SPMValidationError at the top (spm was already loaded), the four v2 resource routers import their default service factories, and the route dependencies import is_ready. None creates a cycle or loads a third-party or standard-library module that was not already loaded; the ASGI and Flask entry points import exactly the same modules as before. The remaining deferred imports keep an inline reason: they load country models, PolicyEngine.py, spm_calculator, Google clients, the v2 persistence stack (whose database module registers an atexit hook) or the bundle manifest, break an import cycle, need configuration at import, or are looked up per call so tests can replace them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Long strings are split by implicit concatenation, so every log message, error message and published Field description keeps its exact text; long comments are rewrapped or moved above the line they describe. Only four docstrings change, none of them published: a Flask route's, two internal functions' and a rule proof fixture's. Three lines keep a suppression: a dotted module path that cannot be wrapped, and the GPT-4 prompts and a script's --help summary, whose text would change if wrapped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every split string keeps its exact text (the parsed code is unchanged), so the rendered rules page and the AGENTS.md block are identical apart from the tool hash. Two test docstrings are reworded to fit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Split long strings (same text), rewrap comments and reword over-long test docstrings. Thirteen test functions whose names alone overflowed the line get shorter names; nothing references them. The economy service tests reach the long-named reform-impact lookup mock through a small hash_prefix_lookup helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Select A, E, FAST, INP, N, PLC and SLF. The earlier commits in this branch fix or explain every finding, so ruff reports none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
api.quality.ruff-lint now lists A, E, FAST, INP, N, PLC and SLF. The rendered rules page also picks up the rules tool's new hash. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The /v2/me, user-report, user-simulation, user-household and user-policy routes that #3891 added or reshaped took 44 dependencies as parameter defaults. Their query dependencies become module-level Annotated aliases, as the other v2 routes do, and the request-size check and the upgrade route's unauthenticated-user header become Annotated parameters. Each handler's principal comes from require_user, the authenticator that NativeRouteDependencies injects per router. FastAPI resolves string annotations against module globals only: with `from __future__ import annotations`, Annotated[AccountPrincipal, Depends(require_user)] would silently become a required "principal" query parameter. These five modules therefore no longer use the future import, so their annotations are evaluated where the handlers are defined, and import the route dependency types and their default service factory at run time. Moving the default factory import out of _service_factory also clears its PLC0415 finding in the three new modules, as the other v2 resource routers already do; the dependencies module is already loaded wherever these routers are built. The OpenAPI documents, with the injected test authenticator and with the default one, are byte-identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Of the 18 PLC0415 findings left in the code #3891 added, the route dependencies' account-request authenticator import moves to the top level. Its module is already loaded wherever the dependencies module is, and it creates no cycle; the ASGI and Flask entry points import exactly the same modules as before. The other deferred imports keep an inline reason, worded as for the existing ones: the v1 session factory is looked up per call so tests can replace it; the v1 reference checks, v2 persistence, the user-account service and Auth0 Management load only when a default factory runs or a v1 reference is checked; readiness validation loads the user-auth and Auth0 settings only when it runs; and the Google Secret Manager client loads only when Auth0 Management reads a secret. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The user-service proof fixture's docstring puts the rule's verdict on its own line, as the validator fixtures do. The import side-effect test's subprocess script asserts the association qualification module is unloaded across three lines, and the identity persistence test's qualification test names the qualification module once, as qualification, so its pending checker fits on one line. The checks are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The typing-only-imports skill now says why the five signed-in user route modules don't use `from __future__ import annotations`: their handlers depend on the authenticator each router is given, which FastAPI cannot resolve from a string annotation against module globals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mport Thirteen packages and modules are only ever imported inside the function that needs them: - policyengine and spm_calculator, which load country models; - the v2 database module, which registers an exit hook at import; - the nine v2 database_session modules, which open persistence only when a default factory runs; - Auth0 Management, which loads the Google client. No application module imports any of them at module level. pyproject.toml now lists them in banned-module-level-imports and selects TID253. Importing one at module level fails (TYPE_CHECKING imports are still fine), and PLC0415 accepts their in-function imports without a suppression. That removes 28 PLC0415 suppressions. Tests and CI/CD scripts may still import them at module level: TID253 joins their file-level exceptions, since find-api-model-versions.py imports policyengine. Modules that some application module does import at module level keep their inline reasons. These include google.cloud, the v2 services modules, constants and country. Comments and configuration only: no code changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
ruff-structure-imports
branch
from
October 16, 2026 07:05
ccc3096 to
a8c5058
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 #3919
Summary
Phase 1 step 1.8, group 7: structure and imports. Stacked on #3915.
SLF001,INP001andPLC0415, alongsideS101,D1,ANNandPLR2004. Tests deliberately reach into private members, pytest test directories aren't packages, and tests often import inside a test after patching the environment. Application code still gets every rule.api.quality.tests-ruff-exemptionsis updated to match.selectgainsA,E,FAST,INP,N,PLCandSLF. All 289 findings left after the exemption are fixed or kept with an inline reason.from __future__ import annotations: FastAPI resolves string annotations against module globals, and the query dependencies were local closures. Each dependency is now a module-level alias instead, such asHouseholdCreateQueryDependency = Annotated[HouseholdCreateQuery, Depends(query_dependency(HouseholdCreateQuery))]. The OpenAPI is byte-identical.Moved (8, plus 4 in the code Stage 12A: Sign-in identity and v1-anchored user associations #3891 added): imports that add no cycle, side effect or third-party load. A fresh-interpreter check of all 220
policyengine_apimodules shows thatpolicyengine_api.asgi,policyengine_api.apiand 211 others load exactly the same modules. Seven route and dependency modules now also load the small, dependency-freereadinessandfastapi_routes.dependenciesmodules.Allowlisted as lazily loaded (28 suppressions removed):
pyproject.tomllists 13 packages and modules in ruff'sbanned-module-level-imports, withTID253selected:policyengineandspm_calculator, which load country models;data.v2.database, which registers an exit hook at import;database_sessionmodules;libs.auth0_management.No application module imports any of them at module level. Importing one there now fails, though
TYPE_CHECKINGimports are fine, andPLC0415accepts their in-function imports without a suppression. Tests and.githubscripts may still import them at module level, soTID253joins their file-level exceptions;find-api-model-versions.pyimportspolicyengine.Kept (32), each with a reason: modules that some application module also imports at module level, so they can't be allowlisted:
data/orm.pyimportsgoogle.cloud);simulation_entrypoint,specification,constants);country,metadata_service);readiness's configuration imports;policyengine_apihas no__init__.pyon purpose, and.github,dashboard/experiments,migrations/v1,migrations/v2andrules/fixturesaren't packages. They're declared in ruff's top-levelnamespace-packagessetting, with a comment. Compared with the fullruff checkoutput before the change, the only other difference is a hyphenated.githubscript name (N999), kept with a reason because a shell script runs it by that path. No__init__.pywas added, and the built wheel and sdist contain the same files.economy_comparison.py, the rules tool'sBaseUnavailableErrorandassert_violation, SQLAlchemy'sTimeoutErrorimported asPoolTimeoutErrorin tests, and 13 test function names that alone overflowed the line. Kept with a reason:country.py'sclass reform, since policyengine-core uses the class name as the reform key; two gRPC-stubExportmethods in a test; and three private accesses with no public equivalent that tests patch.Fielddescriptions that were split are unchanged. Kept with a reason (6 findings, 4 suppressions): a dotted module path, two GPT-4 prompts in the dashboard experiment, and a docstring line that is a script's--helptext.api.quality.ruff-lintnow lists the seven families andTID253. The rules tool changed (wrapped lines and the renames above), and sim takes the same changes in Enable ruff structure and import rules (INP, PLC, SLF, N, A, FAST, E) policyengine-sim-api#799, which has the same allowlist mechanism.Testing
pytest tests/unit tests/contract, to_refactor and the dedupe integration test (themake testset): 2,420 passed, the same as the base. That run was before the stack was rebased onto the release commit; this branch differs from it only in that commit'sCHANGELOG.md,pyproject.tomlversion,uv.lockand changelog fragment.make typecheck-v2is clean. mypy on the 65 changed files outside that gate gives the same output as the base.ruff checkandruff format --check(0.15.12) are clean repo-wide./v2/openapi.jsonpreview and the legacy spec are byte-identical to the base, with and withoutOLD_SIMULATION_GATEWAY_URLset.ruff check(includingRUF100from Enable ruff argument, idiom and pytest-style rules (ARG, B, C4, FBT, PERF, PLW, PT, PTH, RUF, SIM and others) #3924 up, so no suppression is left unused) andruff format --checkare clean.noqacomments. The test suites weren't re-run for this comment-and-configuration change..github/find-api-model-versions.pygained only a suppression comment.CI complete, which fails and says why. Its full run starts once the PRs below it merge.🤖 Generated with Claude Code