Skip to main content
This page extends Common Rules with Python specific content.Applies to: **/*.py, **/*.pyi

Coding Style

Standards

  • Follow PEP 8 conventions
  • Use type annotations on all function signatures

Immutability

Prefer immutable data structures:
from dataclasses import dataclass

@dataclass(frozen=True)
class User:
    name: str
    email: str

Formatting

black

Code formatting

isort

Import sorting

ruff

Linting

Reference

python-patterns

See skill for comprehensive Python idioms and patterns

Testing

Framework

Use pytest as the testing framework.
pytest --cov=src --cov-report=term-missing

Test Organization

Use pytest.mark for test categorization:
import pytest

@pytest.mark.unit
def test_calculate_total():
    assert calculate_total([1, 2, 3]) == 6

@pytest.mark.integration
def test_database_connection():
    db = Database()
    assert db.connect() is True

Reference

python-testing

See skill for detailed pytest patterns and fixtures

Patterns

Protocol (Duck Typing)

from typing import Protocol

class Repository(Protocol):
    def find_by_id(self, id: str) -> dict | None: ...
    def save(self, entity: dict) -> dict: ...

Dataclasses as DTOs

from dataclasses import dataclass

@dataclass
class CreateUserRequest:
    name: str
    email: str
    age: int | None = None

Context Managers & Generators

Use context managers (with statement) for resource management:
with open('file.txt', 'r') as f:
    content = f.read()

# Custom context manager
from contextlib import contextmanager

@contextmanager
def transaction(db):
    try:
        yield db
        db.commit()
    except Exception:
        db.rollback()
        raise
Use generators for lazy evaluation and memory-efficient iteration:
def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

# Memory-efficient iteration over large datasets
for num in fibonacci(1000000):
    if num > 100:
        break

Reference

python-patterns

See skill for comprehensive patterns including decorators, concurrency, and package organization

Security

Secret Management

import os
from dotenv import load_dotenv

load_dotenv()

api_key = os.environ["OPENAI_API_KEY"]  # Raises KeyError if missing

Security Scanning

Use bandit for static security analysis:
bandit -r src/

Reference

django-security

See skill for Django-specific security guidelines (if applicable)

Hooks

PostToolUse Hooks

Configure in ~/.claude/settings.json:
Automatically runs black or ruff formatter on Python files after edits.
{
  "matcher": "Edit",
  "hooks": [{
    "type": "command",
    "command": "node format-python.js"
  }]
}
Example hook:
const { execFileSync } = require('child_process');

let data = '';
process.stdin.on('data', chunk => data += chunk);
process.stdin.on('end', () => {
  const input = JSON.parse(data);
  const filePath = input.tool_input?.file_path || '';
  
  if (/\.py$/.test(filePath)) {
    try {
      execFileSync('ruff', ['format', filePath], { stdio: 'pipe' });
    } catch (e) {}
  }
  
  console.log(data);
});
Runs type checker to catch type errors immediately.
mypy src/
# or
pyright src/

Warnings

Warn about print() statements in edited files (use logging module instead)
import logging

logger = logging.getLogger(__name__)

# WRONG: print() in production code
print(f"Processing user {user_id}")

# CORRECT: Use logging
logger.info(f"Processing user {user_id}")

Common Rules

Language-agnostic base rules

Hooks Overview

Complete hook system reference