Skip to content

Development tools

This guide covers the development tools configured in this repository: prek, Ruff, typos, Bandit, and pytest.

Overview

  • prek: runs Git hooks locally before each commit (same config format as pre-commit; pull requests can still be checked by pre-commit.ci)
  • Ruff: linter and formatter for Python
  • typos: fast spell checker for text files (via crate-ci/typos)
  • Bandit: security-oriented static analysis for Python
  • pytest: test runner with coverage settings in pyproject.toml

prek (local Git hooks)

Setup

uv run prek install

Configuration

Hooks are defined in .pre-commit-config.yaml (Ruff, Taplo, typos, Prettier, markdownlint, uv-lock, gitleaks, and generic file checks). prek reads this file; you do not need the pre-commit Python package for local runs.

Running hooks

uv run prek run --all-files
uv run prek run ruff --all-files

Ruff

Configuration lives in pyproject.toml:

  "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

Typical commands:

uv run ruff check --fix src tests
uv run ruff format src tests

Spell checking (typos)

The typos hook uses .typos.toml at the repository root for corrections and word allow-lists. Run the same check as CI:

uv run prek run typos --all-files

Bandit

[tool.coverage.report]
fail_under = 0

[tool.pytest.ini_options]
uv run bandit -r src -c pyproject.toml

pytest and coverage

testpaths = "tests"
junit_family = "xunit2"
markers = [
  "integration: marks as integration test",
  "notebooks: marks as notebook test",
  "gpu: marks as gpu test",
  "spark: marks tests which need Spark",
  "slow: marks tests as slow",
  "unit: fast offline tests",
]

[tool.tox]
legacy_tox_ini = """
[tox]
envlist = py, integration, spark, all

[testenv]
commands =
uv run pytest

Conventional commits and pull requests

Release notes are built with git-cliff from conventional commit history. Pull request titles are validated by Lint PR (.github/workflows/semantic_pull_request.yml) so they follow the same vocabulary (feat:, fix:, etc.). There is no separate Node-based commitlint hook in this template.

CI

The CI workflow runs uv sync --extra test,ci --frozen and uv run pytest on Linux, macOS, and Windows for Python 3.12–3.14. Quality gates you care about beyond tests should be added explicitly (for example a job that runs Ruff) if you want them on every push.

Customizing tools

Edit pyproject.toml and .pre-commit-config.yaml, then run:

uv run prek run --all-files

For more detail, see the Ruff, Bandit, typos, and prek documentation.