Python development
Guide Python development with greenfield defaults and brownfield flexibility. Apply when writing, maintaining, or reviewing Python code to ensure consistency with modern tooling (uv, ruff, ty, pytest, pre-commit) and patterns (CLI separation, type safety, error handling).From its SKILL.md
npx -y skills add jmlrt/skills --skill python-developmentAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.7 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
Python Development
Apply this skill when writing, maintaining, or reviewing Python code.
Supporting Files
- tooling.md — Copy-paste templates for greenfield project setup (pyproject.toml, Makefile, .pre-commit-config.yaml)
- code-style.md — Style rules and conventions (naming, formatting, type hints, imports)
- patterns.md — Architecture patterns (CLI/core separation, exception hierarchy, error handling)
Mode Detection
Detect the mode from the user's request before acting:
| Signal | Mode |
|---|---|
| "write", "create", "add", "scaffold", "implement", "new" | WRITE |
| "fix", "refactor", "update", "change", "migrate", "improve" | MAINTAIN |
| "review", "check", "audit", "look at", "what do you think" | REVIEW |
WRITE Mode
Step 1: Greenfield or brownfield?
Greenfield (new project or new module in a greenfield project):
- Use templates from tooling.md verbatim — don't approximate
- Apply src/ layout, hatchling build system, full tooling stack
- Apply all rules below from the start
Brownfield (inheriting existing code):
- Read existing code first with Read/Grep before writing anything
- Match existing patterns — don't retrofit greenfield defaults
- Use the brownfield decision tree at the bottom of this file
Step 2: Apply these rules when writing any code
Functions and modules:
- Every function and module gets a docstring summary (one line is enough; add more lines only when behavior is non-obvious)
- Every function gets full type hints using modern syntax (
str | None,list[str], notOptional, notUnion) - See code-style.md for all style rules
Error handling:
- Raise domain exceptions in core logic, catch at the CLI layer — never both
- Always chain exceptions:
raise AppError("msg") from e - See patterns.md for exception hierarchy and CLI/core separation
Structure:
- Separate CLI layer (parse args + display output) from core layer (pure logic, no CLI imports)
- Use
pathlib.Pathfor all file operations — neveros.pathor string concatenation - Use
@dataclassfor any domain model with 2+ fields
Output:
- Default to
typer.echo— don't add Rich or logging unless the user asks for a--verboseflag
Config:
- Use
tomllib(stdlib) + TOML file — not Pydantic, not env vars - Env vars only for secrets or CI overrides
Tests:
- Class-based:
class TestFoo,def test_scenario conftest.pyfor shared fixturestmp_pathfor filesystem,monkeypatchfor env vars- Test core logic directly; test CLI only for argument parsing and exit codes
MAINTAIN Mode
- Read before writing — use Read/Grep to understand the existing code
- Match existing patterns — preserve the style even if it differs from greenfield defaults
- Run checks after editing — ask the user to run
make checkto validate - Don't change tooling unless the user explicitly asks
For brownfield codebases: apply only the brownfield decision tree below.
REVIEW Mode
Go through the code and report findings in two categories:
Blockers (must fix)
- Bare
except:orexcept Exceptionwithout re-raising - Unused imports or dead code
- Secrets or credentials hardcoded in source
Nits (suggest, don't block)
- Missing type hints on function signatures
- Missing docstrings on functions or modules
- Hardcoded values that should be module-level constants or config
- Exception not chained with
from ewhen re-raising -
os.pathor string paths instead ofpathlib.Path - Mutable default arguments (
def f(x=[])) - Wrong exception type (raising base
Exceptioninstead of domain-specific) - Tests touching real filesystem or env vars without
monkeypatch/tmp_path
When a blocker is found, grep for the same pattern across the codebase and report all instances.
Brownfield Decision Tree
Build system?
- Exists (Poetry, setup.cfg, etc.) → keep it
- Missing → migrate to hatchling
Python version?
- 3.11 or older → keep it, don't force upgrade
- 3.12+ → align with greenfield defaults
CLI framework?
- Click or Typer → already aligned, keep it
- argparse or custom → refactor only if actively developing
- No CLI → leave as-is
Type hints?
- 80%+ coverage → run
ty check --strict - <80% → run
ruff checkonly, skip ty - 0% → run tests only
Test count?
- 50+ tests → consider unit/cli split
- <50 → keep flat
tests/directory
Minimal acceptable setup for any brownfield project:
make install # install deps
make test # run tests
make lint # check style
make check # all of the above
Greenfield Checklist
-
.python-versionset to3.12 -
pyproject.tomlwith hatchling,requires-python = ">=3.12",[dependency-groups] dev -
Makefilewith:install,test,test-v,lint,format,fix,typecheck,check,clean -
.pre-commit-config.yamlwith ruff + ty hooks -
src/my_project/withcli.py,commands/,core/ -
tests/withconftest.py -
make install && make checkpasses before first commit -
pre-commit installenabled
See tooling.md for copy-paste templates.
What ships with it: 3 files
16.5 KB alongside SKILL.md
- code-style.md5.3 KB
- patterns.md7.0 KB
- tooling.md4.2 KB