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 52 production codebases (~65,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 (these 27) 45.8 hr 4.9 min ~560×

(These 27 are the large repos that are slow enough to time meaningfully; the full accuracy suite is 52 repos — see below.)

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. These are single-core numbers — the inference engine is single-threaded to replicate astroid's order-sensitive global cache exactly (see LIMITATIONS.md), and that byte-identical path is already 15–2300× pylint.

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 52 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.4.2.tar.gz (1.9 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.4.2-py3-none-win_amd64.whl (4.2 MB view details)

Uploaded Python 3Windows x86-64

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

Uploaded Python 3manylinux: glibc 2.28+ ARM64

prylint-0.4.2-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.4.2-py3-none-macosx_11_0_arm64.whl (4.2 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

prylint-0.4.2-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.4.2.tar.gz.

File metadata

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

File hashes

Hashes for prylint-0.4.2.tar.gz
Algorithm Hash digest
SHA256 0dea90b8bc79eb5e7412c180a9cf034a107cf6e1fea46f8cbe078775908db60f
MD5 e9f5cb1c4cd317474aa07f156fb72280
BLAKE2b-256 c7cf38edbebace645bb87f83909858382391fad6ca4596bd4aa9d3be5910e0d0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: prylint-0.4.2-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.4.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 55394ec3ead2d10652cbe29f820d14f0c03ec8b65d4430c89d57eb549e94d2f1
MD5 cc90eebcdc13d73091cf150c82942e5d
BLAKE2b-256 05031745da692b62eedc94dabb9fbc6572ff571e399ddb66b9bf6dc4530e36b6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for prylint-0.4.2-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 16efe779edc96b8ae3228aef8d6f54c69a9d8114a862f5897e29cf6dc62c9917
MD5 ca5863550a15653390e4567225157536
BLAKE2b-256 041efe64feb4410656c601d83ef22615da8a9a634fbb4d9dd004062c119ea423

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for prylint-0.4.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c948478aa3bc14f0d38a25ebf34189d80d7918863ab1e2620d6727772b73dfe7
MD5 c89a2642c299eb1f9b7f744c39d53f37
BLAKE2b-256 aee59e1b9f44a0b70ab5285c89576ac001aa8b38ee1abf2c02c5b68790216ec8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for prylint-0.4.2-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 019f94c6f05c0565b338661f45ddb0ba27253b513717834e1c5ddd8f5f72ac9e
MD5 359343463a91dd9288ea6fb0a6984734
BLAKE2b-256 4e9fa78aecdccf9631812a71e24bc2ac60ddbc9354b41681e984921fc2a5dfab

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for prylint-0.4.2-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a66f81442a185a90f41c74e6f971bb763ea05af9859487ff6273c6e866b79bf0
MD5 503d9114ae433063494ae58028902754
BLAKE2b-256 59f769c1084179fa97ee9140af196dc991a523c3aab9c507f0cfa7117a9b856a

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