Skip to main content

noqaexplain

Comply or explain - justify every ignored linting rule.

✨ Features 🚀 Quick start 📚 Documentation 🤝 Contribute 👍 Adopters 📜 Legal


Features

noqaexplain is a linter which enforces justifying every ignored linting rule supporting multiple formats/linters:

[!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.

Table of contents

Quick start

Installation

[!TIP] You can use your favorite package manager like uv, hatch or pdm instead of pip.

> pip install noqaexplain[all]

To install rich output and MCP server as well:

> pip install noqaexplain[all]

Usage

To check against all files (the ones with defined mappings from file extension to error disable comment format), run:

> noqaxplain check

You can pass additional arguments to noqaexplain check, like files to check:

> noqaexplain check path/to/file.py maybe.rs other.yml formats.js

If 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: MYLINTER2

Markdown 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.

Advanced

Configuration

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]
# include rules by their complete, case-sensitive name
names = ["ENQ0"] # default: all rules included
# whether to exit after first error or all errors
end_mode = "first" # default: "all"

# 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:"]}

[!TIP] Rule-specific configuration can be found in the section below.

Run as a pre-commit hook

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"

Rules

[!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

and the following configurable options (in pyproject.toml or .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 {}
min_explain_length Minimum length of explanation for disabled linting rules NQE1 10
explain_noqa_pattern String identifying explanation for disabled linting rule NQE0 "enq:"

Contribute

We welcome your contributions! Start here:

Legal

  • 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.

Metadata

Release files for noqaexplain 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for noqaexplain 1.0.0
File Size Uploaded
noqaexplain-1.0.0.tar.gz 18.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for noqaexplain 1.0.0
File Interpreter ABI Platform
noqaexplain-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.0 kB

Release files / noqaexplain-1.0.0.tar.gz

Download URL noqaexplain-1.0.0.tar.gz
Size 18.0 kB
Tags Source
SHA-256 checksum
How to use checksums
c94004bbe952052e8dd730b9382f7ac729214346e01f37cdfc943cf08488b6f5
BLAKE2b-256 checksum
How to use checksums
8cfad289e496dd22985dd80acb4f85e7a9bed015a1f406ca4cee8179d2d3635f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.

Transparency log

Release files / noqaexplain-1.0.0-py3-none-any.whl

Download URL noqaexplain-1.0.0-py3-none-any.whl
Size 11.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9cfe1b4909d406b087809768e2050d860ff2f978c098ae866730b29f617c69aa
BLAKE2b-256 checksum
How to use checksums
4274c0a3593dd3d6a5537de6182433d6208fb297c477feb9a1c07b4dd9ea6b66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.

Transparency log

Release history Release notifications | RSS feed

2.0.0

2 release files

This release

1.0.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page