Skip to content

Code quality

This page summarizes how quality is enforced in the repository. Day-to-day commands are also described in Development tools.

Tools

Concern Tool Configuration
Lint & format Ruff [tool.ruff] in pyproject.toml
Security scans Bandit [tool.bandit] in pyproject.toml
Spelling typos .typos.toml, hook in .pre-commit-config.yaml
Hygiene prek .pre-commit-config.yaml (pre-commit format)
Tests pytest+cov [tool.pytest.ini_options], coverage

There is no dedicated Pyright or mypy job in pyproject.toml today; add one if you want static typing in CI.

Ruff

  "C90", # McCabe complexity
  "N",   # PEP8 naming
  "B",   # Bugbear (opinionated checks)
  "A",   # Flake8-builtins
  "C4",  # Flake8-comprehensions
  "PT",  # Flake8-pytest
  "RUF", # Ruff-specific rules
  "PL",  # Add pylint rules for fuller coverage
  "SIM", # Similarities
  "T10", # Debugger statements
  "DOC", # Docstring
  "D",   # Doc style
  "S",   # Security
]
lint.ignore = [
  "E501", # Line length (handled by formatter)
  "C901", # Disable overly strict complexity checks (optional, adjust as needed)
]
fix = true # Enable autofix
lint.unfixable = [] # List rules that should not be autofixed, if any

[tool.ruff.format]
quote-style = "double"       # Use double quotes for strings
indent-style = "space"       # Use spaces for indentation
docstring-code-format = true # Format code in docstrings

[tool.ruff.lint.pydocstyle]
convention = "google"

[tool.ruff.lint.per-file-ignores]
# Ignore specific rules in the tests directory
"tests/*" = ["S101", "ARG001", "PLC0415", "PLR2004"]
# S101: allow assert statements
# ARG001: allow unused function arguments (common in fixtures)
# PLC0415: allow import statements not at the top level
# PLR2004: allow magic values in the unit tests

Bandit

[tool.coverage.report]
fail_under = 0

[tool.pytest.ini_options]

typos

Project-specific spelling rules and allowed identifiers live in .typos.toml. The hook ID in .pre-commit-config.yaml is typos.

prek (hooks)

repos:
    - repo: https://github.com/pre-commit/pre-commit-hooks
      rev: v6.0.0
      hooks:
          - id: check-added-large-files
          - id: check-case-conflict
          - id: check-merge-conflict
          - id: check-symlinks
          - id: check-yaml
          - id: check-toml
          - id: debug-statements
          - id: end-of-file-fixer
          - id: mixed-line-ending
          - id: trailing-whitespace
          - id: check-docstring-first
          - id: check-json

    - repo: https://github.com/astral-sh/ruff-pre-commit
      rev: v0.15.14
      hooks:
          - id: ruff
            args: [--fix, --config=pyproject.toml]
          - id: ruff-format

    - repo: https://github.com/ComPWA/taplo-pre-commit
      rev: v0.9.3
      hooks:
          - id: taplo-format

    - repo: https://github.com/crate-ci/typos
      rev: v1.46.3
      hooks:
          - id: typos
            args: []

    - repo: https://github.com/rbubley/mirrors-prettier
      rev: v3.8.3
      hooks:
          - id: prettier

    - repo: https://github.com/DavidAnson/markdownlint-cli2
      rev: v0.22.1
      hooks:
          - id: markdownlint-cli2
            args:
                - --config
                - .markdownlint.yaml

    - repo: https://github.com/astral-sh/uv-pre-commit
      rev: 0.11.16

Run everything locally:

uv run prek run --all-files

Coverage

testpaths = "tests"
junit_family = "xunit2"
markers = [
  "integration: marks as integration test",
  "notebooks: marks as notebook test",

fail_under is set to 0 so new projects can merge before coverage is high; raise it when your test suite matures.

Further reading