DevSkyy python-patterns
Python best practices, security patterns, type hints, async patterns, and Pythonic idioms for FastAPI/Django projects.
install
source · Clone the upstream repo
git clone https://github.com/The-Skyy-Rose-Collection-LLC/DevSkyy
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/The-Skyy-Rose-Collection-LLC/DevSkyy "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/python-patterns" ~/.claude/skills/the-skyy-rose-collection-llc-devskyy-python-patterns && rm -rf "$T"
manifest:
.claude/skills/python-patterns/SKILL.mdsource content
Python Patterns
Type Hints
# ✅ GOOD: Fully typed with modern syntax (3.10+) from collections.abc import Sequence def process_items(items: Sequence[str], *, limit: int = 10) -> list[str]: """Process items with optional limit.""" return [item.strip() for item in items[:limit] if item] # ✅ GOOD: Optional and Union from typing import TypeAlias UserID: TypeAlias = int | str def get_user(user_id: UserID) -> dict[str, str] | None: ... # ❌ BAD: Missing types, using Any def process(data, limit=10): return [x for x in data]
Error Handling
# ✅ GOOD: Typed exceptions with context class ServiceError(Exception): def __init__(self, service: str, reason: str, *, correlation_id: str | None = None): self.service = service self.correlation_id = correlation_id super().__init__(f"{service}: {reason}") async def fetch_data(url: str) -> dict: try: async with httpx.AsyncClient() as client: response = await client.get(url, timeout=10.0) response.raise_for_status() return response.json() except httpx.TimeoutException as exc: raise ServiceError("fetch", f"Timeout: {url}") from exc except httpx.HTTPStatusError as exc: raise ServiceError("fetch", f"HTTP {exc.response.status_code}") from exc # ❌ BAD: Bare except, swallowed errors try: result = do_thing() except: pass
Immutable Patterns
from dataclasses import dataclass, replace from typing import Self # ✅ GOOD: Frozen dataclass — immutable by default @dataclass(frozen=True, slots=True) class Product: sku: str name: str price_cents: int active: bool = True def with_price(self, price_cents: int) -> Self: return replace(self, price_cents=price_cents) # ✅ GOOD: NamedTuple for simple data from typing import NamedTuple class Coordinate(NamedTuple): lat: float lon: float # ❌ BAD: Mutable default arguments def add_item(item: str, items: list[str] = []): # DANGEROUS items.append(item) return items # ✅ FIX: Use None sentinel def add_item(item: str, items: list[str] | None = None) -> list[str]: if items is None: items = [] return [*items, item]
Async Patterns (FastAPI)
import asyncio from contextlib import asynccontextmanager # ✅ GOOD: Proper async with concurrency control semaphore = asyncio.Semaphore(10) async def fetch_with_limit(url: str) -> dict: async with semaphore: async with httpx.AsyncClient() as client: response = await client.get(url) return response.json() # ✅ GOOD: Gather with error handling async def fetch_all(urls: list[str]) -> list[dict]: tasks = [fetch_with_limit(url) for url in urls] results = await asyncio.gather(*tasks, return_exceptions=True) return [r for r in results if not isinstance(r, Exception)] # ❌ BAD: Blocking in async context async def bad_endpoint(): import time time.sleep(5) # Blocks event loop! # ✅ FIX: Use async sleep or run_in_executor async def good_endpoint(): await asyncio.sleep(5) # Non-blocking
Security Patterns
import secrets import hashlib from pathlib import Path # ✅ GOOD: Parameterized queries async def get_user(db, user_id: int) -> dict | None: return await db.fetch_one("SELECT * FROM users WHERE id = $1", user_id) # ❌ BAD: SQL injection async def get_user_bad(db, user_id): return await db.fetch_one(f"SELECT * FROM users WHERE id = {user_id}") # ✅ GOOD: Safe path handling def safe_file_path(base_dir: str, filename: str) -> Path: base = Path(base_dir).resolve() target = (base / filename).resolve() if not target.is_relative_to(base): raise ValueError("Path traversal detected") return target # ✅ GOOD: Constant-time comparison for secrets def verify_token(provided: str, expected: str) -> bool: return secrets.compare_digest(provided, expected) # ✅ GOOD: Safe subprocess import subprocess def run_command(args: list[str]) -> str: result = subprocess.run(args, capture_output=True, text=True, check=True) return result.stdout # ❌ BAD: Shell injection subprocess.run(f"echo {user_input}", shell=True)
Pydantic Validation
from pydantic import BaseModel, Field, field_validator class CreateProductRequest(BaseModel): name: str = Field(..., min_length=1, max_length=200) price_cents: int = Field(..., gt=0, le=999_999_99) sku: str = Field(..., pattern=r"^[A-Z]{2,4}-\d{4,8}$") tags: list[str] = Field(default_factory=list, max_length=20) @field_validator("name") @classmethod def name_not_empty(cls, v: str) -> str: if not v.strip(): raise ValueError("Name cannot be blank") return v.strip()
Testing Patterns
import pytest from unittest.mock import AsyncMock, patch @pytest.mark.asyncio async def test_fetch_data_success(): """fetch_data returns parsed JSON on success.""" mock_response = AsyncMock() mock_response.json.return_value = {"key": "value"} mock_response.raise_for_status = AsyncMock() with patch("httpx.AsyncClient.get", return_value=mock_response): result = await fetch_data("https://api.example.com/data") assert result == {"key": "value"} @pytest.mark.asyncio async def test_fetch_data_timeout(): """fetch_data raises ServiceError on timeout.""" with patch("httpx.AsyncClient.get", side_effect=httpx.TimeoutException("timeout")): with pytest.raises(ServiceError, match="Timeout"): await fetch_data("https://api.example.com/data")
Pythonic Idioms
# Comprehensions over loops squares = [x ** 2 for x in range(10) if x % 2 == 0] # Context managers for resources with open("data.json") as f: data = json.load(f) # Walrus operator for check-and-use if (match := pattern.search(text)) is not None: process(match.group()) # Structural pattern matching (3.10+) match command: case {"action": "create", "data": data}: create(data) case {"action": "delete", "id": id_}: delete(id_) case _: raise ValueError(f"Unknown command: {command}")
Related
- Agent:
| Command:python-reviewer
| Skill:/code-review
,coding-standardssecurity-review