halay08

python-patterns

0
0
# Install this skill:
npx skills add halay08/fullstack-agent-skills --skill "python-patterns"

Install specific skill from multi-skill repository

# Description

Python development principles and decision-making. Framework selection, async patterns, type hints, project structure. Teaches thinking, not copying.

# SKILL.md


name: python-patterns
description: Python development principles and decision-making. Framework selection, async patterns, type hints, project structure. Teaches thinking, not copying.
allowed-tools: Read, Write, Edit, Glob, Grep


Python Patterns

Python development principles and decision-making for 2025.
Learn to THINK, not memorize patterns.


โš ๏ธ How to Use This Skill

This skill teaches decision-making principles, not fixed code to copy.

  • ASK user for framework preference when unclear
  • Choose async vs sync based on CONTEXT
  • Don't default to same framework every time

1. Framework Selection (2025)

Decision Tree

What are you building?
โ”‚
โ”œโ”€โ”€ API-first / Microservices
โ”‚   โ””โ”€โ”€ FastAPI (async, modern, fast)
โ”‚
โ”œโ”€โ”€ Full-stack web / CMS / Admin
โ”‚   โ””โ”€โ”€ Django (batteries-included)
โ”‚
โ”œโ”€โ”€ Simple / Script / Learning
โ”‚   โ””โ”€โ”€ Flask (minimal, flexible)
โ”‚
โ”œโ”€โ”€ AI/ML API serving
โ”‚   โ””โ”€โ”€ FastAPI (Pydantic, async, uvicorn)
โ”‚
โ””โ”€โ”€ Background workers
    โ””โ”€โ”€ Celery + any framework

Comparison Principles

Factor FastAPI Django Flask
Best for APIs, microservices Full-stack, CMS Simple, learning
Async Native Django 5.0+ Via extensions
Admin Manual Built-in Via extensions
ORM Choose your own Django ORM Choose your own
Learning curve Low Medium Low

Selection Questions to Ask:

  1. Is this API-only or full-stack?
  2. Need admin interface?
  3. Team familiar with async?
  4. Existing infrastructure?

2. Async vs Sync Decision

When to Use Async

async def is better when:
โ”œโ”€โ”€ I/O-bound operations (database, HTTP, file)
โ”œโ”€โ”€ Many concurrent connections
โ”œโ”€โ”€ Real-time features
โ”œโ”€โ”€ Microservices communication
โ””โ”€โ”€ FastAPI/Starlette/Django ASGI

def (sync) is better when:
โ”œโ”€โ”€ CPU-bound operations
โ”œโ”€โ”€ Simple scripts
โ”œโ”€โ”€ Legacy codebase
โ”œโ”€โ”€ Team unfamiliar with async
โ””โ”€โ”€ Blocking libraries (no async version)

The Golden Rule

I/O-bound โ†’ async (waiting for external)
CPU-bound โ†’ sync + multiprocessing (computing)

Don't:
โ”œโ”€โ”€ Mix sync and async carelessly
โ”œโ”€โ”€ Use sync libraries in async code
โ””โ”€โ”€ Force async for CPU work

Async Library Selection

Need Async Library
HTTP client httpx
PostgreSQL asyncpg
Redis aioredis / redis-py async
File I/O aiofiles
Database ORM SQLAlchemy 2.0 async, Tortoise

3. Type Hints Strategy

When to Type

Always type:
โ”œโ”€โ”€ Function parameters
โ”œโ”€โ”€ Return types
โ”œโ”€โ”€ Class attributes
โ”œโ”€โ”€ Public APIs

Can skip:
โ”œโ”€โ”€ Local variables (let inference work)
โ”œโ”€โ”€ One-off scripts
โ”œโ”€โ”€ Tests (usually)

Common Type Patterns

# These are patterns, understand them:

# Optional โ†’ might be None
from typing import Optional
def find_user(id: int) -> Optional[User]: ...

# Union โ†’ one of multiple types
def process(data: str | dict) -> None: ...

# Generic collections
def get_items() -> list[Item]: ...
def get_mapping() -> dict[str, int]: ...

# Callable
from typing import Callable
def apply(fn: Callable[[int], str]) -> str: ...

Pydantic for Validation

When to use Pydantic:
โ”œโ”€โ”€ API request/response models
โ”œโ”€โ”€ Configuration/settings
โ”œโ”€โ”€ Data validation
โ”œโ”€โ”€ Serialization

Benefits:
โ”œโ”€โ”€ Runtime validation
โ”œโ”€โ”€ Auto-generated JSON schema
โ”œโ”€โ”€ Works with FastAPI natively
โ””โ”€โ”€ Clear error messages

4. Project Structure Principles

Structure Selection

Small project / Script:
โ”œโ”€โ”€ main.py
โ”œโ”€โ”€ utils.py
โ””โ”€โ”€ requirements.txt

Medium API:
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ main.py
โ”‚   โ”œโ”€โ”€ models/
โ”‚   โ”œโ”€โ”€ routes/
โ”‚   โ”œโ”€โ”€ services/
โ”‚   โ””โ”€โ”€ schemas/
โ”œโ”€โ”€ tests/
โ””โ”€โ”€ pyproject.toml

Large application:
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ myapp/
โ”‚       โ”œโ”€โ”€ core/
โ”‚       โ”œโ”€โ”€ api/
โ”‚       โ”œโ”€โ”€ services/
โ”‚       โ”œโ”€โ”€ models/
โ”‚       โ””โ”€โ”€ ...
โ”œโ”€โ”€ tests/
โ””โ”€โ”€ pyproject.toml

FastAPI Structure Principles

Organize by feature or layer:

By layer:
โ”œโ”€โ”€ routes/ (API endpoints)
โ”œโ”€โ”€ services/ (business logic)
โ”œโ”€โ”€ models/ (database models)
โ”œโ”€โ”€ schemas/ (Pydantic models)
โ””โ”€โ”€ dependencies/ (shared deps)

By feature:
โ”œโ”€โ”€ users/
โ”‚   โ”œโ”€โ”€ routes.py
โ”‚   โ”œโ”€โ”€ service.py
โ”‚   โ””โ”€โ”€ schemas.py
โ””โ”€โ”€ products/
    โ””โ”€โ”€ ...

5. Django Principles (2025)

Django Async (Django 5.0+)

Django supports async:
โ”œโ”€โ”€ Async views
โ”œโ”€โ”€ Async middleware
โ”œโ”€โ”€ Async ORM (limited)
โ””โ”€โ”€ ASGI deployment

When to use async in Django:
โ”œโ”€โ”€ External API calls
โ”œโ”€โ”€ WebSocket (Channels)
โ”œโ”€โ”€ High-concurrency views
โ””โ”€โ”€ Background task triggering

Django Best Practices

Model design:
โ”œโ”€โ”€ Fat models, thin views
โ”œโ”€โ”€ Use managers for common queries
โ”œโ”€โ”€ Abstract base classes for shared fields

Views:
โ”œโ”€โ”€ Class-based for complex CRUD
โ”œโ”€โ”€ Function-based for simple endpoints
โ”œโ”€โ”€ Use viewsets with DRF

Queries:
โ”œโ”€โ”€ select_related() for FKs
โ”œโ”€โ”€ prefetch_related() for M2M
โ”œโ”€โ”€ Avoid N+1 queries
โ””โ”€โ”€ Use .only() for specific fields

6. FastAPI Principles

async def vs def in FastAPI

Use async def when:
โ”œโ”€โ”€ Using async database drivers
โ”œโ”€โ”€ Making async HTTP calls
โ”œโ”€โ”€ I/O-bound operations
โ””โ”€โ”€ Want to handle concurrency

Use def when:
โ”œโ”€โ”€ Blocking operations
โ”œโ”€โ”€ Sync database drivers
โ”œโ”€โ”€ CPU-bound work
โ””โ”€โ”€ FastAPI runs in threadpool automatically

Dependency Injection

Use dependencies for:
โ”œโ”€โ”€ Database sessions
โ”œโ”€โ”€ Current user / Auth
โ”œโ”€โ”€ Configuration
โ”œโ”€โ”€ Shared resources

Benefits:
โ”œโ”€โ”€ Testability (mock dependencies)
โ”œโ”€โ”€ Clean separation
โ”œโ”€โ”€ Automatic cleanup (yield)

Pydantic v2 Integration

# FastAPI + Pydantic are tightly integrated:

# Request validation
@app.post("/users")
async def create(user: UserCreate) -> UserResponse:
    # user is already validated
    ...

# Response serialization
# Return type becomes response schema

7. Background Tasks

Selection Guide

Solution Best For
BackgroundTasks Simple, in-process tasks
Celery Distributed, complex workflows
ARQ Async, Redis-based
RQ Simple Redis queue
Dramatiq Actor-based, simpler than Celery

When to Use Each

FastAPI BackgroundTasks:
โ”œโ”€โ”€ Quick operations
โ”œโ”€โ”€ No persistence needed
โ”œโ”€โ”€ Fire-and-forget
โ””โ”€โ”€ Same process

Celery/ARQ:
โ”œโ”€โ”€ Long-running tasks
โ”œโ”€โ”€ Need retry logic
โ”œโ”€โ”€ Distributed workers
โ”œโ”€โ”€ Persistent queue
โ””โ”€โ”€ Complex workflows

8. Error Handling Principles

Exception Strategy

In FastAPI:
โ”œโ”€โ”€ Create custom exception classes
โ”œโ”€โ”€ Register exception handlers
โ”œโ”€โ”€ Return consistent error format
โ””โ”€โ”€ Log without exposing internals

Pattern:
โ”œโ”€โ”€ Raise domain exceptions in services
โ”œโ”€โ”€ Catch and transform in handlers
โ””โ”€โ”€ Client gets clean error response

Error Response Philosophy

Include:
โ”œโ”€โ”€ Error code (programmatic)
โ”œโ”€โ”€ Message (human readable)
โ”œโ”€โ”€ Details (field-level when applicable)
โ””โ”€โ”€ NOT stack traces (security)

9. Testing Principles

Testing Strategy

Type Purpose Tools
Unit Business logic pytest
Integration API endpoints pytest + httpx/TestClient
E2E Full workflows pytest + DB

Async Testing

# Use pytest-asyncio for async tests

import pytest
from httpx import AsyncClient

@pytest.mark.asyncio
async def test_endpoint():
    async with AsyncClient(app=app, base_url="http://test") as client:
        response = await client.get("/users")
        assert response.status_code == 200

Fixtures Strategy

Common fixtures:
โ”œโ”€โ”€ db_session โ†’ Database connection
โ”œโ”€โ”€ client โ†’ Test client
โ”œโ”€โ”€ authenticated_user โ†’ User with token
โ””โ”€โ”€ sample_data โ†’ Test data setup

10. Decision Checklist

Before implementing:

  • [ ] Asked user about framework preference?
  • [ ] Chosen framework for THIS context? (not just default)
  • [ ] Decided async vs sync?
  • [ ] Planned type hint strategy?
  • [ ] Defined project structure?
  • [ ] Planned error handling?
  • [ ] Considered background tasks?

11. Anti-Patterns to Avoid

โŒ DON'T:

  • Default to Django for simple APIs (FastAPI may be better)
  • Use sync libraries in async code
  • Skip type hints for public APIs
  • Put business logic in routes/views
  • Ignore N+1 queries
  • Mix async and sync carelessly

โœ… DO:

  • Choose framework based on context
  • Ask about async requirements
  • Use Pydantic for validation
  • Separate concerns (routes โ†’ services โ†’ repos)
  • Test critical paths

Remember: Python patterns are about decision-making for YOUR specific context. Don't copy codeโ€”think about what serves your application best.

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.