Write production-quality Python code following PEP 8, type safety, and comprehensive testing standards. Use for any Python coding task including new features, refactoring, debugging, or building complete applications.
Shared Knowledge: This skill builds on brain/knowledge/general-problem-solving.md, brain/knowledge/coding-general.md, and brain/knowledge/testing.md. Always apply those principles alongside the language-specific guidance below.
Language-Specific Testing: See testing-guidelines.md in this skill folder for framework-specific testing patterns.
⛔ Hard Rules: Non-Negotiable
These bind every line of Python you add or modify. They are the ONE exception to "match the
repository's conventions": when the repo itself violates one of them, the rule still wins for the
code you write. Leave existing violations in untouched code alone (never mass-refactor), but nothing
new may break these. Softer conflicts between repo patterns and this skill go to the user per
brain/knowledge/coding-general.md §2, "When the repo and the guidelines disagree". Re-read this
list before writing code, and walk it again at handoff (§5).
The toolchain is ruff, ruff format, and mypy, and all of it runs green before handoff.ruff check, ruff format --check, mypy, and pytest clean on the code you touched, even in
a repo configured for black/isort/flake8/pylint (run those too if the repo's CI does; they don't
replace this gate). Never silence a finding to get there: a # noqa or # type: ignore without
a specific rule code and a real reason is a violation, not a fix.
Type hints on every function signature you write, parameters and return type, public or
private, in modern syntax: list[str], dict[str, int], X | None. Never import List,
Dict, Optional, or Union from typing for new code unless the project pins a Python
version that still needs them (below 3.10).
Docstrings on every public module, class, and function (Google or NumPy style, matching the
repo's), with Args:, Returns:, and Raises: where they apply.
Test files mirror the source package layout under tests/; never flatten them to the root.
A test for src/app/services/orders.py lives at tests/services/test_orders.py, and you create
the folders as you add each file. Scaffolding the suite yourself is not an exception: an empty
tests/ directory is exactly where files end up dumped at the root.
Pickle-format model and data files are untrusted code, not data.torch.load,
joblib.load, and fairseq-style checkpoints execute arbitrary code at load time: load only from
trusted sources, prefer safetensors, and pass weights_only=True where the call supports it.
File size: split new code into a new module; never mass-refactor an existing file for size. A
.py file you create, or a pre-existing one your change grows across 1,500 lines (the hard cap;
the warn tier starts at 800), goes into a new cohesive module instead of sailing past the cap. The
per-language tier table is in brain/knowledge/coding-general.md §3 (File size). This binds your
code only: a file already over the cap stays untouched for size; route your addition into a new
module and name the oversized file in the handoff. Test files (tests/ trees, test_*.py,
*_test.py, conftest.py) are warn-only, never a hard failure. The new-code quality gate (§5)
enforces the cap.
Toolchain commands run through the project's environment manager, never a guessed
interpreter. Detect the manager from the lockfile and prefix every tool invocation with its
runner: uv run when uv.lock is present (uv run mypy src/), poetry run for poetry.lock,
pipenv run for Pipfile.lock. With none of those, use the project venv's interpreter as
python -m <tool>. Never call a tool's entry-point binary out of .venv/Scripts or .venv/bin
by path, never fall back to a globally installed copy, and never install into whichever
environment happens to be active: a missing tool is added through the manager (uv add --dev,
poetry add --group dev) or surfaced to the user.
1. Code Style & Standards
PEP 8 Compliance:
4 spaces for indentation (never tabs)
Maximum line length: 88 characters (the ruff format default)
Two blank lines between top-level definitions
Imports: standard library, third-party, local (separated by blank lines; ruff check enforces the ordering via its isort rules)
Naming Conventions:
snake_case for functions, variables, modules
PascalCase for classes
UPPER_CASE for constants
Type Hints (modern syntax; Hard Rule 2):
def process_data(
items: list[str],
config: dict[str, int],
timeout: float | None = None,
) -> dict[str, int | str]:
"""Process items according to configuration."""
...
Documentation:
Use Google or NumPy style docstrings
Document all public APIs (classes, functions, modules)
Include: purpose, parameters (Args:), return values (Returns:), exceptions (Raises:), and an example where useful
2. Implementation Guidelines
Error Handling:
# Use specific exceptions
raise ValueError(f"Invalid user_id: {user_id}")
# Provide context in error messages
try:
result = risky_operation()
except SpecificError as e:
logger.error(f"Operation failed for user {user_id}: {e}")
raise
Resource Management:
# Use context managers (built-in, or @contextlib.contextmanager for custom resources)
with open(file_path) as f:
data = f.read()
Common Utilities:
If the project has shared utility libraries (retry, logging, caching helpers), prefer them over reimplementing common patterns.
ML model files:
Weight files in pickle-based formats (torch.load, joblib.load, fairseq checkpoints) execute
arbitrary code at load time. Treat them as untrusted code, not data: load only from trusted sources,
prefer safetensors, and pass weights_only=True to torch.load where the call supports it.
3. Performance
Caching:
from functools import cache, lru_cache
@cache # For functions with hashable arguments
def fibonacci(n: int) -> int:
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
@lru_cache(maxsize=128) # For size-limited cache
def expensive_computation(param: str) -> dict:
...
Efficient Data Structures:
Use generators for large datasets: (x for x in range(1000000))
Choose appropriate collections: set for membership, deque for queues
Use collections.defaultdict and collections.Counter where appropriate
Profiling Critical Code:
Profile with cProfile + pstats (sort by 'cumulative') before optimizing.
4. Testing
Use pytest with the Arrange-Act-Assert structure. Test happy paths, error conditions, and boundary values; aim for >80% coverage on critical modules. Test files mirror the source package layout under a top-level tests/ directory and are never dumped flat at the tests/ root, even in a suite you created yourself. See testing-guidelines.md in this skill folder for the test layout, fixtures, parametrization, mocking, and coverage detail. The new-code quality gate at scripts/python_quality_gate.py checks diff coverage before handoff (run it with --skip-mutants); its mutation half is opt-in and runs only after the user has committed the work themselves and asked for it. See testing-guidelines.md §"New-code quality gate".
5. Quality Validation & Completion Checklist
Run these checks before marking work complete:
Walk the ⛔ Hard Rules block at the top item by item against your diff. These are the rules that regress; verify them by looking, not by assuming.
No lint errors: ruff check . (ruff carries the flake8, isort, pylint-style, and bandit-style rule sets)
Formatting clean: ruff format --check . (run ruff format . to fix)
Type checking clean: mypy src/
Tests pass with coverage (>=80% for critical paths): pytest --cov=src --cov-report=term-missing
Every command above ran through the project's environment manager (uv run / poetry run / pipenv run, or the venv's python -m), not a .venv binary by path or a global install (Hard Rule 7)
Coverage half of the new-code quality gate run where the toolchain is available (scripts/python_quality_gate.py --skip-mutants in this skill folder). The mutation half is optional: never commit anything yourself; ask the user whether they want it and to commit the changes themselves first (see testing-guidelines.md §"New-code quality gate")
File-size gate clean: no new or cap-crossing production file hits the 1,500-line cap (warn at 800), and new code goes into a new module rather than growing a file past the cap (Hard Rule 6). The gate reports exit code 4 on a cap crossing and runs on git and the filesystem alone, so it works even where pytest is absent. Ruff has no file- or module-length rule; a greenfield project wanting a related lint signal can enable the function-level PLR0915 (too-many-statements) and C901 (complexity), but neither caps a file.
Test files mirror the source package layout under tests/, not dumped flat at the root (Hard Rule 4)
Documentation complete (docstrings on every public API; Hard Rule 3)
Performance profiled if applicable
Code reviewed (use code-review skill)
Summarize the changes to the user, alongside any problems and caveats you can see with the new code.
When to Use This Skill
Writing new Python modules, classes, or functions
Refactoring existing Python code
Debugging Python applications
Setting up Python project structure
Creating API endpoints, CLI tools, or python packages
Building data processing pipelines
Implementing algorithms or business logic
Related Skills
code-review: For reviewing the current diff after implementation
branch-review: For reviewing all changes in the branch before merging
1---2name: python3description: Write production-quality Python code following PEP 8, type safety, and comprehensive testing standards. Use for any Python coding task including new features, refactoring, debugging, or building complete applications.4---56# Python78## Instructions910> **Shared Knowledge**: This skill builds on `brain/knowledge/general-problem-solving.md`, `brain/knowledge/coding-general.md`, and `brain/knowledge/testing.md`. Always apply those principles alongside the language-specific guidance below.11> **Language-Specific Testing**: See `testing-guidelines.md` in this skill folder for framework-specific testing patterns.1213### ⛔ Hard Rules: Non-Negotiable1415These bind every line of Python you add or modify. They are the ONE exception to "match the16repository's conventions": when the repo itself violates one of them, the rule still wins for the17code you write. Leave existing violations in untouched code alone (never mass-refactor), but nothing18new may break these. Softer conflicts between repo patterns and this skill go to the user per19`brain/knowledge/coding-general.md` §2, "When the repo and the guidelines disagree". Re-read this20list before writing code, and walk it again at handoff (§5).21221. **The toolchain is ruff, ruff format, and mypy, and all of it runs green before handoff.**23 `ruff check`, `ruff format --check`, `mypy`, and `pytest` clean on the code you touched, even in24 a repo configured for black/isort/flake8/pylint (run those too if the repo's CI does; they don't25 replace this gate). Never silence a finding to get there: a `# noqa` or `# type: ignore` without26 a specific rule code and a real reason is a violation, not a fix.272. **Type hints on every function signature you write**, parameters and return type, public or28 private, in modern syntax: `list[str]`, `dict[str, int]`, `X | None`. Never import `List`,29 `Dict`, `Optional`, or `Union` from `typing` for new code unless the project pins a Python30 version that still needs them (below 3.10).313. **Docstrings on every public module, class, and function** (Google or NumPy style, matching the32 repo's), with `Args:`, `Returns:`, and `Raises:` where they apply.334. **Test files mirror the source package layout under `tests/`; never flatten them to the root.**34 A test for `src/app/services/orders.py` lives at `tests/services/test_orders.py`, and you create35 the folders as you add each file. Scaffolding the suite yourself is not an exception: an empty36 `tests/` directory is exactly where files end up dumped at the root.375. **Pickle-format model and data files are untrusted code, not data.** `torch.load`,38 `joblib.load`, and fairseq-style checkpoints execute arbitrary code at load time: load only from39 trusted sources, prefer safetensors, and pass `weights_only=True` where the call supports it.406. **File size: split new code into a new module; never mass-refactor an existing file for size.** A41 `.py` file you create, or a pre-existing one your change grows across 1,500 lines (the hard cap;42 the warn tier starts at 800), goes into a new cohesive module instead of sailing past the cap. The43 per-language tier table is in `brain/knowledge/coding-general.md` §3 (File size). This binds your44 code only: a file already over the cap stays untouched for size; route your addition into a new45 module and name the oversized file in the handoff. Test files (`tests/` trees, `test_*.py`,46 `*_test.py`, `conftest.py`) are warn-only, never a hard failure. The new-code quality gate (§5)47 enforces the cap.487. **Toolchain commands run through the project's environment manager, never a guessed49 interpreter.** Detect the manager from the lockfile and prefix every tool invocation with its50 runner: `uv run` when `uv.lock` is present (`uv run mypy src/`), `poetry run` for `poetry.lock`,51 `pipenv run` for `Pipfile.lock`. With none of those, use the project venv's interpreter as52 `python -m <tool>`. Never call a tool's entry-point binary out of `.venv/Scripts` or `.venv/bin`53 by path, never fall back to a globally installed copy, and never install into whichever54 environment happens to be active: a missing tool is added through the manager (`uv add --dev`,55 `poetry add --group dev`) or surfaced to the user.5657### 1. Code Style & Standards5859**PEP 8 Compliance:**60- 4 spaces for indentation (never tabs)61- Maximum line length: 88 characters (the ruff format default)62- Two blank lines between top-level definitions63- Imports: standard library, third-party, local (separated by blank lines; `ruff check` enforces the ordering via its isort rules)6465**Naming Conventions:**66- `snake_case` for functions, variables, modules67- `PascalCase` for classes68- `UPPER_CASE` for constants6970**Type Hints** (modern syntax; Hard Rule 2):71```python72def process_data(73 items: list[str],74 config: dict[str, int],75 timeout: float | None = None,76) -> dict[str, int | str]:77 """Process items according to configuration."""78 ...79```8081**Documentation:**82- Use Google or NumPy style docstrings83- Document all public APIs (classes, functions, modules)84- Include: purpose, parameters (`Args:`), return values (`Returns:`), exceptions (`Raises:`), and an example where useful8586### 2. Implementation Guidelines8788**Error Handling:**89```python90# Use specific exceptions91raise ValueError(f"Invalid user_id: {user_id}")9293# Provide context in error messages94try:95 result = risky_operation()96except SpecificError as e:97 logger.error(f"Operation failed for user {user_id}: {e}")98 raise99```100101**Resource Management:**102```python103# Use context managers (built-in, or @contextlib.contextmanager for custom resources)104with open(file_path) as f:105 data = f.read()106```107108**Common Utilities:**109If the project has shared utility libraries (retry, logging, caching helpers), prefer them over reimplementing common patterns.110111**ML model files:**112Weight files in pickle-based formats (`torch.load`, `joblib.load`, fairseq checkpoints) execute113arbitrary code at load time. Treat them as untrusted code, not data: load only from trusted sources,114prefer safetensors, and pass `weights_only=True` to `torch.load` where the call supports it.115116### 3. Performance117118**Caching:**119```python120from functools import cache, lru_cache121122@cache # For functions with hashable arguments123def fibonacci(n: int) -> int:124 if n < 2:125 return n126 return fibonacci(n-1) + fibonacci(n-2)127128@lru_cache(maxsize=128) # For size-limited cache129def expensive_computation(param: str) -> dict:130 ...131```132133**Efficient Data Structures:**134- Use generators for large datasets: `(x for x in range(1000000))`135- Choose appropriate collections: `set` for membership, `deque` for queues136- Use `collections.defaultdict` and `collections.Counter` where appropriate137138**Profiling Critical Code:**139- Profile with `cProfile` + `pstats` (sort by `'cumulative'`) before optimizing.140141### 4. Testing142143Use **pytest** with the Arrange-Act-Assert structure. Test happy paths, error conditions, and boundary values; aim for >80% coverage on critical modules. Test files mirror the source package layout under a top-level `tests/` directory and are never dumped flat at the `tests/` root, even in a suite you created yourself. See `testing-guidelines.md` in this skill folder for the test layout, fixtures, parametrization, mocking, and coverage detail. The new-code quality gate at `scripts/python_quality_gate.py` checks diff coverage before handoff (run it with `--skip-mutants`); its mutation half is opt-in and runs only after the user has committed the work themselves and asked for it. See `testing-guidelines.md` §"New-code quality gate".144145### 5. Quality Validation & Completion Checklist146147Run these checks before marking work complete:148149- [ ] **Walk the ⛔ Hard Rules block at the top item by item against your diff.** These are the rules that regress; verify them by looking, not by assuming.150- [ ] No lint errors: `ruff check .` (ruff carries the flake8, isort, pylint-style, and bandit-style rule sets)151- [ ] Formatting clean: `ruff format --check .` (run `ruff format .` to fix)152- [ ] Type checking clean: `mypy src/`153- [ ] Tests pass with coverage (>=80% for critical paths): `pytest --cov=src --cov-report=term-missing`154- [ ] Every command above ran through the project's environment manager (`uv run` / `poetry run` / `pipenv run`, or the venv's `python -m`), not a `.venv` binary by path or a global install (Hard Rule 7)155- [ ] Coverage half of the new-code quality gate run where the toolchain is available (`scripts/python_quality_gate.py --skip-mutants` in this skill folder). The mutation half is optional: never commit anything yourself; ask the user whether they want it and to commit the changes themselves first (see `testing-guidelines.md` §"New-code quality gate")156- [ ] File-size gate clean: no new or cap-crossing production file hits the 1,500-line cap (warn at 800), and new code goes into a new module rather than growing a file past the cap (Hard Rule 6). The gate reports exit code 4 on a cap crossing and runs on git and the filesystem alone, so it works even where pytest is absent. Ruff has no file- or module-length rule; a greenfield project wanting a related lint signal can enable the function-level PLR0915 (too-many-statements) and C901 (complexity), but neither caps a file.157- [ ] Test files mirror the source package layout under `tests/`, not dumped flat at the root (Hard Rule 4)158- [ ] Documentation complete (docstrings on every public API; Hard Rule 3)159- [ ] Performance profiled if applicable160- [ ] Code reviewed (use `code-review` skill)161- [ ] Summarize the changes to the user, alongside any problems and caveats you can see with the new code.162163## When to Use This Skill164165- Writing new Python modules, classes, or functions166- Refactoring existing Python code167- Debugging Python applications168- Setting up Python project structure169- Creating API endpoints, CLI tools, or python packages170- Building data processing pipelines171- Implementing algorithms or business logic172173## Related Skills174175- `code-review`: For reviewing the current diff after implementation176- `branch-review`: For reviewing all changes in the branch before merging
Run npx skillmds@latest add brenordv/python 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.
Write production-quality Python code following PEP 8, type safety, and comprehensive testing standards. Use for any Python coding task including new features, refactoring, debugging, or building complete applications. It is listed under Productivity on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: executes scripts. 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.
brenordv (@brenordv) published this skill. Their other Agent Skills are listed on their SkillMD profile.