Fable Converted Pylint to Rust

adamraudonis1 pts0 comments

prylint · PyPI

Skip to main content<br>Switch to mobile version

Warning

You are using an unsupported browser, upgrade to a newer version.

Warning

Some features may not work without JavaScript. Please try enabling it if you encounter problems.

Search PyPI

Search

prylint 0.4.2

pip install prylint

Copy PIP instructions

Latest release

Released:<br>Jun 19, 2026

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

Navigation

Verified details

These details have been verified by PyPI<br>Maintainers

adamraudonis

Unverified details

These details have not been verified by PyPI<br>Project links

Changelog

Issues

Repository

Meta

License Expression: GPL-2.0-or-later

SPDX<br>License Expression

Author: Adam Raudonis

Tags

pylint

linter

lint

static-analysis

rust

python

Requires: Python >=3.9

Classifiers

Development Status

4 - Beta

Intended Audience

Developers

Operating System

MacOS

Microsoft :: Windows

POSIX :: Linux

Programming Language

Python :: 3

Python :: 3.9

Python :: 3.10

Python :: 3.11

Python :: 3.12

Python :: 3.13

Python :: 3.14

Rust

Topic

Software Development :: Debuggers

Software Development :: Quality Assurance

Report project as malware

Project description

prylint

A Rust reimplementation of pylint that<br>produces byte-for-byte identical output — 15–2300× faster (median ~85×).

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

Install

pip install prylint

Requirements: a python3 (≥3.9) on PATH (used only to mirror pylint's<br>module-resolution paths and to reproduce CPython's exact syntax-error messages<br>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 .`)<br>prylint -E . # errors only (like `pylint -E .`)<br>prylint --disable=C0114,... . # same --disable / --enable / inline pragmas

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

Benchmarks

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

codebase<br>pylint<br>prylint<br>speedup

black<br>26.7 hr<br>41s<br>2328×

sentry<br>3.7 hr<br>24s<br>546×

home-assistant (17.5k files)<br>10.3 hr<br>82s<br>452×

airflow<br>1.9 hr<br>17s<br>399×

salt<br>1890s<br>8.8s<br>215×

zulip<br>909s<br>5.3s<br>172×

django<br>1524s<br>10.1s<br>150×

ansible<br>419s<br>2.9s<br>143×

nova (OpenStack)<br>1209s<br>10.3s<br>117×

fastapi<br>116s<br>1.0s<br>120×

mypy<br>367s<br>3.9s<br>95×

sqlalchemy<br>614s<br>7.1s<br>87×

pandas<br>1009s<br>14.2s<br>71×

scikit-learn<br>613s<br>9.6s<br>64×

sympy<br>1238s<br>26s<br>48×

…and 12 more, all ≥30×

aggregate (these 27)<br>45.8 hr<br>4.9 min<br>~560×

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

Median per-repo speedup ~85×; the aggregate is higher because pylint's<br>duplicate-code check (R0801) is O(n²) and dominates on test-heavy repos like<br>black. These are single-core numbers — the inference engine is<br>single-threaded to replicate astroid's order-sensitive global cache exactly<br>(see LIMITATIONS.md), and that byte-identical path is already<br>15–2300× pylint.

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

Accuracy

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

AST fidelity — prylint's parse tree (built on the<br>ruff parser) is compared node-by-node<br>against astroid's (positions, scopes, locals, brain transforms) across all<br>corpus files: zero differences.

Inference fidelity — astroid's inference engine is ported exactly:<br>lazy-generator semantics, the 100-node inference budget, the bounded-LRU<br>caches (lookup 128, _metaclass_lookup_attribute 1024) with their exact<br>eviction, the 64-entry inference-tip FIFO, Uninferable propagation. Every<br>name/attribute/call node's inference is dumped and compared against astroid.

Output fidelity — full runs compared byte-for-byte, including message<br>order, module headers, the score footer, # pylint: pragma handling<br>(disable/enable blocks, disable-next, skip-file), config-file discovery,<br>and exit-code bitmasks.

Blind testing — two batteries of 10 repos each were added after<br>development and judged cold; every divergence was root-caused and fixed.

Known, documented exceptions (one obscure SQLAlchemy class; the deliberately<br>excluded no-member family; the places pylint is...

pylint prylint python byte astroid inference

Related Articles