Ruff-Only "Golden Path" Development Setup¶
Overview¶
This repository uses Ruff as the single tool for Python code formatting and linting. This "golden path" approach ensures:
- ✅ Single Source of Truth: All tool configurations in
pyproject.toml - ✅ One Formatter: Ruff replaces Black, isort, and multiple linters
- ✅ Pinned Versions: Deterministic builds with exact version control
- ✅ Reproducibility: Identical results on local machines, containers, and CI
- ✅ Simplicity: Fewer tools, faster feedback, less configuration
Why Ruff-Only?¶
Before: Multiple Tools¶
- Black: Code formatting
- isort: Import sorting
- Flake8: Linting
- Pylint: Additional linting
- pycodestyle: Style checking
- pydocstyle: Docstring checking
Problems: Tool conflicts, configuration drift, slow execution, version mismatches
After: Ruff Only¶
- Ruff: All-in-one formatting + linting + import sorting
- Speed: 10-100x faster than traditional tools
- Compatibility: Drop-in replacement for Black + isort
- Comprehensive: Implements 800+ linting rules
Quick Start¶
1. Install Dependencies¶
# Install all dependencies
make install
# Or manually:
pip install -r requirements.txt
pip install -r requirements-dev.txt
pip install -e .
pre-commit install
2. Format Your Code¶
# Format all code
make fmt
# Or use Ruff directly:
ruff format src/ tests/ scripts/
ruff check --fix --select I src/ tests/ scripts/ # Fix imports
3. Lint Your Code¶
4. Run Pre-commit Hooks¶
# Run all pre-commit hooks (includes Ruff + MyPy + tests)
make pre-commit
# Or use pre-commit directly:
pre-commit run --all-files
Development Workflow¶
Before Committing¶
- Format your code:
make fmt - Fix linting issues:
make lint - Check types:
make type - Run tests:
make test-unit - Run pre-commit:
make pre-commit
VS Code Integration¶
The repository is configured for automatic formatting on save:
- Formatter: Ruff (replaces Black)
- Import Organizer: Ruff (replaces isort)
- Linter: Ruff (replaces Flake8/Pylint)
Settings in .vscode/settings.json:
{
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.ruff": "explicit",
"source.organizeImports.ruff": "explicit"
}
}
}
Pre-commit Hooks¶
Pre-commit automatically runs on every commit:
- Ruff Format: Formats code (replaces Black)
- Ruff Lint: Checks code quality (replaces Flake8/isort)
- MyPy: Type checking
- Pyupgrade: Syntax modernization (Python 3.12+)
- Bandit: Security checks
- Pre-commit hooks: File checks (YAML, TOML, JSON, trailing whitespace, etc.)
- Pytest: Unit tests (integration tests excluded for speed)
Configuration¶
pyproject.toml¶
All tool configuration lives in pyproject.toml:
[tool.ruff]
line-length = 88
target-version = "py312"
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
[tool.ruff.lint]
select = ["E", "F", "W", "C90", "I", ...] # Comprehensive rule set
ignore = ["E501", ...] # Pragmatic ignores
[tool.ruff.lint.isort]
known-first-party = ["portfolio_management"]
combine-as-imports = true
Version Pinning¶
All tools use pinned versions for reproducibility:
Pre-commit (.pre-commit-config.yaml):
- Ruff:
v0.8.0 - MyPy:
v1.11.2 - Pyupgrade:
v3.15.0 - Pre-commit hooks:
v5.0.0
Requirements (requirements-dev.txt):
ruff>=0.8.0mypy>=1.11.0pytest>=8.0.0pre-commit>=4.0.0
CI/CD Integration¶
GitHub Actions workflow (.github/workflows/tests.yml):
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12" # Pinned to Python 3.12
- name: Run pytest suite
run: pytest -m "not integration" # Fast unit tests only
CI reproduces local behavior exactly:
- Same Python version (3.12)
- Same tool versions (pinned in pre-commit)
- Same test selection (unit tests only)
Makefile Commands¶
The Makefile provides consistent commands across environments:
| Command | Description |
|---|---|
make install |
Install all dependencies |
make fmt |
Format code with Ruff |
make lint |
Lint code with Ruff |
make type |
Run type checking with MyPy |
make test |
Run all tests |
make test-unit |
Run only unit tests (fast) |
make test-integration |
Run only integration tests |
make pre-commit |
Run all pre-commit hooks |
make clean |
Remove build artifacts |
Ruff Features¶
Formatting (Replaces Black)¶
Linting (Replaces Flake8, Pylint, etc.)¶
# Lint files
ruff check src/
# Auto-fix issues
ruff check --fix src/
# Show all violations
ruff check --output-format=full src/
Import Sorting (Replaces isort)¶
Migration from Black + isort¶
If you have existing code formatted with Black and isort:
- Ruff is Black-compatible: No reformatting needed
- Ruff import sorting: Compatible with isort's "black" profile
- One-time migration: Run
make fmtto ensure consistency
Troubleshooting¶
Issue: Pre-commit hooks fail¶
Solution: Update pre-commit hooks
Issue: Ruff not found¶
Solution: Reinstall dev dependencies
Issue: VS Code not using Ruff¶
Solution: Install Ruff extension and reload
- Install "Ruff" extension (charliermarsh.ruff)
- Reload VS Code
- Verify in settings:
"editor.defaultFormatter": "charliermarsh.ruff"
Issue: Different results locally vs CI¶
Verify versions match:
# Local
ruff --version
mypy --version
python --version
# CI logs
# Check GitHub Actions output for version mismatches
Best Practices¶
- Always run
make fmtbefore committing - Use
make pre-committo verify everything passes - Don't modify
.pre-commit-config.yamlwithout updating docs - Pin new tool versions explicitly
- Keep
pyproject.tomlas single source of truth
Resources¶
Support¶
For issues or questions:
- Check this documentation
- Review
pyproject.tomlfor configuration - Check
.pre-commit-config.yamlfor hook versions - Consult Memory Bank (
memory-bank/techContext.md)