pre-commit run --files <touched> — full hook chain (ruff + ruff-format + check-toml/yaml/merge-conflict + commitizen)
Phase 3 Tier B additional MCP verifications:
PostgreSQL MCP → Query DB state before/after
Legacy DB MCP → Query legacy databases for data verification
Implementation Rules (Phase 3)
Model structure — Domain-driven app/model/<domain>/{models.py, requests.py, responses.py}; cross-cutting types in model/common/. Separate *Request from *Response; never merge. When a response carries both DB-mapped fields AND computed/Python-only fields, split into a *DbRow base (SELECT columns only) + a *Model subclass that adds enrichment and @computed_field properties. Query builders and aggregation utilities receive the DB-row base. Composition over deep inheritance.
Settings — BaseSettings hierarchy, SecretStr for sensitive values, @lru_cache(maxsize=1) on the get_settings accessor. Tests that mutate env call get_settings.cache_clear().
Error handling — One global Exception handler in create_app + a per-domain-error handler in app/exception_handlers.py. Domain errors raised straight from service/repository; never wrapped in HTTPException. Handler detail strings hardcoded — never str(exc).
Async hygiene — except asyncio.CancelledError: raise separately from except Exception. Bounded asyncio.Queue for background work. asyncio.gather for independent queries. Heavy SDK clients constructed once at lifespan; blocking calls wrapped in asyncio.to_thread at adapter seams.
Minimize complexity — generators for large data, dict lookups over list scans, function length ~50-60 lines (soft guide; extract a helper past that).
Staff Review Configuration (Phase 4)
Patterns file path: Path to this skill's patterns.md
Python-Specific Rules
Type hints are mandatory — use Pydantic and strict typing per patterns.md.
All imports at module top — never inside a function or method.
Tests are required during implementation, not after — RED → GREEN → REFACTOR for every behavior.
No positive claim without running pytest tests/ -x -q.
Pydantic model fields with non-trivial types, defaults, or validators MUST have WHY comments explaining the rationale (data source format, business rule, cross-system constraint).
One global FastAPI Exception handler in create_app; never per-endpoint try / except → HTTPException.
TestClient(app, raise_server_exceptions=False) for any test that exercises the global handler.
Domain metadata (schema names, plant codes, environment-specific strings) lives on an Enum property — never hardcoded in N places.
Quality Checklist (Python-Specific)
Add these to the shared workflow's verification checklist:
Python 3.14 (built-in list[str] / dict[str, int], PEP 604 str | None; no from __future__ import annotations)
No from typing import List, Dict, Optional — use built-ins
Pydantic for all structured data; BaseSettings for configuration; SecretStr for sensitive values
Request/Response Pydantic models separated; *DbRow base + *Model subclass where DB-mapped and computed fields coexist
json_schema_extra used ONLY for OpenAPI examples — never for internal flags
One global Exception handler + per-domain handlers in app/exception_handlers.py; routes/services raise domain errors, never HTTPException
Sanitized 500 detail — never leak str(exc) to clients
except asyncio.CancelledError re-raised; never swallowed in except BaseException
Middleware order declared in one list and pinned by a test
@lru_cache(maxsize=1) on get_settings; tests call cache_clear() after env mutations
Heavy SDK clients constructed once at lifespan; blocking calls wrapped in asyncio.to_thread at adapter seams
Repository returns typed Pydantic models, not raw asyncpg.Record
Parameterized SQL ($1, $2) — no f-string interpolation of user input
Independent DB queries run concurrently (asyncio.gather)
No fetch-then-filter — JOIN or IN (subquery) in one round trip
asyncio_mode="auto" in pyproject.toml; markers golden, e2e, integration
TestClient(app, raise_server_exceptions=False) for tests that exercise the global handler
MagicMock(spec=Class) + AsyncMock for async methods; autouse fixture clears app.dependency_overrides
pytest tests/ -x -q passes (or alternative verification documented)
1---2name: python-dev3description: Python development. Use for Python, FastAPI, Pydantic, asyncpg, pytest, pandas, SQLAlchemy.4---56# Python Development78**Announce:** "I'm using the python-dev skill. Following the 4-phase workflow."910## MANDATORY: Read and Follow the Shared Workflow1112**You MUST read [workflow.md](../../shared/workflow.md) NOW** and follow ALL 4 phases defined there. The sections below provide Python-specific inputs for each phase.1314Read [patterns.md](patterns.md) during Phase 1.1516**If you lost workflow.md from context:** Re-read `../../shared/workflow.md` NOW before continuing.1718---1920## Python-Specific Configuration2122### Verification Commands (Phase 1 plan + Phase 3 verify)2324WORKFLOW STATE Verification line: `pytest tests/ -x -q, ruff check, ruff format --check`2526**Phase 3 Tier A commands:**27- `pytest tests/ -x -q` — default suite (unit + golden); excludes `e2e` and `integration` markers28- `pytest tests/ -x -q -m e2e` — e2e replay tests (no DB)29- `pytest tests/ -x -q -m integration` — integration tests (requires real DB)30- `pytest tests/ -x -q -m ''` — everything31- `ruff check .` — linting32- `ruff format --check .` — formatting33- `pre-commit run --files <touched>` — full hook chain (ruff + ruff-format + check-toml/yaml/merge-conflict + commitizen)3435**Phase 3 Tier B additional MCP verifications:**36- PostgreSQL MCP → Query DB state before/after37- Legacy DB MCP → Query legacy databases for data verification3839### Implementation Rules (Phase 3)4041- **Model structure** — Domain-driven `app/model/<domain>/{models.py, requests.py, responses.py}`; cross-cutting types in `model/common/`. Separate `*Request` from `*Response`; never merge. When a response carries both DB-mapped fields AND computed/Python-only fields, split into a `*DbRow` base (SELECT columns only) + a `*Model` subclass that adds enrichment and `@computed_field` properties. Query builders and aggregation utilities receive the DB-row base. Composition over deep inheritance.42- **Settings** — `BaseSettings` hierarchy, `SecretStr` for sensitive values, `@lru_cache(maxsize=1)` on the `get_settings` accessor. Tests that mutate env call `get_settings.cache_clear()`.43- **Error handling** — One global `Exception` handler in `create_app` + a per-domain-error handler in `app/exception_handlers.py`. Domain errors raised straight from service/repository; never wrapped in `HTTPException`. Handler `detail` strings hardcoded — never `str(exc)`.44- **Async hygiene** — `except asyncio.CancelledError: raise` separately from `except Exception`. Bounded `asyncio.Queue` for background work. `asyncio.gather` for independent queries. Heavy SDK clients constructed once at lifespan; blocking calls wrapped in `asyncio.to_thread` at adapter seams.45- **Minimize complexity** — generators for large data, dict lookups over list scans, function length ~50-60 lines (soft guide; extract a helper past that).4647### Staff Review Configuration (Phase 4)4849- **Patterns file path:** Path to this skill's `patterns.md`5051---5253## Python-Specific Rules5455- Type hints are mandatory — use Pydantic and strict typing per `patterns.md`.56- All imports at module top — never inside a function or method.57- Tests are required during implementation, not after — RED → GREEN → REFACTOR for every behavior.58- No positive claim without running `pytest tests/ -x -q`.59- Pydantic model fields with non-trivial types, defaults, or validators MUST have WHY comments explaining the rationale (data source format, business rule, cross-system constraint).60- One global FastAPI `Exception` handler in `create_app`; never per-endpoint `try / except → HTTPException`.61- `TestClient(app, raise_server_exceptions=False)` for any test that exercises the global handler.62- Domain metadata (schema names, plant codes, environment-specific strings) lives on an Enum property — never hardcoded in N places.6364---6566## Quality Checklist (Python-Specific)6768Add these to the shared workflow's verification checklist:6970- [ ] Python 3.14 (built-in `list[str]` / `dict[str, int]`, PEP 604 `str | None`; no `from __future__ import annotations`)71- [ ] No `from typing import List, Dict, Optional` — use built-ins72- [ ] Pydantic for all structured data; `BaseSettings` for configuration; `SecretStr` for sensitive values73- [ ] Request/Response Pydantic models separated; `*DbRow` base + `*Model` subclass where DB-mapped and computed fields coexist74- [ ] `json_schema_extra` used ONLY for OpenAPI examples — never for internal flags75- [ ] One global `Exception` handler + per-domain handlers in `app/exception_handlers.py`; routes/services raise domain errors, never `HTTPException`76- [ ] Sanitized 500 detail — never leak `str(exc)` to clients77- [ ] `except asyncio.CancelledError` re-raised; never swallowed in `except BaseException`78- [ ] Middleware order declared in one list and pinned by a test79- [ ] `@lru_cache(maxsize=1)` on `get_settings`; tests call `cache_clear()` after env mutations80- [ ] Heavy SDK clients constructed once at lifespan; blocking calls wrapped in `asyncio.to_thread` at adapter seams81- [ ] Repository returns typed Pydantic models, not raw `asyncpg.Record`82- [ ] Parameterized SQL (`$1`, `$2`) — no f-string interpolation of user input83- [ ] Independent DB queries run concurrently (`asyncio.gather`)84- [ ] No fetch-then-filter — JOIN or `IN (subquery)` in one round trip85- [ ] `asyncio_mode="auto"` in `pyproject.toml`; markers `golden`, `e2e`, `integration`86- [ ] `TestClient(app, raise_server_exceptions=False)` for tests that exercise the global handler87- [ ] `MagicMock(spec=Class)` + `AsyncMock` for async methods; autouse fixture clears `app.dependency_overrides`88- [ ] DataFrames copied before mutation; no `iterrows()`89- [ ] `ruff check .` passes; `ruff format --check .` passes90- [ ] Pre-commit (ruff + ruff-format + check-toml/yaml/merge-conflict + commitizen) passes on touched files91- [ ] `pytest tests/ -x -q` passes (or alternative verification documented)
Run npx skillmds@latest add concertonotes/python-dev in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Python development. Use for Python, FastAPI, Pydantic, asyncpg, pytest, pandas, SQLAlchemy. It is listed under Data & Analytics on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: makes network calls. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
ConcertoNotes (@concertonotes) published this skill. Their other Agent Skills are listed on their SkillMD profile.