Modern Python development with uv, FastAPI, Pydantic, and clean architecture. Use for Python project setup, LLM app development, API design, testing strategy, and architecture decisions...
This skill provides modern Python development guidance for 2025, specializing in:
Designed for TypeScript developers who value simplicity and type safety.
Apply these principles to all Python development:
Claude should automatically use this skill when:
Choose structure based on project complexity:
| Complexity | Structure | When to Use |
|---|---|---|
| Script/PoC | Flat (single file) | Quick experiments, one-off scripts |
| Small App | 2-layer (domain + adapters) | MVPs, simple APIs |
| Production | 3-layer (domain + ports + adapters) | Multiple integrations, complex business logic |
Only add layers when complexity warrants it.
domain/ → Pure business logic (Pydantic models, services)
ports/ → Interfaces (Protocol classes) - add when needed
adapters/ → External integrations (API, DB, LLM clients)
Key principle: Start simple, refactor when pain points emerge.
See REFERENCE.md for detailed structures.
# 1. Initialize project
uv init my-project && cd my-project
# 2. Add dependencies
uv add fastapi pydantic uvicorn
uv add --dev pytest pytest-watch ruff mypy
# 3. Configure tools
# See REFERENCE.md for pyproject.toml configs
# Terminal 1: Watch tests (auto-run on changes)
uv run ptw -- tests/unit -v
# Terminal 2: Write code
# Follow Red -> Green -> Refactor cycle
uv run ruff check --fix . # Lint & auto-fix
uv run mypy src/ # Type check
uv run pytest --cov=src # Test with coverage
Always use Pydantic for LLM outputs to ensure type safety:
from pydantic import BaseModel, Field
class ExtractedInfo(BaseModel):
summary: str = Field(description="Brief summary")
key_points: list[str]
sentiment: Literal["positive", "neutral", "negative"]
Use Instructor for type-safe LLM calls:
import instructor
from openai import OpenAI
client = instructor.from_openai(OpenAI())
response = client.chat.completions.create(
model="gpt-4o",
response_model=ExtractedInfo,
messages=[{"role": "user", "content": text}]
)
# response is typed as ExtractedInfo ✓
See EXAMPLES.md for more patterns.
from fastapi import FastAPI, Depends
def get_service() -> UserService:
# Initialize dependencies here
return UserService(repo=get_repo())
@app.post("/users")
async def create_user(
request: CreateUserRequest,
service: UserService = Depends(get_service)
):
return service.create(request)
See EXAMPLES.md for complete examples.
tests/
├── unit/ # Fast, isolated, no I/O
├── integration/ # With real dependencies (DB, cache)
└── functional/ # E2E API tests
Coverage targets:
See EXAMPLES.md for test code.
-> None, list[str], dict[str, Any])Protocol over ABC for interfacespydantic.BaseModel for data classes with validationruff check --fix before commitsAny type unless absolutely necessary| TypeScript | Python Equivalent |
|---|---|
interface |
Protocol or BaseModel |
type |
TypeAlias or Literal |
zod |
pydantic |
npm/pnpm/yarn |
uv |
eslint + prettier |
ruff |
jest/vitest |
pytest |
express/fastify |
fastapi |
NestJS DI |
FastAPI Depends |
See EXAMPLES.md for detailed mapping.
When providing guidance:
Always prioritize working code over perfect architecture.
uv inituv addpyproject.toml configured (Ruff, mypy, pytest)pytest-watch)