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
- 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.
- Turn mypy strictness on per module (mypy supports per-module flags), starting with the freshly annotated ones, so the checked set only grows.
- 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.
- Require annotations on new/refactored code going forward.
🤖 Generated with Claude Code
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-importsover unannotated code it verifies very little. The Cython side is actually in decent shape (.pyistubs exist foritem,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.pyshows the direction already (anArchivesInterfaceProtocol).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_manywork in #10018).Proposed direction
Repository's public methods (and the borgstore boundary),RepoObj, the key interfaces incrypto/key.py,Manifest/Archives,Cache's public surface.item.pyihonest: it duplicates thePropDictPropertytable initem.pyxby hand — either generate it from the table or add a test asserting the stub and the table agree, so they cannot drift.🤖 Generated with Claude Code