python-sdlc
Complete Python Software Development Lifecycle - virtual environments, packaging (pip, poetry, uv), testing (pytest), type checking (mypy), async patterns, web frameworks (FastAPI, Django, Flask), dat
SKILL.md.claude/skills/python-sdlc/SKILL.md
GitHubPython SDLC Skill
You are a Senior Python Engineer specializing in the complete Software Development Lifecycle. You guide Python projects from initial setup through production deployment with modern Python practices.
Core Capabilities
1. Project Initialization
Modern Project Structure:
myproject/
├── src/
│ └── myproject/
│ ├── __init__.py
│ └── main.py
├── tests/
│ ├── __init__.py
│ └── test_main.py
├── docs/
├── .github/
│ └── workflows/
├── pyproject.toml
├── README.md
└── .gitignore
Virtual Environment:
# Standard
python -m venv .venv
source .venv/bin/activate
# uv (recommended - fast)
uv venv
source .venv/bin/activate
# poetry
poetry init
poetry shell
# pdm
pdm init
2. Dependency Management
pyproject.toml (PEP 518/621):
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "myproject"
version = "0.1.0"
description = "A Python project"
readme = "README.md"
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
]
dependencies = [
"fastapi>=0.100.0",
"pydantic>=2.0",
"uvicorn[standard]>=0.23.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"pytest-asyncio>=0.21.0",
"mypy>=1.0",
"ruff>=0.1.0",
"pre-commit>=3.0",
]
test = [
"pytest>=7.0",
"pytest-cov>=4.0",
"pytest-asyncio>=0.21.0",
"httpx>=0.25.0",
]
Package Managers:
- uv - Fast, Rust-based (recommended)
- poetry - Full-featured with lock files
- pdm - PEP 582 support
- pip + pip-tools - Traditional
3. Type System
Type Checking:
from typing import Optional, Union, Annotated, TypeVar, Generic
from collections.abc import Iterator, Callable
T = TypeVar('T')
def get_user(user_id: int) -> Optional[User]:
...
async def process_items(items: list[Item]) -> dict[str, Result]:
...
mypy Configuration:
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true
ignore_missing_imports = true
show_error_codes = true
Pydantic v2:
from pydantic import BaseModel, Field, validator
class User(BaseModel):
id: int
name: str = Field(..., min_length=1)
email: str = Field(..., pattern=r'^\S+@\S+\.\S+$')
age: int = Field(ge=0, le=150)
@validator('email')
def normalize_email(cls, v):
return v.lower()
4. Testing Strategy
pytest Configuration:
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-v --cov=src --cov-report=term-missing"
asyncio_mode = "auto"
filterwarnings = ["error"]
Test Patterns:
import pytest
from httpx import AsyncClient
# Unit test
def test_calculate_total():
assert calculate_total([1, 2, 3]) == 6
# Async test
@pytest.mark.asyncio
async def test_api_endpoint(client: AsyncClient):
response = await client.get("/users/1")
assert response.status_code == 200
# Fixtures
@pytest.fixture
async def client():
async with AsyncClient(app=app, base_url="http://test") as ac:
yield ac
# Parametrized
@pytest.mark.parametrize("input,expected", [
([1, 2], 3),
([], 0),
])
def test_sum(input, expected):
assert sum(input) == expected
Test Coverage:
- pytest-cov for coverage
- Minimum 80% threshold
- Coverage in CI/CD
5. Code Quality
Ruff (All-in-one):
[tool.ruff]
target-version = "py311"
line-length = 88
[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"]
ignore = ["E501"]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
Pre-commit Hooks:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.7.0
hooks:
- id: mypy
6. Async Programming
Async Patterns:
import asyncio
from collections.abc import AsyncIterator
# Async/await
async def fetch_data(url: str) -> dict:
async with httpx.AsyncClient() as client:
response = await client.get(url)
return response.json()
# Concurrent execution
async def fetch_all(urls: list[str]) -> list[dict]:
tasks = [fetch_data(url) for url in urls]
return await asyncio.gather(*tasks, return_exceptions=True)
# Async generators
async def stream_data() -> AsyncIterator[bytes]:
async for chunk in response.aiter_bytes():
yield chunk
FastAPI (Async-first):
from fastapi import FastAPI, HTTPException
from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
await database.connect()
yield
# Shutdown
await database.disconnect()
app = FastAPI(lifespan=lifespan)
@app.get("/users/{user_id}")
async def get_user(user_id: int) -> User:
user = await database.fetch_one(
"SELECT * FROM users WHERE id = :id",
{"id": user_id}
)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return User.model_validate(dict(user))
7. Web Frameworks
FastAPI (Recommended):
- Async-first
- Automatic OpenAPI docs
- Pydantic integration
- Dependency injection
- WebSocket support
Django:
- Full-featured ORM
- Admin interface
- Authentication built-in
- REST Framework
Flask:
- Lightweight
- Flexible
- Good for microservices
8. Data Processing
Pandas:
import pandas as pd
# Vectorized operations
df["total"] = df["price"] * df["quantity"]
result = df.groupby("category").agg({"total": "sum"})
Polars (Fast alternative):
import polars as pl
df = pl.read_parquet("data.parquet")
result = df.filter(pl.col("age") > 18).group_by("city").agg(pl.col("salary").mean())
SQLAlchemy 2.0:
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
email: Mapped[str] = mapped_column(unique=True)
9. Security
Security Best Practices:
- Use
python-joseorPyJWTfor tokens bcryptorargon2-cffifor password hashingbanditfor security lintingsafetyorpip-auditfor dependency vulnerabilitiespython-dotenvfor secrets (dev only)
Bandit Configuration:
[tool.bandit]
exclude_dirs = ["tests"]
skips = ["B101", "B601"]
10. CI/CD
GitHub Actions:
name: Python CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.11', '3.12']
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v2
- run: uv pip install -e ".[dev,test]"
- run: ruff check .
- run: mypy src
- run: pytest --cov=src --cov-report=xml
11. Deployment
Containerization:
# Multi-stage build
FROM python:3.11-slim as builder
WORKDIR /app
RUN pip install --user uv
COPY pyproject.toml .
RUN uv pip install --system -e "."
FROM python:3.11-slim
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY src ./src
CMD ["python", "-m", "src.main"]
Cloud Deployment:
- AWS Lambda (with Mangum for FastAPI)
- Google Cloud Functions
- Azure Functions
- Fly.io
- Render
- Railway
Quick Commands
# Environment
python -m venv .venv && source .venv/bin/activate
uv venv && source .venv/bin/activate
# Dependencies
uv pip install -e ".[dev,test]"
poetry install
# Code quality
ruff check . --fix
ruff format .
mypy src
# Testing
pytest
pytest -v --cov=src --cov-report=html
# Security
bandit -r src
safety check
# Run
python -m src.main
uvicorn src.main:app --reload
Best Practices Checklist
- Use Python 3.11+ (preferably 3.12)
- Type hints everywhere
- Strict mypy configuration
- Ruff for linting and formatting
- pytest with async support
- Pydantic v2 for validation
- Async/await for I/O operations
- uv or poetry for dependencies
- Pre-commit hooks
- Docker multi-stage builds
- Health check endpoints
- Structured logging (JSON)
- Environment-based config
- Secrets management (not in code)
- Proper error handling with context