Skip to content

Enable ruff annotation rules (ANN) - #777

Draft
anth-volk wants to merge 10 commits into
ruff-typing-importsfrom
ruff-annotations
Draft

anth-volk wants to merge 10 commits into
ruff-typing-importsfrom
ruff-annotations

Conversation

@anth-volk

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

Copy link
Copy Markdown
Contributor

Fixes #776

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

Phase 1 step 1.8, group 3: annotations. Stacked on #773.

  • Annotations: ruff.toml gains ANN, and every function outside tests is now annotated, one commit per project. Findings fixed: fastapi 35, contract 36, observability 4, persistence 6, entry 11, gateway 40, executor 230, plus a CI script and the proof fixtures.
  • Any: replaced by real types, such as policyengine Simulation/Dataset/Policy/Region, ModuleType, storage.Client and SQLAlchemy RowMapping/Table. object is used for opaque values.
  • Remaining suppressions: each has an inline reason:
    • **dump_kwargs is forwarded to model_dump;
    • the Modal remote/spawn protocol's results vary by function;
    • three Pydantic wrap serializers keep noqa: ANN201, because annotating them changes the OpenAPI schema.
  • Modal specifics:
    • The executor's src/modal/app.py gets no __future__ import, because Modal records function signatures.
    • _image_setup.py keeps its no-imports constraint.
    • Editing fetch_artifacts will rebuild that image layer once on the next deploy.
  • After rebasing onto main: Count households once: sum the weight column unweighted #767 added _count_output_entities next to _sum_output_variable in simulation_output_common.py, which conflicted with this PR. Both now take simulation: Simulation.
  • Test-file exemptions: **/tests/** ignores S101, D1, ANN and PLR2004, registered as sim.quality.tests-ruff-exemptions.

Testing

  • All seven projects' test suites match their baselines:

    Project Passed
    fastapi 14
    contract 145
    observability 30
    stage12 12
    entry 224
    gateway 214
    executor 733
  • ruff check is clean, and src formatting is unchanged.

  • Pyright: it isn't run in CI, and none of the new errors comes from a wrong annotation.

    • Gateway: 4 new errors, verified against the base branch. They're "must return on all code paths" artefacts: the routes return inside the observability span() context, which is typed as possibly swallowing exceptions.
    • Executor: about 11 new errors from existing patterns: Optional access that ensure() guarantees, pandas .sum() typing, and narrowing after hasattr.

🤖 Generated with Claude Code

@anth-volk
anth-volk added this pull request to stack #755 October 13, 2026 12:35
@anth-volk anth-volk mentioned this pull request Oct 13, 2026
2 tasks done
anth-volk and others added 10 commits October 13, 2026 21:06
Add the missing parameter and return annotations. AppExit forwards its
callback arguments as object rather than Any, the JWT decoder's private
validator returns the same dict type its caller declares, and the
metrics middleware types call_next as Starlette's RequestResponseEndpoint.
Ping endpoints already pass response_model explicitly, so their new
return annotations do not change the generated responses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Type the SPM resolution and validation entry points, the gateway request
pre-validators (object in, object out) and the Modal Dict store helpers.
The three wrap model serializers in spm.py stay unannotated with a
reasoned noqa: Pydantic turns a serializer's return annotation into the
model's serialization JSON schema, which would rewrite the OpenAPI spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f ANN

Replace Any with object for values that are only inspected or passed
through, and type the persistence row helpers with SQLAlchemy's
RowMapping, Table and ColumnElement (imported for type checking only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every annotated route passes response_model explicitly, so FastAPI keeps
using it and the OpenAPI golden file is unchanged. _bundle_payload keeps
Any for **dump_kwargs, forwarded unchanged to BaseModel.model_dump, with
a reasoned noqa. Test fixtures outside tests/ are annotated too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Type the runtime, output builders, Modal entrypoints, scripts and the test
fixtures that live outside tests/. PolicyEngine, Google Cloud Storage and
observability types are imported for type checking only, country modules
are ModuleType, and duck-typed analysis values that tests replace with
SimpleNamespace are object. _try_compute_output uses a ParamSpec so its
arguments are checked against the wrapped function.

The in-repo src/modal package shadows the Modal library here, so Modal
types stay quoted or behind TYPE_CHECKING. _image_setup.py may not import
anything at module level, so it uses a local TYPE_CHECKING flag. The
RemoteFunction protocol keeps Any (with a reasoned noqa) because it
mirrors modal.Function.remote and spawn, whose payloads vary per function.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Select ANN. Tests are exempt, alongside the docstring, magic-number and
assert rules a later group will enable. scripts/rules findings are left
for the next sync from policyengine-api.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
_json_from_stdin returns object (every caller narrows it), and the proof
fixtures annotate their SQLAlchemy connection and table parameters. The
schema-authority proof reads the fixtures as text, so it is unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sim.quality.ruff-lint now includes ANN, and the **/tests/** per-file
ignore list (S101, D1, ANN, PLR2004) is registered as
sim.quality.tests-ruff-exemptions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

Enable ruff annotation rules (ANN)

1 participant