Python Code Review Patterns
SkillFiles & storageProvides Python-specific code review rules for the dh code-reviewer agent. Activates on pyproject.toml or *.py file detection — enforces uv, ruff, ty, pytest, type annotation, error handling, and Python 3.11+ idioms including pathlib, match statements, and modern union syntax.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Python Code Review Patterns skill
What this skill tells your AI
The instructions your AI receives, as published by jamie-bitflight/claude_skills in plugins/development-harness/skills/code-review-python/SKILL.md and read by ahel’s review.
Stack-specific rules loaded by dh:code-reviewer when pyproject.toml or *.py files are detected.
Type Annotations
- All public function boundaries must have type annotations — parameters and return type
Anyis only acceptable with an inline comment explaining why a specific type cannot be usedTypedDictis required for dicts that cross module boundaries; plaindict[str, ...]is only acceptable within a single functionOptional[X]is legacy — useX | None(Python 3.10+ union syntax)Union[X, Y]is legacy — useX | Y- Return type
Nonemust be explicit on functions that have no return value but have side effects - Protocol classes are preferred over ABC for structural typing
Ruff Compliance
- Bare
except:is a blocking finding — must beexcept ExceptionType: print()in library code (non-CLI, non-script) is a blocking finding (T201) — uselogginginstead- Magic numbers in comparisons are a blocking finding (PLR2004) — extract to named constants
- Unused imports must be removed, not commented out
- f-strings are required for string interpolation —
%and.format()are legacy __all__must be defined in modules that have public API surface
ty Type Safety
- Unresolved imports indicate a missing
uv add— fix the import, not the type checker # ty: ignoresuppressions are prohibited — fix the code to satisfy tyty extra-pathsinpyproject.tomlmust stay in sync withpytestpythonpath- TypedDict nominal incompatibility across modules means the TypedDict should be defined in a shared location, not duplicated
pytest Patterns
- Test names follow behavioral naming:
test_<what>_when_<condition>_returns_<result>ortest_<what>_when_<condition>_raises_<exception> - Tests assert on observable behavior, not on implementation details (internal state, private methods)
- Integration tests hit real dependencies — mocking the thing under test is not a test
- Fixtures are preferred over test-class instance state
assert result is not Noneis not a meaningful assertion — assert the actual expected value- Tests are isolated — no shared mutable state between test functions
- Parametrize repetitive test cases with
@pytest.mark.parametrize - Each test file mirrors the module it tests:
src/foo/bar.py→tests/foo/test_bar.py
uv Usage
- All Python execution uses
uv run— barepythoninvocations are only acceptable in CI where the venv is pre-activated - New dependencies are added with
uv add— manual edits topyproject.tomldependencies without runninguv addleave the lockfile stale - Scripts with external dependencies declare PEP 723 inline metadata (
# /// script) and also add those deps viauv add --devfor IDE tooling uv run --scriptis used for standalone scripts with PEP 723 metadata
Error Handling
except Exception:is a blocking finding unless immediately followed by a re-raise or very specific logging- Empty
exceptblocks are a blocking finding — they swallow all errors silently - Exception messages must include enough context to diagnose without reading the source:
raise ValueError(f"Expected positive int, got {value!r}")notraise ValueError("invalid input") - Sentinel return values (returning
Noneor-1on error without raising) require a documented contract — silence must be intentional and documented
Modern Python 3.11+ Idioms
matchstatements are preferred for multi-branch dispatch on type or value (over longif/elifchains)pathlib.Pathis required for all file path operations —os.pathis legacytomllib(stdlib in 3.11+) is used for reading TOML — do not addtomlias a dependencydatetime.UTCis used instead ofdatetime.timezone.utc(Python 3.11+)ExceptionGroupandexcept*are used for concurrent exception handling where appropriatestr.removeprefix()andstr.removesuffix()replace manual slicing for prefix/suffix removal
Anti-Patterns
# WRONG: bare except
try:
do_thing()
except:
pass
# RIGHT: narrow except with action
try:
do_thing()
except ConnectionError as e:
logger.warning("Connection failed: %s", e)
raise
# WRONG: magic number
if status == 429:
...
# RIGHT: named constant
HTTP_TOO_MANY_REQUESTS = 429
if status == HTTP_TOO_MANY_REQUESTS:
...
# WRONG: os.path
import os
path = os.path.join(base, "config.toml")
# RIGHT: pathlib
from pathlib import Path
path = Path(base) / "config.toml"
Signals
- GitHub stars
- 66
- Forks
- 10
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
code-review-python- Source
- github.com/jamie-bitflight/claude_skills