Skip to main content

A pluggable framework for writing Python lint rules on the standard-library AST.

Project description

cacao-nib (nib)

A pluggable framework for writing Python lint rules on top of the stdlib ast module. Ships zero builtin rules: rules live in plugin packages you write or install.

Plugins are loaded explicitly via [tool.nib] plugins = [...] in pyproject.toml, so what runs is exactly what you list.

Installation

Requires Python 3.14+.

python -m pip install cacao-nib

Usage

nib check                                   # lint current directory (recursive)
nib check path/to/file.py
nib check --plugins nib_rules
nib check --select X001,DJ                  # only these codes/groups
nib check --ignore X002 --extend-ignore DJ  # ignore X002, then also skip the DJ group

Run nib --help for the full set of options; each subcommand takes --help too (e.g. nib check --help).

[tool.nib] is read from the nearest pyproject.toml, found by searching up from the current directory (a pyproject.toml without a [tool.nib] table is skipped and the search continues in the parent). So running nib from a subdirectory still picks up the project's config:

[tool.nib]
plugins = ["nib_rules"]
select  = ["X001", "DJ"]   # optional - empty = run everything
ignore  = ["X002"]         # optional
  • plugins - the rule modules to load. With none, nib has no rules and every file is "clean".
  • select - codes/groups to run; omitted or empty runs every loaded rule.
  • ignore - codes/groups to skip; takes precedence over select on overlap.

CLI --select / --ignore replace their config counterparts; --extend-select / --extend-ignore add to them. Each token is matched exactly against either a rule's code or a rule's group.

Each entry in plugins is just an importable module name: nib imports it and the Rule subclasses defined there register themselves. So a plugin can be a third-party package you pip install, or a module that lives in your own repo.

In-repo rules (no install needed)

The plugin doesn't have to be a published package. nib prepends the project root (the directory of the pyproject.toml it found) to sys.path before importing plugins, so any importable module sitting next to your pyproject.toml works from anywhere in the tree. Example layout:

your_repo/
  pyproject.toml  # [tool.nib] plugins = ["nib_rules"]
  nib_rules/
    __init__.py   # your Rule subclasses live here
  src/your_app/...

Then nib check picks them up from your_repo or any subdirectory of it.

Writing a rule

A rule is a Python class with visit_<AstName> methods:

from nib import Rule, Diagnostic, ast

class NoEval(Rule):
    code = "X001"
    group = "X"   # optional. `--select X` then picks every rule in this group

    def visit_Call(self, node):
        if isinstance(node.func, ast.Name) and node.func.id == "eval":
            return [Diagnostic(node, "no eval")]

Subclassing Rule auto-registers it; the visit_<AstName> methods mirror ast.NodeVisitor's dispatch. code identifies the individual rule; group (optional) is a category label shared by related rules so users can select/ignore them as a set.

Suppressing diagnostics

eval("x")              # noqa            — suppress every code on this line
eval("x")              # noqa: X001      — suppress only X001
eval("x"); print("y")  # noqa: X001,X002 — multiple codes

The comment must sit on the same line as the diagnostic's reported position (for multi-line nodes, that's the start line).

Performance

On large runs nib checks files in parallel across CPU cores using subinterpreters. Small runs stay single-process to skip the startup overhead. Repeat runs are cached on top of that (see below).

nib is benchmarked against a full Django checkout; the results are tracked here.

Caching

A re-run skips files that haven't changed since they last passed, so repeated nib invocations are very fast on an unchanged tree. The cache lives in ./.cacao_nib_cache, keyed in two parts: the nib version and enabled rule set select the cache file - a new release or a different --select/--ignore/plugin list starts fresh - and within it each file is keyed by path and replayed only while unchanged. Both clean and flagged files are cached - an unchanged file's diagnostics (none, or the same findings as last time) are replayed from the cache without re-parsing, until the file changes.

nib check --no-cache             # ignore the cache: check every file
nib check --cache-dir path/to/c  # use a different cache directory

Pre-commit

nib ships a pre-commit hook. Add to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/g-nie/cacao-nib
    rev: v0.2.0
    hooks:
      - id: nib

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cacao_nib-0.2.0.tar.gz (41.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cacao_nib-0.2.0-py3-none-any.whl (28.1 kB view details)

Uploaded Python 3

File details

Details for the file cacao_nib-0.2.0.tar.gz.

File metadata

  • Download URL: cacao_nib-0.2.0.tar.gz
  • Upload date:
  • Size: 41.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cacao_nib-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8725d5834d1676b2295f363502fe316232311249be16059901d8f3f4678eb8c3
MD5 78e74de28f1c0bf621ca9a8afe2362bc
BLAKE2b-256 cc44743a7ac338a32d18c77ff8c7605e4d4accc4f4bcb345ed1904be562128c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for cacao_nib-0.2.0.tar.gz:

Publisher: publish.yml on g-nie/cacao-nib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cacao_nib-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: cacao_nib-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 28.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cacao_nib-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 45e617b9ef22cc8af2df41fde5e15307793c257ca33fe8c8e3d94a48c7fe4fc6
MD5 1987735c86f2d03ff0d3afd676a19edf
BLAKE2b-256 0f6fc509a936f6afd42f7bbea7cd73585b1b6c95a856dc8d339f5f9464e16956

See more details on using hashes here.

Provenance

The following attestation bundles were made for cacao_nib-0.2.0-py3-none-any.whl:

Publisher: publish.yml on g-nie/cacao-nib

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page