smithery.ai

backend-python

Modern Python backend stack: FastAPI, SQLAlchemy 2.0, Pydantic v2, uv, ruff. Use when: building Python APIs, async services, or working with Python backend code. "python api", "async python".

First seen Mar 21, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,570 B
  • docs SUMMARY.md 295 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

Python Backend Stack

Live docs: Add use context7 to prompt for up-to-date FastAPI, SQLAlchemy, Pydantic documentation.

Tooling (2025)

Tool Purpose Why
uv Package manager 10-100x faster than pip
ruff Linter + formatter Replaces black, isort, flake8
FastAPI Web framework Async, auto-docs, Pydantic
SQLAlchemy 2.0 ORM Async support, type hints
Pydantic v2 Validation 5-50x faster than v1
pytest Testing See [testing.md](references/testing.md)

Project Setup

# Initialize
uv init my-api
cd my-api
uv add fastapi sqlalchemy[asyncio] pydantic pydantic-settings
uv add --dev ruff pytest pytest-asyncio httpx

# pyproject.toml
[tool.ruff]
line-length = 100
select = ["E", "F", "I", "N", "UP", "B", "A", "C4", "SIM"]

[tool.ruff.format]
quote-style = "double"

[tool.pytest.ini_options]
asyncio_mode = "auto"

Project Structure

src/
├── main.py              # FastAPI app
├── config.py            # Settings (pydantic-settings)
├── db/
│   ├── __init__.py
│   ├── engine.py        # Async engine + session
│   └── models.py        # SQLAlchemy models
├── api/
│   ├── __init__.py
│   ├── deps.py          # Dependencies (get_db, get_user)
│   └── routes/
│       ├── __init__.py
│       ├── auth.py
│       └── users.py
├── schemas/             # Pydantic models
│   ├── __init__.py
│   └── user.py
└── services/            # Business logic
    └── user.py
tests/
├── conftest.py
└── test_users.py

FastAPI Patterns

Basic App

from fastapi import FastAPI
from contextlib import asynccontextmanager

@asynccontextmanager
async def lifespan(app: FastAPI):
    # Startup
    await init_db()
    yield
    # Shutdown
    await close_db()

app = FastAPI(lifespan=lifespan)

Route with Dependencies

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession

router = APIRouter(prefix="/users", tags=["users"])

@router.get("/{user_id}", response_model=UserOut)
async def get_user(
    user_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    user = await db.get(User, user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    return user

Pydantic Schemas

from pydantic import BaseModel, EmailStr, Field
from datetime import datetime

class UserCreate(BaseModel):
    email: EmailStr
    name: str = Field(min_length=1, max_length=100)

class UserOut(BaseModel):
    id: int
    email: str
    name: str
    created_at: datetime

    model_config = {"from_attributes": True}  # For ORM mode

Settings

from pydantic_settings import BaseSettings
from functools import lru_cache

class Settings(BaseSettings):
    database_url: str
    secret_key: str
    debug: bool = False

    model_config = {"env_file": ".env"}

@lru_cache
def get_settings() -> Settings:
    return Settings()

SQLAlchemy 2.0 Async

Engine Setup

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, DeclarativeBase

engine = create_async_engine(
    "postgresql+asyncpg://user:pass@localhost/db",
    echo=False,
    pool_size=5,
    max_overflow=10,
)

AsyncSessionLocal = sessionmaker(
    engine, class_=AsyncSession, expire_on_commit=False
)

class Base(DeclarativeBase):
    pass

Models

from sqlalchemy import String, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from datetime import datetime

class User(Base):
    __tablename__ = "users"

    id: Mapped[int] = mapped_column(primary_key=True)
    email: Mapped[str] = mapped_column(String(255), unique=True, index=True)
    name: Mapped[str] = mapped_column(String(100))
    created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)

    posts: Mapped[list["Post"]] = relationship(back_populates="author")

Database Dependency

from typing import AsyncGenerator

async def get_db() -> AsyncGenerator[AsyncSession, None]:
    async with AsyncSessionLocal() as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise

Queries

from sqlalchemy import select
from sqlalchemy.orm import selectinload

# Get one
user = await db.get(User, user_id)

# Query with filter
stmt = select(User).where(User.email == email)
result = await db.execute(stmt)
user = result.scalar_one_or_none()

# Eager load relationships
stmt = select(User).options(selectinload(User.posts)).where(User.id == user_id)

# Pagination
stmt = select(User).offset(skip).limit(limit).order_by(User.created_at.desc())
result = await db.execute(stmt)
users = result.scalars().all()

Error Handling

from fastapi import HTTPException, status
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
    return JSONResponse(
        status_code=422,
        content={"error": {"code": "VALIDATION_ERROR", "details": exc.errors()}},
    )

# Custom exceptions
class NotFoundError(Exception):
    def __init__(self, resource: str, id: int):
        self.resource = resource
        self.id = id

@app.exception_handler(NotFoundError)
async def not_found_handler(request, exc):
    return JSONResponse(
        status_code=404,
        content={"error": {"message": f"{exc.resource} {exc.id} not found"}},
    )

Anti-patterns

Don't Do Instead
pip install uv add
black + isort + flake8 ruff
SQLAlchemy 1.x style SQLAlchemy 2.0 with Mapped[]
Pydantic v1 Pydantic v2 (model_config, not Config)
Sync database calls Async with asyncpg/aiosqlite
Global DB session Dependency injection
Business logic in routes Services layer