Comply or explain - justify every ignored linting rule.
β¨ Features π Quick start π Documentation π€ Contribute π Adopters π Legal
noqaexplain is a linter which enforces justifying every ignored linting rule supporting multiple formats/linters:
- Python -
ruffandflake8# noqa,coveragepy# pragma: no cover, andlintkitline, span, and file suppressions - JavaScript/TypeScript -
eslint - Rust -
clippy - Dockerfiles -
hadolint - YAML -
yamllintandlintkitline, span, and file suppressions - TOML -
lintkitline, span, and file suppressions - Markdown -
PyMarkdown,Vale, andmd-dead-link-check - Shell -
shellcheck
Important
You can expand this list with any language and linter by using
extend_mapping_suffix and/or extend_mapping_name!
Feel free to open a request to add support for more linters.
> pip install noqaexplain[all]To install rich output and MCP server as well:
> pip install noqaexplain[all]To check against all files (the ones with defined mappings from file extension to error disable comment format), run:
> noqaxplain checkYou can pass additional arguments to noqaexplain check, like files
to check:
> noqaexplain check path/to/file.py maybe.rs other.yml formats.jsIf a certain file has a line with disabled check without an explanation, the tool will report it:
path/to/file.py:10:5: ENQ0 Missing explanation (enoqa) for disabled linting rule
to fix it, just add an explanation after the disable comment prefixed by enq:,
e.g.:
import some_library
# enq: Disabled private access check as there is no other workaround currently.
# noqa: SLF001
some_library._private_function()The same rule applies to opening span and file-wide lintkit directives:
# enq: Generated settings are checked separately before publication.
# noqa-file: MYLINTER1
# enq: This generated section cannot follow the repository style.
# noqa-start: MYLINTER2
generated = true
# noqa-end: MYLINTER2Markdown suppressions use an HTML comment for the explanation:
<!-- enq: Generated content cannot satisfy the line length rule. -->
<!-- pyml disable-next-line line-length -->Markdown matching uses the literal comment prefixes <!-- pyml, <!-- vale,
and <!-- md-dead-link-check. Every matching comment needs an explanation.
You can configure noqaexplain in pyproject.toml (or .noqaexplain.toml
in the root of your project, just remove the [tool.noqaexplain] section),
for example:
[tool.noqaexplain]
explain_noqa_pattern = "enq:"
# Extends Python noqas mappings
# Now every # my_noqa_header: will be treated as a noqa comment
# and checked for explanations.
extend_mapping_suffix = {".py" = ["# my_noqa_header:"]}
# Target any MySuperFile.md file(s) and look for explanations
extend_mapping_name = {"MySuperFile.md" = ["# my_noqa_header:"]}
[tool.noqaexplain.ENQ1]
min_explain_length = 10Select rules and stopping behavior with CLI flags, for example:
noqaexplain check --names ENQ0 --end_mode firstTip
Rule-specific configuration can be found in the section below.
noqaexplain can be used as a pre-commit hook, to add as a plugin:
repos:
- repo: "https://github.com/open-nudge/noqaexplain"
rev: ... # select the tag or revision you want, or run `pre-commit autoupdate`
hooks:
- id: "noqaexplain"Tip
Run noqaexplain rules to see the list of available rules.
noqaexplain provides the following rules:
| Name | Description |
|---|---|
NQE0 |
Ensures that all disabled linting rules have an explanation on the nearest preceding nonblank line |
NQE1 |
Ensures that all disabled linting rules have an associated explanation of at least |
Shared options belong in [tool.noqaexplain] (or at the root of
.noqaexplain.toml):
| Option | Description | Affected rules | Default |
|---|---|---|---|
extend_mapping_suffix |
Additional file suffix to noqa comment(s) format mappings (dict of lists) | All | {} |
extend_mapping_name |
Additional file name to noqas comment(s) format mappings (dict of lists) | All | {} |
mapping_suffix |
File suffix to noqa comment format(s) mappings (dict of lists, overrides default!) | All | {} |
mapping_name |
File name to noqa comment format(s) mappings (dict of lists, overrides default!) | All | {} |
dir_ignores |
Directory names ignored during default file discovery | All | standard |
extend_dir_ignores |
Additional directory names ignored during default file discovery | All | [] |
explain_noqa_pattern |
String identifying explanation for disabled linting rule | All | "enq:" |
ENQ1 options belong in [tool.noqaexplain.ENQ1]:
| Option | Description | Default |
|---|---|---|
min_explain_length |
Minimum char length of explanation for disabled linting rules | 10 |
We welcome your contributions! Start here:
- This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
- This project is copyrighted by open-nudge - the appropriate copyright notice is included in each file.