Skip to main content

A Rust reimplementation of pylint's error checking that produces byte-for-byte identical output to pylint — 15-84x faster

Project description

prylint

A Rust reimplementation of pylint that produces byte-for-byte identical output15–2300× faster (median ~85×).

prylint is not "inspired by" pylint. It is a bug-for-bug port: the same messages, at the same lines and columns, with the same text, in the same order, with the same exit codes and the same Your code has been rated footer — verified byte-identically against real pylint on 27 production codebases (~60,000 Python files), including django, numpy, pandas, sympy, home-assistant, sqlalchemy, twisted, scikit-learn, and pylint's own functional test suite. Where pylint has bugs, prylint reproduces them. Where pylint crashes, prylint reports the same crash message.

Install

pip install prylint

Requirements: a python3 (≥3.9) on PATH (used only to mirror pylint's module-resolution paths and to reproduce CPython's exact syntax-error messages for unparseable files). pylint and astroid themselves are not required.

Usage

Use it exactly like pylint — full check mode is the default:

prylint .                      # all checks (like `pylint .`)
prylint -E .                   # errors only (like `pylint -E .`)
prylint --disable=C0114,... .  # same --disable / --enable / inline pragmas

Output, message order, exit codes, the score footer, --rcfile / pyproject.toml discovery, init-hook, and # pylint: pragmas all match pylint 4.0.5.

Benchmarks

prylint . vs pylint . (both full check mode), pylint 4.0.5, Apple M-series, single-threaded:

codebase pylint prylint speedup
black 26.7 hr 41s 2328×
sentry 3.7 hr 24s 546×
home-assistant (17.5k files) 10.3 hr 82s 452×
airflow 1.9 hr 17s 399×
salt 1890s 8.8s 215×
zulip 909s 5.3s 172×
django 1524s 10.1s 150×
ansible 419s 2.9s 143×
nova (OpenStack) 1209s 10.3s 117×
fastapi 116s 1.0s 120×
mypy 367s 3.9s 95×
sqlalchemy 614s 7.1s 87×
pandas 1009s 14.2s 71×
scikit-learn 613s 9.6s 64×
sympy 1238s 26s 48×
…and 12 more, all ≥30×
aggregate (27 repos) 45.8 hr 4.9 min ~560×

Median per-repo speedup ~85×; the aggregate is higher because pylint's duplicate-code check (R0801) is O(n²) and dominates on test-heavy repos like black. This is single-core — the inference engine is deliberately single-threaded to replicate astroid's order-sensitive global cache exactly (see LIMITATIONS.md).

Every row above is also an accuracy test: each repo's full output is byte-identical to pylint's (see exceptions in LIMITATIONS.md).

Accuracy

prylint was built by differential testing against pinned pylint 4.0.5 / astroid 4.0.4 / CPython 3.12:

  1. AST fidelity — prylint's parse tree (built on the ruff parser) is compared node-by-node against astroid's (positions, scopes, locals, brain transforms) across all corpus files: zero differences.
  2. Inference fidelity — astroid's inference engine is ported exactly: lazy-generator semantics, the 100-node inference budget, the bounded-LRU caches (lookup 128, _metaclass_lookup_attribute 1024) with their exact eviction, the 64-entry inference-tip FIFO, Uninferable propagation. Every name/attribute/call node's inference is dumped and compared against astroid.
  3. Output fidelity — full runs compared byte-for-byte, including message order, module headers, the score footer, # pylint: pragma handling (disable/enable blocks, disable-next, skip-file), config-file discovery, and exit-code bitmasks.
  4. Blind testing — two batteries of 10 repos each were added after development and judged cold; every divergence was root-caused and fixed.

Known, documented exceptions (one obscure SQLAlchemy class; the deliberately excluded no-member family; the places pylint is nondeterministic against itself) are catalogued in LIMITATIONS.md.

How it works

  • File discovery, message control, config parsing, and reporting are direct ports of pylint's own logic (down to os.walk ordering, the ************* Module header rule, and the score-report footer).
  • Parsing uses ruff's Rust parser, then rebuilds astroid's exact tree shape (docstring extraction, decorator positions, implicit class locals, metaclass handling, brain transforms for dataclasses/enums/namedtuples/attrs/…).
  • A full port of astroid's inference engine resolves names, calls, attributes, MROs, and operator protocols with astroid's exact conservatism — including its caches and their quirks, because the quirks are observable in the output.
  • Files the Rust parser rejects are re-judged by CPython itself (an embedded, stdlib-only helper) so syntax-error messages match ast.parse exactly.

Reproducing the test suite

scripts/setup_corpora.sh clones all 27 corpora at pinned commits and builds the pinned pylint/astroid ground-truth venv. The accuracy contract: every change must keep the corpora byte-identical (harness/ holds the differential comparators).

License

GPL-2.0-or-later, the same license as pylint — prylint reproduces pylint's message texts and behavior verbatim.

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

prylint-0.3.0.tar.gz (1.3 MB view details)

Uploaded Source

Built Distributions

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

prylint-0.3.0-py3-none-win_amd64.whl (4.2 MB view details)

Uploaded Python 3Windows x86-64

prylint-0.3.0-py3-none-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

prylint-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (4.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

prylint-0.3.0-py3-none-macosx_11_0_arm64.whl (4.2 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

prylint-0.3.0-py3-none-macosx_10_12_x86_64.whl (4.3 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file prylint-0.3.0.tar.gz.

File metadata

  • Download URL: prylint-0.3.0.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for prylint-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c32366cd7b0ed9ece61def6e37ad2c310b90bd82a15934485a03b883459758d7
MD5 3db3612d57eda60a41b5528a56c04ec6
BLAKE2b-256 3fd2f19582fae5359bee8e2a3bea0c201888a3d5c1706ba5aa37c372a15327ac

See more details on using hashes here.

File details

Details for the file prylint-0.3.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: prylint-0.3.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 4.2 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for prylint-0.3.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 4108073164f3e86160263be3993f3d855b3065cb37661cd5dd5aa07c1dd6169c
MD5 5dde9be898d9d8c8769e1a2aa9891355
BLAKE2b-256 f9c9e2bbbce6505c7fd3a2fb76740c3510bf647c499a4c9ce155e915fcb2c14c

See more details on using hashes here.

File details

Details for the file prylint-0.3.0-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for prylint-0.3.0-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 6b23cabd89d5f40370b24db05afbd691291c08eaec016d9dfd9d6179f66a16f4
MD5 43c476113b57c103445df45172325887
BLAKE2b-256 99c37e55fd366b3c26a1c501fab4b4347c15b883e422f21abc3b650172b997ab

See more details on using hashes here.

File details

Details for the file prylint-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for prylint-0.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a673238eb0dcef4b459c2ccf4cdae19fcfcc6ccbdfc44930c1b93d478e7260df
MD5 579bd63efaaa355d40991fec913dc862
BLAKE2b-256 c6441a326ab05aac62e6a54d7f6575988b4bc6b7323a51c67c809267969697ab

See more details on using hashes here.

File details

Details for the file prylint-0.3.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for prylint-0.3.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bc34c60c9174475c9704d1c5e1b738a9da8e3eab5d01e74223619bf90ab2feab
MD5 97060d6ad475bdc4d29e794cc1bab6ac
BLAKE2b-256 1085ce5c235a0977d11adf89b34eef231803852bff96ea59e34178b41d7df43f

See more details on using hashes here.

File details

Details for the file prylint-0.3.0-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for prylint-0.3.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 38f43de72b66ae4d793ce675f3f0fe17921208cdd0b38e4f70376d678af4e0c3
MD5 f00b92efb0f50653dd5060f3b6b33360
BLAKE2b-256 db348c10ec595f8cb14c03d5529f4615eae2db87f2d36139c57ad577ee46e804

See more details on using hashes here.

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