| name | python-standards |
| description | Python coding standards, conventions, and best practices. Use when writing, reviewing, or testing Python code. |
Python Coding Standards
New Project Preferences
When starting new Python projects, prefer:
- uv for package/environment management (fast, modern alternative to pip/venv)
- FastAPI for web APIs
- Pydantic for data validation and serialization
Style Guide
Follow PEP 8 with these project-specific additions:
Formatting
- Line length: 88 characters (Black default)
- Use Black for formatting, isort for imports
- Use double quotes for strings (Black default)
Naming Conventions
user_service.py
class UserService:
pass
def get_user_by_id(user_id: int) -> User:
active_users = []
MAX_RETRY_ATTEMPTS = 3
DEFAULT_TIMEOUT_SECONDS = 30
def _internal_helper():
pass
class Base:
def __private_method(self):
pass
Imports
import os
import sys
from pathlib import Path
import requests
from pydantic import BaseModel
from app.models import User
from app.services import UserService
Type Hints
Always use type hints for function signatures:
from typing import Optional, List, Dict, Any, Union
from collections.abc import Sequence, Mapping
def process_users(
users: List[User],
filter_active: bool = True,
metadata: Optional[Dict[str, Any]] = None,
) -> List[ProcessedUser]:
"""Process a list of users with optional filtering."""
...
def get_value(key: str) -> str | None:
...
Docstrings
Use Google-style docstrings:
def fetch_user(user_id: int, include_deleted: bool = False) -> User:
"""Fetch a user by their ID.
Args:
user_id: The unique identifier of the user.
include_deleted: Whether to include soft-deleted users.
Returns:
The User object if found.
Raises:
UserNotFoundError: If no user exists with the given ID.
DatabaseConnectionError: If the database is unavailable.
"""
...
Error Handling
try:
user = await fetch_user(user_id)
except UserNotFoundError:
logger.warning(f"User {user_id} not found")
raise HTTPException(status_code=404, detail="User not found")
except DatabaseConnectionError as e:
logger.error(f"Database error: {e}")
raise HTTPException(status_code=503, detail="Service unavailable")
class UserNotFoundError(Exception):
"""Raised when a user cannot be found."""
def __init__(self, user_id: int):
self.user_id = user_id
super().__init__(f"User with ID {user_id} not found")
Classes and Data
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class User:
id: int
email: str
name: str
created_at: datetime = field(default_factory=datetime.utcnow)
is_active: bool = True
from pydantic import BaseModel, EmailStr, validator
class UserCreate(BaseModel):
email: EmailStr
name: str
@validator('name')
def name_must_not_be_empty(cls, v):
if not v.strip():
raise ValueError('Name cannot be empty')
return v.strip()
Async Code
async def get_user_with_posts(user_id: int) -> UserWithPosts:
async with get_db_session() as session:
user = await session.get(User, user_id)
posts = await session.execute(
select(Post).where(Post.user_id == user_id)
)
return UserWithPosts(user=user, posts=posts.scalars().all())
async def fetch_all_data(user_id: int) -> tuple[User, list[Post], Settings]:
user, posts, settings = await asyncio.gather(
fetch_user(user_id),
fetch_posts(user_id),
fetch_settings(user_id),
)
return user, posts, settings
Testing
import pytest
from unittest.mock import Mock, patch, AsyncMock
@pytest.fixture
def mock_user():
return User(id=1, email="test@example.com", name="Test User")
@pytest.fixture
def mock_db_session():
with patch('app.database.get_session') as mock:
yield mock
@pytest.mark.asyncio
async def test_fetch_user(mock_db_session, mock_user):
mock_db_session.return_value.get = AsyncMock(return_value=mock_user)
result = await fetch_user(1)
assert result.id == 1
assert result.email == "test@example.com"
@pytest.mark.parametrize("input,expected", [
("hello", "HELLO"),
("World", "WORLD"),
("", ""),
])
def test_uppercase(input, expected):
assert uppercase(input) == expected
Project Commands
Check .claude/commands.md for project-specific commands. Common Python commands:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install -r requirements-dev.txt
black .
isort .
ruff check .
mypy .
pytest
pytest --cov=app --cov-report=html
pytest -x -v
Common Patterns
Context Managers
from contextlib import contextmanager, asynccontextmanager
@contextmanager
def temporary_file(suffix: str = ".tmp"):
path = Path(tempfile.mktemp(suffix=suffix))
try:
yield path
finally:
path.unlink(missing_ok=True)
@asynccontextmanager
async def get_db_connection():
conn = await create_connection()
try:
yield conn
finally:
await conn.close()
Logging
import logging
logger = logging.getLogger(__name__)
def process_order(order_id: int) -> None:
logger.info(f"Processing order {order_id}")
try:
logger.debug(f"Order {order_id} validated")
except ValidationError as e:
logger.warning(f"Order {order_id} validation failed: {e}")
raise
except Exception as e:
logger.exception(f"Unexpected error processing order {order_id}")
raise