Skip to content

gradual typing: annotate the module boundaries, make mypy actually check something #10021

Description

@ThomasWaldmann

From a global code review of the borg2 codebase (2026-08).

Problem

The codebase is essentially untyped: a rough count finds ~95 of ~3000 function definitions with a return annotation (~3%). mypy runs in CI, but with --ignore-missing-imports over unannotated code it verifies very little. The Cython side is actually in decent shape (.pyi stubs exist for item, compress, hashindex, crypto/low_level, and the chunkers) — it is the pure-Python core (repository, cache, archive, manifest, helpers) that is dark for both the type checker and IDEs. manifest.py shows the direction already (an ArchivesInterface Protocol).

For 2.0, where internal APIs are breaking anyway, annotating the seams is cheap and pays off in every future refactor (e.g. the splits proposed in #10016/#10017, or the get_many work in #10018).

Proposed direction

  1. Annotate the boundaries first, not everything: Repository's public methods (and the borgstore boundary), RepoObj, the key interfaces in crypto/key.py, Manifest/Archives, Cache's public surface.
  2. Turn mypy strictness on per module (mypy supports per-module flags), starting with the freshly annotated ones, so the checked set only grows.
  3. Keep item.pyi honest: it duplicates the PropDictProperty table in item.pyx by hand — either generate it from the table or add a test asserting the stub and the table agree, so they cannot drift.
  4. Require annotations on new/refactored code going forward.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions