- Регистрация
- 1 Мар 2015
- Сообщения
- 14,564
- Баллы
- 155
The Challenge We Faced
Our FastAPI menu service had grown rapidly, leading to inconsistent code quality across the team. Print statements were scattered everywhere, error handling was inconsistent, and code reviews spent too much time on formatting issues.
# Bad practices we needed to fix
def process_order(order_id):
try:
print(f"Processing order {order_id}")
result = api.get_order(order_id)
print(result)
return result
except Exception as e:
print(f"Error: {e}") # No logging, lost when deployed
raise HTTPException(status_code=500, detail="Failed") # Lost original exception
The Solution: Ruff + Pre-commit
We chose Ruff for its speed (100x faster than flake8) and auto-fixing capabilities, combined with pre-commit for automation. This powerful combination enforces code quality before code even reaches the repository.
1. Setting Up the Tools
First, we added the necessary dependencies:
pip install ruff==0.11.0 pre-commit==4.1.0
Then created two key configuration files:
2. Configure Ruff (pyproject.toml)
[tool.ruff.lint]
select = ["E", "F", "B", "I"]
fixable = ["ALL"]
ignore = ["B008"] # Ignore Depends() warnings for FastAPI
[tool.ruff.lint.isort]
known-third-party = ["fastapi", "sqlmodel", "pydantic"]
3. Set up Pre-commit (.pre-commit-config.yaml)
repos:
- repo:
rev: v0.11.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo:
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
A simple pre-commit install command enabled the hooks
4. Install Pre-commit Hook
pre-commit install
Real-World Examples
Before/After: Proper Exception Handling
# Before
try:
data = crud.read(model_name=Menu, id=menu_id)
except Exception as e:
print(f"DB error: {e}")
raise HTTPException(status_code=500, detail="Database error")
# After (with Ruff fixes)
try:
data = crud.read(model_name=Menu, id=menu_id)
except Exception as e:
logger.error(f"DB error: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail="Database error") from e
Before/After: Import Sorting
# Before
import random
from fastapi import APIRouter
import logging
from typing import Optional
from app.models import Menu
# After (auto-fixed by Ruff)
import logging
import random
from typing import Optional
from fastapi import APIRouter
from app.models import Menu
Handling Failed Checks
When you see this error:
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- files were modified by this hook
Fixing .github/workflows/ci-test.yml
Simply add the changes and retry:
git add .
git commit -m "Your message" # Try again
CI Integration
We updated our GitHub workflow to use Ruff:
# .github/workflows/ci-test.yml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install -r requirements.txt
- run: ruff check .
Manual Fixes
Check specific files:
# Find issues
ruff check app/routes/
# Auto-fix issues
ruff check --fix app/routes/
# Run all pre-commit hooks manually
pre-commit run --all-files
Results: The Numbers Tell the Story
Our refactoring achieved impressive results:
More importantly, our team now spends less time on formatting issues and more time on application logic. Debugging production issues has become significantly easier with proper logging and exception chaining.
The most valuable outcome? New developers can contribute clean, consistent code from day one without memorizing all our style conventions. The tools do the heavy lifting automatically.
This refactoring wasn't just about prettier code—it was about building a foundation for better software engineering practices that will serve us well as our codebase continues to grow.
Our FastAPI menu service had grown rapidly, leading to inconsistent code quality across the team. Print statements were scattered everywhere, error handling was inconsistent, and code reviews spent too much time on formatting issues.
# Bad practices we needed to fix
def process_order(order_id):
try:
print(f"Processing order {order_id}")
result = api.get_order(order_id)
print(result)
return result
except Exception as e:
print(f"Error: {e}") # No logging, lost when deployed
raise HTTPException(status_code=500, detail="Failed") # Lost original exception
The Solution: Ruff + Pre-commit
We chose Ruff for its speed (100x faster than flake8) and auto-fixing capabilities, combined with pre-commit for automation. This powerful combination enforces code quality before code even reaches the repository.
1. Setting Up the Tools
First, we added the necessary dependencies:
pip install ruff==0.11.0 pre-commit==4.1.0
Then created two key configuration files:
2. Configure Ruff (pyproject.toml)
[tool.ruff.lint]
select = ["E", "F", "B", "I"]
fixable = ["ALL"]
ignore = ["B008"] # Ignore Depends() warnings for FastAPI
[tool.ruff.lint.isort]
known-third-party = ["fastapi", "sqlmodel", "pydantic"]
3. Set up Pre-commit (.pre-commit-config.yaml)
repos:
- repo:
rev: v0.11.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo:
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
A simple pre-commit install command enabled the hooks
4. Install Pre-commit Hook
pre-commit install
Real-World Examples
Before/After: Proper Exception Handling
# Before
try:
data = crud.read(model_name=Menu, id=menu_id)
except Exception as e:
print(f"DB error: {e}")
raise HTTPException(status_code=500, detail="Database error")
# After (with Ruff fixes)
try:
data = crud.read(model_name=Menu, id=menu_id)
except Exception as e:
logger.error(f"DB error: {str(e)}", exc_info=True)
raise HTTPException(status_code=500, detail="Database error") from e
Before/After: Import Sorting
# Before
import random
from fastapi import APIRouter
import logging
from typing import Optional
from app.models import Menu
# After (auto-fixed by Ruff)
import logging
import random
from typing import Optional
from fastapi import APIRouter
from app.models import Menu
Handling Failed Checks
When you see this error:
trim trailing whitespace.................................................Failed
- hook id: trailing-whitespace
- files were modified by this hook
Fixing .github/workflows/ci-test.yml
Simply add the changes and retry:
git add .
git commit -m "Your message" # Try again
CI Integration
We updated our GitHub workflow to use Ruff:
# .github/workflows/ci-test.yml
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install -r requirements.txt
- run: ruff check .
Manual Fixes
Check specific files:
# Find issues
ruff check app/routes/
# Auto-fix issues
ruff check --fix app/routes/
# Run all pre-commit hooks manually
pre-commit run --all-files
Results: The Numbers Tell the Story
Our refactoring achieved impressive results:
- 143 lines removed
- 198 lines added
- 20 files modified
- 0 print statements remaining
- 100% consistent exception handling
More importantly, our team now spends less time on formatting issues and more time on application logic. Debugging production issues has become significantly easier with proper logging and exception chaining.
The most valuable outcome? New developers can contribute clean, consistent code from day one without memorizing all our style conventions. The tools do the heavy lifting automatically.
This refactoring wasn't just about prettier code—it was about building a foundation for better software engineering practices that will serve us well as our codebase continues to grow.