borgbackup / borgbackup/borg

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

Open
#10,021 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.