wdm0006/python-skills/code-quality
Claude Code and agent skill by wdm0006/python-skills
- community
Checking that the SKILL.md file is still in the repository.
Improves Python library code quality through ruff linting, mypy type checking, Pythonic idioms, and refactoring. Use when reviewing code for quality issues, adding type hints, configuring static analysis tools, or refactoring Python library code.
Install
npx vskill@latest install wdm0006/python-skills/code-qualitySKILL.md
Python Code Quality
Quick Reference
| Tool | Purpose | Command | |
|---|---|---|---|
| ruff | Lint + format | ruff check src && ruff format src | |
| mypy | Type check | mypy src |
Ruff Configuration
Minimal config in pyproject.toml:
For full configuration options, see [RUFF_CONFIG.md](RUFF_CONFIG.md).
MyPy Configuration
For strict settings and overrides, see [MYPY_CONFIG.md](MYPY_CONFIG.md).
Type Hints Patterns
For protocols and advanced patterns, see [TYPE_PATTERNS.md](TYPE_PATTERNS.md).
Common Anti-Patterns
x = x or default is fine only when no falsy value is a meaningful input — the domain is None-or-object, or the one falsy case is an empty container (e.g. items = items or []). For numeric, boolean, or string fields where 0, False, or "" are meaningful inputs, it is a bug — use x if x is not None else default.
A Rule You Enabled Isn't a Rule That Fires
Linters ship exemptions, and the costly ones are invisible: the rule is in select, the job is green, and the class of mistake you believed was policed walks straight through. Before relying on a check to protect something, write the violation on purpose once and confirm it gets reported.
The Ruff default that bites hardest is dummy-variable-rgx. It exists so _-prefixed throwaways don't trip unused-variable checks, but its default pattern matches any leading-underscore name — so F811 (redefinition of an unused name) ignores every private helper in the codebase.
ruff check --select F811 passes clean on that file. Rename both to is_rate_limited and it fires immediately (verified on ruff 0.16). The gate is working — the name opted out of it.
This shape shows up most often after two branches independently add the same module-level helper and a conflict resolution keeps both sides. Nothing goes red; the bodies usually agree at first; then someone patches the dead copy and cannot work out why the behaviour didn't change.
Prefer fixing it in config, so the check actually covers private names:
State the tradeoff honestly before adopting it: _, keep = pair() stays silent, but _unused = compute() now trips F841. In a codebase that leans on _name throwaways that is real noise — delete the assignment or use a bare _ rather than reverting the regex.
Independently, after resolving a conflict in a module both branches edited, look for duplicated module-level definitions directly — this catches shadowing the linter's config can't. The anchored pattern is deliberate: nested def/ class inside a class or function is indented and won't match, which is the scope where accidental shadowing actually costs you.
The habit generalizes past Ruff: when a check is load-bearing, introduce the mistake once and watch it get caught, the same way a regression test is only trustworthy after you've seen it go red.
Fail Loud: Don't Degrade Silently
The costliest bugs aren't crashes — they're failures that look like success. Code that swallows an error and returns something plausible corrupts data downstream with no signal that anything went wrong. Prefer raising, or at minimum surfacing an explicit error, over a quiet fallback.
Don't collapse exceptions into a generic string — and don't discard output.
Give success and failure distinct sentinels. If the error path writes the same status value the success path uses, failed runs read as complete.
Never substitute fabricated data on failure. Returning randomized or sample data when a fetch fails makes the UI show plausible-but-invented numbers.
Signal partial results — don't return them as complete. A paginated fetch that aborts mid-stream and returns what it has looks identical to a full result.
Batch loops: collect per-item errors, don't just `continue`. Skipping bad inputs silently gives no way to know coverage was incomplete — and makes sibling operations inconsistent when some report errors and others don't.
The unifying rule: when you catch an error, either recover meaningfully or make the failure visible (raise, log at error level, or return a distinguishable sentinel). A return/continue/fallback inside except that produces normal-looking output is where silent corruption lives.
Determinism & Reproducibility
Non-deterministic output is a quiet tax: churny, unreviewable diffs; flaky tests; and simulations no one can reproduce from a seed. Three sources recur.
Serializing from an unordered container. Building a list or JSON payload by iterating a set (or merging into a dict and ranging it) emits results in an order that varies run to run — str hashing is randomized per process, so a regenerated file is the same data reshuffled, and the real change drowns in noise in a repo whose whole point may be a clean diff. Impose a total order before you serialize.
Multiple RNGs, none injectable. A library that draws from both random and numpy.random needs both seeded to be reproducible — seeding one leaves the other free-running, so the run is only half-deterministic. And seeding the global RNGs (random.seed, np.random.seed) clobbers the caller's global state. Accept a seed (or an RNG instance) and thread local generators through, so callers get reproducibility without you reaching into their globals.
Unpinned parsing context. Locale-dependent parsing — datetime.strptime with %b/%a (month/day names) — silently changes behavior across machines. Pin the format and locale so a test that passes on your box passes in CI too.
Non-determinism also weakens tests: a function that shuffles its output forces assertions so loose ("contains any of these words") that they stop catching regressions. Make the seam deterministic — inject the RNG — and assert exact output.
Pythonic Idioms
Module Organization
Checklist
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/python/code-quality/SKILL.md
Popularity
- Repository stars
- 95
- Repository forks
- 14
- 7-day trend score
- 23
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 18 May 2026, 5 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/wdm0006/python-skills/code-quality)