This file provides comprehensive guidance to Claude Code when working with Python code in this repository.
Follow the PEP 8 style guide.
- Indentation: Use 4 spaces per indentation level. Avoid tabs.
- Maximum Line Length: Limit all lines to a maximum of 79 characters (72 for docstrings/comments).
- Blank Lines: Use two blank lines to separate top-level function and class definitions. Use one blank line to separate method definitions inside a class. Use blank lines sparingly within functions to indicate logical sections.
- Use PEP 484 type hints. Use the version that uses
dictinstead oftyping.Dict.
- Never create a file longer than 500 lines of code. If approaching this limit, refactor by splitting into modules.
- Functions should be under 50 lines with a single, clear responsibility.
- Classes should be under 100 lines and represent a single concept or entity.
- Organize code into clearly separated modules, grouped by feature or responsibility.
Use venv for dependencies.
python3 -m venv env
source env/bin/activate
pip install pip -U # Upgrade pip.
pip install -r requirements.txtUse Google-style docstrings for all public functions, classes, and modules:
def calculate_discount(
price: Decimal,
discount_percent: float,
min_amount: Decimal = Decimal("0.01")
) -> Decimal:
"""
Calculate the discounted price for a product.
Args:
price: Original price of the product
discount_percent: Discount percentage (0-100)
min_amount: Minimum allowed final price
Returns:
Final price after applying discount
Raises:
ValueError: If discount_percent is not between 0 and 100
ValueError: If final price would be below min_amount
Example:
>>> calculate_discount(Decimal("100"), 20)
Decimal('80.00')
"""- Variables and functions:
snake_case - Classes:
PascalCase - Constants:
UPPER_SNAKE_CASE - Private attributes/methods:
_leading_underscore - Type aliases:
PascalCase - Enum values:
UPPER_SNAKE_CASE
# Create custom exceptions for your domain
class PaymentError(Exception):
"""Base exception for payment-related errors."""
pass
class InsufficientFundsError(PaymentError):
"""Raised when account has insufficient funds."""
def __init__(self, required: Decimal, available: Decimal):
self.required = required
self.available = available
super().__init__(
f"Insufficient funds: required {required}, available {available}"
)
# Use specific exception handling
try:
process_payment(amount)
except InsufficientFundsError as e:
logger.warning(f"Payment failed: {e}")
return PaymentResult(success=False, reason="insufficient_funds")
except PaymentError as e:
logger.error(f"Payment error: {e}")
return PaymentResult(success=False, reason="payment_error")
# Use context managers for resource management
from contextlib import contextmanager
@contextmanager
def database_transaction():
"""Provide a transactional scope for database operations."""
conn = get_connection()
transaction = conn.begin_transaction()
try:
yield conn
transaction.commit()
except Exception:
transaction.rollback()
raise
finally:
conn.close()- Every module should have a docstring explaining its purpose
- Public functions must have complete docstrings
- Complex logic should have inline comments with
# Reason:prefix - Keep README.md updated with setup instructions and examples
- Maintain CHANGELOG.md for version history
from fastapi import APIRouter, HTTPException, status
from typing import List
router = APIRouter(prefix="/products", tags=["products"])
@router.get(
"/",
response_model=List[Product],
summary="List all products",
description="Retrieve a paginated list of all active products"
)
async def list_products(
skip: int = 0,
limit: int = 100,
category: Optional[str] = None
) -> List[Product]:
"""
Retrieve products with optional filtering.
- **skip**: Number of products to skip (for pagination)
- **limit**: Maximum number of products to return
- **category**: Filter by product category
"""
# Implementation here- Never commit secrets - use environment variables
- Validate all user input with Pydantic
- Use parameterized queries for database operations
- Implement rate limiting for APIs
- Keep dependencies updated with
uv - Use HTTPS for all external communications
- Implement proper authentication and authorization
from passlib.context import CryptContext
import secrets
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
"""Hash password using bcrypt."""
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
"""Verify a password against its hash."""
return pwd_context.verify(plain_password, hashed_password)
def generate_secure_token(length: int = 32) -> str:
"""Generate a cryptographically secure random token."""
return secrets.token_urlsafe(length)- PEP 8: https://pep8.org/
- PEP 484 (Type Hints): https://www.python.org/dev/peps/pep-0484/
- The Hitchhiker's Guide to Python: https://docs.python-guide.org/
- NEVER ASSUME OR GUESS - When in doubt, ask for clarification
- Always verify file paths and module names before use
- Keep CLAUDE.md updated when adding new patterns or dependencies
- Test your code - No feature is complete without tests
- Document your decisions - Future developers (including yourself) will thank you
main (protected) βββ PR βββ feature/your-feature β β deploy development
- git checkout main && git pull origin main
- git checkout -b feature/new-feature
- Make changes + tests
- git push origin feature/new-feature
- Create PR β Review β Merge to main
This document is a living guide. Update it as the project evolves and new patterns emerge.