Static-check strategy for Python — ruff rule selection (lint vs format), pyright-strict vs mypy trade-offs, progressive typing adoption, per-file/per-line suppression discipline, and how the dhpk python module''s post-edit + pre-commit hooks invoke them. Use when configuring ruff/pyright/mypy or triaging their output. Not for runtime debugging or test design; use dhpk-python-pro or dhpk-pytest-async. Output: a tool configuration or triage plan with commands and pass/fail gates.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add hmj1026/dhpk --skill dhpk-python-static-checks --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Dhpk Python Static Checks?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/hmj1026-dhpk-python-static-checks)More formats (shields.io, HTML) on the badges page.
---
name: dhpk-python-static-checks
description: 'Static-check strategy for Python — ruff rule selection (lint vs format), pyright-strict vs mypy trade-offs, progressive typing adoption, per-file/per-line suppression discipline, and how the dhpk python module''s post-edit + pre-commit hooks invoke them. Use when configuring ruff/pyright/mypy or triaging their output. Not for runtime debugging or test design; use dhpk-python-pro or dhpk-pytest-async. Output: a tool configuration or triage plan with commands and pass/fail gates.'
metadata:
dhpk-invocation-class: implicit-eligible
---
# Python Static Checks
How to configure and reason about the Python tooling the `python` dhpk module
drives. The module never bundles config — it runs the project's own
`pyproject.toml` via the configured runner (`uv run` by default).
## ruff — lint + format in one tool
- **Two commands, one tool:** `ruff check` (lint) and `ruff format` (Black-compatible
formatter). The hooks run both; CI should too.
- **Rule selection** lives in `[tool.ruff.lint] select = [...]`. A solid baseline
(ccas uses it): `E` (pycodestyle), `F` (pyflakes), `I` (isort/import order),
`N` (pep8-naming), `W` (warnings), `UP` (pyupgrade — modern-syntax nudges).
Add `B` (bugbear), `S` (bandit security), `ASYNC` as the codebase matures.
- **Per-line suppression:** `# noqa: E501` (specific code, never bare `# noqa`).
**Per-file:** `[tool.ruff.lint.per-file-ignores]` (e.g. allow unused imports in
`__init__.py`, asserts in `tests/`).
- Keep `line-length` and `target-version` in `pyproject.toml` so editor, hook, and
CI agree. `ruff check --fix` and `ruff format` auto-resolve most findings.
## Type checking — pyright vs mypy
- The module's `python_typechecker` knob selects `pyright` (default), `mypy`, or
`none`. Pick one and gate on it; running both doubles noise.
- **pyright:** fast, excellent inference, `strict` mode is aggressive. Configure in
`pyproject.toml` `[tool.pyright]` (or `pyrightconfig.json`): set `pythonVersion`,
`venvPath`/`venv`, and `typeCheckingMode`. ccas runs strict.
- **mypy:** ubiquitous, plugin ecosystem (pydantic, SQLAlchemy). Configure
`[tool.mypy]`; adopt `--strict` incrementally via per-module overrides.
- **Progressive adoption** for a legacy codebase: start non-strict, enable strict
per-package via overrides, ratchet up. Don't blanket-`# type: ignore` to go green
— each ignore needs a trailing reason and ideally a specific error code.
## How the hooks invoke them
- **post-edit** (`post-edit-python-lint.sh`): advisory `ruff check` + `ruff format
--check` on edited `.py`. Batched once at Stop by default (`DHPK_PY_LINT_MODE`),
never blocks. Set `DHPK_PY_STOP_TYPECHECK=1` to also typecheck at Stop.
- **pre-commit** (`pre-commit-python-validation.sh`): the real gate — `ruff check`,
`ruff format --check`, then the type checker on staged `.py`, grouped by the
owning `pyproject.toml` dir. Exit 2 blocks the commit; `[skip-python-lint]`
bypasses.
- **Tool resolution:** runner prefix (`uv run`) is used only when its binary exists,
else tools run bare off PATH; if neither resolves, the gate self-skips with a
warning rather than failing — so a machine without the toolchain isn't blocked.
## Monorepo / subdir backends
Project root is found by walking up to the nearest `pyproject.toml`, so a backend
under `backend/` is handled with zero config. Set `python_project_roots="backend"`
only to *restrict* checks to that subtree (ignore stray top-level scripts).
## When NOT to Use
Not for writing application logic (see `dhpk-python-pro`), and not for choosing *which*
tests to write (see `dhpk-pytest-async`). Load this only when configuring or triaging
ruff / pyright / mypy.
## Output
A `pyproject.toml` whose `[tool.ruff.lint] select`, `[tool.ruff]` line-length /
target-version, and `[tool.pyright]` / `[tool.mypy]` blocks are explicit and
agree across editor, post-edit hook, and CI — plus scoped, reason-tagged
suppressions instead of blanket ignores.
## Verification
- `ruff check` + `ruff format --check` and the chosen type checker run clean on
the same config the hooks use.
- Every `# noqa` / `# type: ignore` names a code and a reason.
- The pre-commit gate resolves tools via the runner prefix (or self-skips), so a
machine without the toolchain is never falsely blocked.
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!