Skip to main content

Extensible Python linter written in Rust

Project description

jg-lint

Extensible Python linter with a Rust core.

Installation

Requires Python 3.14+.

uv add jg-lint

or with pip:

pip install jg-lint

or with Poetry:

poetry add jg-lint

Development install

To build from source, you need Maturin and a Rust toolchain:

git clone https://github.com/giacosoft/jg-lint.git
cd jg-lint
uv sync
uv run maturin develop

Usage

jg-lint check <paths...>

Lint one or more files or directories:

jg-lint check src/
jg-lint check src/ lib/ main.py
jg-lint check --config path/to/project src/

The --config flag points to the directory containing pyproject.toml (defaults to .).

Built-in rules

Code Description
JG001 Imports must be at module top level
JG002 if statements are not allowed in test functions (any function or method whose name starts with test_)

Built-in rules are opt-in: they only run when you list them in select (see Configuration). For example, select = ["JG*"] enables every built-in rule, and select = ["JG001"] enables only JG001.

Output looks like:

src/app.py:12:1: MY001 TODO comments should be tracked as issues
src/app.py:45:1: MY001 TODO comments should be tracked as issues

Found 2 violation(s)

Exit code is 1 if any violations are found, 0 otherwise.

Inline suppression

Some rules opt in to per-line suppression via # noqa:

x = something()  # noqa: MY001
y = another()  # noqa: MY001, MY002

By design, # noqa is not honored by default — rules must explicitly set allow_noqa = True to allow it. This keeps suppression intentional and reserved for cases where the rule author has decided it's acceptable.

Configuration

All configuration lives in pyproject.toml under [tool.jg-lint]:

[tool.jg-lint]
select = ["MY001", "JG*"]    # rules to enable (see "Selecting rules" below)
ignore = ["MY002"]           # skip these rules globally
exclude = [".venv/**", "build/**"]
rules_path = "./rules"       # directory containing your custom rule modules

[tool.jg-lint.per-file-ignores]
"tests/**" = ["MY001"]       # skip MY001 in test files

Selecting rules

Each entry in select, ignore, and per-file-ignores is matched against a rule's code with the following pattern semantics:

  • "*" — matches every code.
  • "JG*" — matches every code starting with JG (e.g. JG001, JG042).
  • "JG001" — exact match.

Defaults when select is empty:

  • Built-in rules (e.g. JG001, JG002) are not enabled. List them explicitly with select = ["JG*"] or by code.
  • Plugin rules from rules_path are enabled.

Writing custom rules

1. Create a rule module

Put it inside the directory you've configured as rules_path (e.g. ./rules/no_todo.py or ./rules/no_todo/__init__.py).

from jg_linter import Rule, Violation


class NoTodoComments(Rule):
    code = "MY001"
    message = "TODO comments should be tracked as issues"

    def check(self, file_path: str, content: str) -> list[Violation]:
        violations = []
        for i, line in enumerate(content.splitlines(), 1):
            if "# TODO" in line:
                violations.append(
                    Violation(file_path, i, 1, self.code, self.message)
                )
        return violations


def get_rules() -> list[Rule]:
    return [NoTodoComments()]

Each rule needs:

  • code -- unique identifier (e.g. MY001)
  • message -- human-readable description
  • check(file_path, content) -- returns a list of Violation objects

Set test_only = True on a rule to run it only against test files (files named test_*.py, *_test.py, or inside a tests/ directory).

Set allow_noqa = True on a rule to allow inline # noqa: CODE suppression. Without this, the rule cannot be silenced per-line and can only be turned off project-wide via ignore or per-file-ignores.

2. Point jg-lint at the rules folder

[tool.jg-lint]
rules_path = "./rules"

Every top-level .py file and package inside rules_path is imported automatically; any module exposing get_rules() contributes rules. Files and folders starting with _ are skipped. The rules directory is prepended to sys.path during loading, so no PYTHONPATH setup is needed.

3. Run

jg-lint check src/
src/app.py:3:1: MY001 TODO comments should be tracked as issues
src/utils.py:17:1: MY001 TODO comments should be tracked as issues

Found 2 violation(s)

Contributing

You need a Rust toolchain (stable), Python 3.14+, and uv.

git clone https://github.com/giacosoft/jg-lint.git
cd jg-lint
uv sync
uv run maturin develop

Tests

cargo test                 # Rust unit tests
uv run pytest              # Python tests (rebuild with `maturin develop` if Rust changed)

Linting and formatting

Before opening a PR, run the same checks CI does:

# Rust
cargo fmt --all -- --check          # formatting
cargo clippy --all-targets -- -D warnings   # lints (fails on any warning)
cargo audit                          # CVEs in dependencies (install with `cargo install cargo-audit`)

# Python
uv run ruff check .                  # lint
uv run ruff format --check .         # format check

To auto-fix:

cargo fmt --all
cargo clippy --fix --all-targets
uv run ruff check --fix .
uv run ruff format .

License

MIT — see LICENSE.

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

jg_lint-0.5.0.tar.gz (25.5 kB view details)

Uploaded Source

Built Distributions

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

jg_lint-0.5.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.15manylinux: glibc 2.17+ x86-64

jg_lint-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARM64

jg_lint-0.5.0-cp314-cp314-win_amd64.whl (1.0 MB view details)

Uploaded CPython 3.14Windows x86-64

jg_lint-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

jg_lint-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

jg_lint-0.5.0-cp314-cp314-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

jg_lint-0.5.0-cp314-cp314-macosx_10_12_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.14macOS 10.12+ x86-64

File details

Details for the file jg_lint-0.5.0.tar.gz.

File metadata

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

File hashes

Hashes for jg_lint-0.5.0.tar.gz
Algorithm Hash digest
SHA256 fadf979c75a155ca641247d6ba939ca6dd8bd867ae00ff42c67275371b9bd1f0
MD5 647ced98f8960ffd31d8758e8990d212
BLAKE2b-256 3eec5a1ed56180167b21b30d9cffb76d997cb4fc6450ba04e2157ce8253b1f5a

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0.tar.gz:

Publisher: release.yml on jangia/jg-lint

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

File details

Details for the file jg_lint-0.5.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for jg_lint-0.5.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4beafb6f5ef98c7767f9707f23a7a3080a4ac8469d9af54f98af9eac9a392983
MD5 530c1d6b7220077b1e39ebf1c327e181
BLAKE2b-256 03272b2698ab009b60fa0783f82e7102fd2365e3463785c0b46c1798daf79aa8

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on jangia/jg-lint

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

File details

Details for the file jg_lint-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for jg_lint-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 6b2c09a6024a38617ee669a4f7732493de27db095e34812a1cad5b305067d9ae
MD5 57dc4bc3a097e7e11bdd3460293a7452
BLAKE2b-256 436e9364058328e5e7b6fd8caabc6d4b77e9d70fc82c3a2874e4dd6e59b2b028

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on jangia/jg-lint

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

File details

Details for the file jg_lint-0.5.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: jg_lint-0.5.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 1.0 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for jg_lint-0.5.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 f412e068e250d2586d9e15006496daafcdca775c0c696e27b0de988b8d5229e8
MD5 cec48b82fd658e496bc838ece7829d57
BLAKE2b-256 dd504cb7620c09559a7c9b601199a448c5e6ae7e206f26c1063cef59a382da02

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0-cp314-cp314-win_amd64.whl:

Publisher: release.yml on jangia/jg-lint

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

File details

Details for the file jg_lint-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for jg_lint-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 be81aee172ba0bf39e9f28451b5c4d43953f8081ea5da3b05d7634c83085149d
MD5 2eb03c28cd0d17197d8279dec126a723
BLAKE2b-256 1954aeede4ffbb1a9b77f8f73daf3bc07b4b6e6038db92f57144a2ee6d71bf66

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on jangia/jg-lint

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

File details

Details for the file jg_lint-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for jg_lint-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fd92b341493862117620792187ba1a364fd5ac4dc8387246da9b9dca439cc281
MD5 d0f4dbb047a5a2b7c329b51b3a0bbc4e
BLAKE2b-256 a426e4fcbfea93ec2551dcbeed051bd28fde89bf22aacac5314705724b7d6995

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on jangia/jg-lint

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

File details

Details for the file jg_lint-0.5.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for jg_lint-0.5.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 562c777bfee2aad53af71186d918febcbe41ba376c22155744bbeb46c9cfb67a
MD5 e02223b8334ce8ddd70c6f5a9d3f4f16
BLAKE2b-256 a5219cddf23776dfb06f8a8cf41e230bd91a879cce1ddefb2bcc4cfb82249092

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: release.yml on jangia/jg-lint

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

File details

Details for the file jg_lint-0.5.0-cp314-cp314-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for jg_lint-0.5.0-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 19d590ede123973d4e3d18fddad198d8f7b458c848bb0d13372728dfbfcaffcd
MD5 1304128cd24f638b7d749421ae973b36
BLAKE2b-256 a72dcb5caa36efb29cd6d617fed09467b95a3685f19c7d42dbead6bf5fac6806

See more details on using hashes here.

Provenance

The following attestation bundles were made for jg_lint-0.5.0-cp314-cp314-macosx_10_12_x86_64.whl:

Publisher: release.yml on jangia/jg-lint

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