Modern Python (3.10+) review checklist: typing, dataclasses/pydantic, async-await discipline, logging over print, exception chain, ruff+pyright. Use when writing or reviewing backend Python (async FastAPI/SQLAlchemy). Not for non-backend or pre-3.10 code. Output: typed, ruff/pyright-clean code.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add hmj1026/dhpk --skill dhpk-python-pro --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Dhpk Python Pro?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/hmj1026-dhpk-python-pro)More formats (shields.io, HTML) on the badges page.
---
name: dhpk-python-pro
description: 'Modern Python (3.10+) review checklist: typing, dataclasses/pydantic, async-await discipline, logging over print, exception chain, ruff+pyright. Use when writing or reviewing backend Python (async FastAPI/SQLAlchemy). Not for non-backend or pre-3.10 code. Output: typed, ruff/pyright-clean code.'
metadata:
dhpk-invocation-class: implicit-eligible
---
# Python Pro (3.10+)
Framework-agnostic guidance for modern, type-checked Python services. Assumes the
`python` dhpk module's tooling baseline (ruff for lint+format, pyright or mypy for
types, `uv run` as the default runner — all overridable). For web-API specifics see
the `fastapi` module; for tests see the `pytest` module.
## Typing discipline
- **Annotate every public function** (params + return). Prefer `X | None` over
`Optional[X]`, `list[str]` over `List[str]` (PEP 585 3.9+, PEP 604 3.10+).
- Run the type checker as a gate, not a suggestion. ccas runs **pyright strict**;
mypy is the alternative. Don't add `# type: ignore` without a reason comment.
- Model data with `@dataclass(slots=True)` or **pydantic** models, not bare dicts.
Pydantic at the I/O boundary (request/response, config); dataclasses for internal
value objects.
- Use `typing.Protocol` for structural interfaces and dependency-injection seams
(host-testable code) instead of inheritance.
## Async-await discipline
- Never call blocking I/O inside an `async def` coroutine — it stalls the event
loop. Wrap unavoidable blocking calls in `await asyncio.to_thread(...)`.
- Don't mix sync and async DB sessions. With SQLAlchemy 2.0 async, every query is
`await session.execute(...)`; never hold a session across `await` boundaries it
doesn't own.
- Guard external calls with timeouts (`asyncio.wait_for`, httpx `timeout=`); an
unbounded `await` is a latent hang. ccas isolates poison PDFs this way.
- Use `asyncio.TaskGroup` (3.11+) or `asyncio.gather` for fan-out; propagate
cancellation rather than swallowing `CancelledError`.
## Errors & logging
- **No `print()` in library/app code** — use the `logging` module (structured JSON
in ccas). `print` is for CLIs/scripts only. The post-edit hook flags stray prints.
- Define a project exception hierarchy (`class AppError(Exception)` → specific
subclasses). Raise specific, catch specific. Never `except Exception: pass` — log
with context and re-raise or convert. (See the silent-failure-hunter agent.)
- Preserve the chain: `raise NewError(...) from err`. Don't discard the original
traceback.
- Validate inputs at the boundary and fail fast with a descriptive message; don't
let a `None` or malformed value propagate three layers deep.
## Structure & idioms
- One responsibility per module; keep `__init__.py` thin. Layer
Controller/Router → Service → Repository (or your stack's equivalent).
- Dependency-inject collaborators (clients, sessions, clocks) so they're swappable
in tests — don't reach for module-level singletons inside business logic.
- Prefer comprehensions and generators over manual loops for transforms; prefer
`pathlib.Path` over `os.path`; prefer f-strings.
- Keep functions small; if a function needs a comment to explain a block, that
block usually wants to be its own named function.
## Tooling baseline (what the hooks enforce)
- `ruff check` (lint) + `ruff format` (formatting) — single tool, fast. ccas selects
rule families `E, F, I, N, W, UP`. See the `dhpk-python-static-checks` skill for the
selection strategy.
- Type checker on every commit (pyright/mypy). Coverage floor via pytest-cov.
- The `python` module's pre-commit gate runs ruff + format-check + type-check on
staged `.py`; `[skip-python-lint]` bypasses in an emergency.
## When NOT to Use
Not for non-Python work, frontend tasks, or codebases pinned to Python <=3.9
(the `X | None`, `slots=True`, and `TaskGroup` idioms here assume 3.10/3.11+).
For ruff/pyright config see `dhpk-python-static-checks`; for web-API specifics see
`dhpk-fastapi-pro`; for tests see `dhpk-pytest-async`.
## Output
Python that meets the checklist above: every public function annotated, data
modelled with dataclasses/pydantic, no blocking I/O in `async def`, no stray
`print`, a preserved exception chain — and that passes ruff + the type checker
clean.
## Verification
- `ruff check` and `ruff format --check` report no findings.
- `pyright` (strict) or `mypy` passes; no new `# type: ignore` without a reason.
- No `print()` in library/app code; `pytest --cov` meets the coverage floor.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!