gradual typing: annotate the module boundaries, make mypy actually check something
- Dominant language
- Python
- Stars
- 13.7k
- Forks
- 875
- Avg merge
- 11h 15m
- Merged PRs (30d)
- 192
Description
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](https://claude.com/claude-code)
Contributor guide
Research direction
Start by reading the existing ArchivesInterface Protocol in manifest.py and the public surfaces of repository, cache, archive, helpers, crypto/key.py, and borgstore. Then inspect item.pyi alongside item.pyx and review how mypy is configured for per-module checking. Done means the selected boundaries are annotated, strict checking covers those modules, and the item stub cannot drift from its Cython property table.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- developer-experience, tooling
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100