The repo currently lints with black --line-length=100 only, pinned at black==22.6.0 in .pre-commit-config.yaml. That is formatting alone — no import sorting, no unused-import detection, no modernisation, no bug-pattern checks. Proposal: replace it with ruff, which covers formatting and linting in one fast tool.
Proposed configuration
Add to pyproject.toml (which currently has only [build-system] and [tool.pytest.ini_options]):
[tool.ruff]
line-length = 100 # keep the repo's existing width
target-version = "py311"
[tool.ruff.lint]
select = [
"E", "F", # pycodestyle + pyflakes
"I", # isort - import order
"UP", # pyupgrade - modern syntax
"B", # bugbear - common bug patterns
"SIM", # simplify - redundant code
"C4", # comprehension cleanups
"NPY", # numpy-specific gotchas
"PTH", # use pathlib over os.path
"RUF", # ruff's own extra checks
]
And replace the black hook in .pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.16.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
Refactoring the codebase to conform
This is the bulk of the work, and the reason it needs to be a deliberate pass rather than a drive-by:
network_unmixer.py is entirely under # fmt: off (line 2), so no formatter has ever touched it. It has many lines well over 100 characters (one docstring line is 744 characters). Deciding whether to lift # fmt: off — and reflowing if so — is the single biggest decision here. ELEMENT_LIST carries # fmt: skip and must keep it.
- Expect a meaningful number of
UP and PTH hits: the codebase uses typing.Dict/List/Optional throughout (pre-PEP 585/604 style) and os.path in places.
B will likely flag the bare assert statements used for input validation, and the broad raise Exception(...) calls in solve (TRY/EM rules would too, if adopted).
- The codebase is annotated for
pyre and carries deliberate # pyre-fixme comments — these must survive the pass.
- Any rule that genuinely needs suppressing should get a
# noqa: RULE with a one-line reason, not a blanket ignore.
Suggested sequencing
- Add the ruff config and run
ruff check in report-only mode to size the problem.
- Land the mechanical
--fix-able changes first (imports, comprehensions, pyupgrade) in one commit.
- Handle
# fmt: off in network_unmixer.py as a separate, reviewable commit.
- Address remaining hand-fix rules.
- Swap the pre-commit hooks and re-run
pre-commit install; note in the README that collaborators need to run it once after cloning.
Keeping hooks to lint/format only — the full test suite is slow by design (Hypothesis, deadline=None) and belongs in CI, not a per-commit hook.
The repo currently lints with
black --line-length=100only, pinned atblack==22.6.0in.pre-commit-config.yaml. That is formatting alone — no import sorting, no unused-import detection, no modernisation, no bug-pattern checks. Proposal: replace it with ruff, which covers formatting and linting in one fast tool.Proposed configuration
Add to
pyproject.toml(which currently has only[build-system]and[tool.pytest.ini_options]):And replace the black hook in
.pre-commit-config.yaml:Refactoring the codebase to conform
This is the bulk of the work, and the reason it needs to be a deliberate pass rather than a drive-by:
network_unmixer.pyis entirely under# fmt: off(line 2), so no formatter has ever touched it. It has many lines well over 100 characters (one docstring line is 744 characters). Deciding whether to lift# fmt: off— and reflowing if so — is the single biggest decision here.ELEMENT_LISTcarries# fmt: skipand must keep it.UPandPTHhits: the codebase usestyping.Dict/List/Optionalthroughout (pre-PEP 585/604 style) andos.pathin places.Bwill likely flag the bareassertstatements used for input validation, and the broadraise Exception(...)calls insolve(TRY/EMrules would too, if adopted).pyreand carries deliberate# pyre-fixmecomments — these must survive the pass.# noqa: RULEwith a one-line reason, not a blanket ignore.Suggested sequencing
ruff checkin report-only mode to size the problem.--fix-able changes first (imports, comprehensions, pyupgrade) in one commit.# fmt: offinnetwork_unmixer.pyas a separate, reviewable commit.pre-commit install; note in the README that collaborators need to run it once after cloning.Keeping hooks to lint/format only — the full test suite is slow by design (Hypothesis,
deadline=None) and belongs in CI, not a per-commit hook.