Skip to main content

An extremely fast Python linter, written in Rust.

Project description

ruff

Actions status PyPI version

An extremely fast Python linter, written in Rust.

Bar chart with benchmark results

Linting the CPython codebase from scratch.

  • ⚡️ 10-100x faster than existing linters
  • 🐍 Installable via pip
  • 🤝 Python 3.10 compatibility
  • 🛠️ pyproject.toml support
  • 📦 ESLint-inspired cache semantics
  • 👀 TypeScript-inspired --watch semantics

ruff is a proof-of-concept and not yet intended for production use. It supports only a small subset of the Flake8 rules, and may crash on your codebase.

Read the launch blog post.

Installation and usage

Installation

Available as ruff on PyPI:

pip install ruff

Usage

To run ruff, try any of the following:

ruff path/to/code/to/check.py
ruff path/to/code/
ruff path/to/code/*.py

You can run ruff in --watch mode to automatically re-run on-change:

ruff path/to/code/ --watch

Configuration

ruff is configurable both via pyproject.toml and the command line.

For example, you could configure ruff to only enforce a subset of rules with:

[tool.ruff]
line-length = 88
select = [
    "F401",
    "F403",
]

Alternatively, on the command-line:

ruff path/to/code/ --select F401 F403

See ruff --help for more:

ruff
An extremely fast Python linter.

USAGE:
    ruff [OPTIONS] <FILES>...

ARGS:
    <FILES>...

OPTIONS:
    -e, --exit-zero             Exit with status code "0", even upon detecting errors
    -h, --help                  Print help information
        --ignore <IGNORE>...    Comma-separated list of error codes to ignore
    -n, --no-cache              Disable cache reads
    -q, --quiet                 Disable all logging (but still exit with status code "1" upon
                                detecting errors)
        --select <SELECT>...    Comma-separated list of error codes to enable
    -v, --verbose               Enable verbose logging
    -w, --watch                 Run in watch mode by re-running whenever files change

Development

ruff is written in Rust (1.63.0). You'll need to install the Rust toolchain for development.

Assuming you have cargo installed, you can run:

cargo run resources/test/src
cargo fmt
cargo clippy
cargo test

Deployment

ruff is distributed on PyPI, and published via maturin.

See: .github/workflows/release.yaml.

Benchmarking

First, clone CPython. It's a large and diverse Python codebase, which makes it a good target for benchmarking.

git clone --branch 3.10 https://github.com/python/cpython.git resources/test/cpython

Add this pyproject.toml to the CPython directory:

[tool.linter]
line-length = 88
exclude = [
    "Lib/ctypes/test/test_numbers.py",
    "Lib/dataclasses.py",
    "Lib/lib2to3/tests/data/bom.py",
    "Lib/lib2to3/tests/data/crlf.py",
    "Lib/lib2to3/tests/data/different_encoding.py",
    "Lib/lib2to3/tests/data/false_encoding.py",
    "Lib/lib2to3/tests/data/py2_test_grammar.py",
    "Lib/sqlite3/test/factory.py",
    "Lib/sqlite3/test/hooks.py",
    "Lib/sqlite3/test/regression.py",
    "Lib/sqlite3/test/transactions.py",
    "Lib/sqlite3/test/types.py",
    "Lib/test/bad_coding2.py",
    "Lib/test/badsyntax_3131.py",
    "Lib/test/badsyntax_pep3120.py",
    "Lib/test/encoded_modules/module_iso_8859_1.py",
    "Lib/test/encoded_modules/module_koi8_r.py",
    "Lib/test/sortperf.py",
    "Lib/test/test_email/torture_test.py",
    "Lib/test/test_fstring.py",
    "Lib/test/test_genericpath.py",
    "Lib/test/test_getopt.py",
    "Lib/test/test_grammar.py",
    "Lib/test/test_htmlparser.py",
    "Lib/test/test_importlib/stubs.py",
    "Lib/test/test_importlib/test_files.py",
    "Lib/test/test_importlib/test_metadata_api.py",
    "Lib/test/test_importlib/test_open.py",
    "Lib/test/test_importlib/test_util.py",
    "Lib/test/test_named_expressions.py",
    "Lib/test/test_patma.py",
    "Lib/test/test_peg_generator/__main__.py",
    "Lib/test/test_pipes.py",
    "Lib/test/test_source_encoding.py",
    "Lib/test/test_weakref.py",
    "Lib/test/test_webbrowser.py",
    "Lib/tkinter/__main__.py",
    "Lib/tkinter/test/test_tkinter/test_variables.py",
    "Modules/_decimal/libmpdec/literature/fnt.py",
    "Modules/_decimal/tests/deccheck.py",
    "Tools/c-analyzer/c_parser/parser/_delim.py",
    "Tools/i18n/pygettext.py",
    "Tools/test2to3/maintest.py",
    "Tools/test2to3/setup.py",
    "Tools/test2to3/test/test_foo.py",
    "Tools/test2to3/test2to3/hello.py",
]

Next, to benchmark the release build:

cargo build --release

hyperfine --ignore-failure --warmup 1 \
  "./target/release/ruff ./resources/test/cpython/ --no-cache" \
  "./target/release/ruff ./resources/test/cpython/"

Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
  Time (mean ± σ):     353.6 ms ±   7.6 ms    [User: 2868.8 ms, System: 171.5 ms]
  Range (min  max):   344.4 ms  367.3 ms    10 runs

Benchmark 2: ./target/release/ruff ./resources/test/cpython/
  Time (mean ± σ):      59.6 ms ±   2.5 ms    [User: 36.4 ms, System: 345.6 ms]
  Range (min  max):    55.9 ms   67.0 ms    48 runs

To benchmark against the ecosystem's existing tools:

hyperfine --ignore-failure --warmup 5 \
  "./target/release/ruff ./resources/test/cpython/ --no-cache" \
  "pylint --recursive=y resources/test/cpython/" \
  "pyflakes resources/test/cpython" \
  "autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
  "pycodestyle resources/test/cpython" \
  "pycodestyle --select E501 resources/test/cpython" \
  "flake8 resources/test/cpython" \
  "flake8 --select=F831,F541,F634,F403,F706,F901,E501 resources/test/cpython" \
  "python -m scripts.run_flake8 resources/test/cpython" \
  "python -m scripts.run_flake8 resources/test/cpython --select=F831,F541,F634,F403,F706,F901,E501"

In order, these evaluate:

  • ruff
  • Pylint
  • PyFlakes
  • autoflake
  • pycodestyle
  • pycodestyle, limited to the checks supported by ruff
  • Flake8
  • Flake8, limited to the checks supported by ruff
  • Flake8, with a hack to enable multiprocessing on macOS
  • Flake8, with a hack to enable multiprocessing on macOS, limited to the checks supported by ruff

(You can poetry install from ./scripts to create a working environment for the above.)

Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
  Time (mean ± σ):     469.3 ms ±  16.3 ms    [User: 2663.0 ms, System: 972.5 ms]
  Range (min  max):   445.2 ms  494.8 ms    10 runs

Benchmark 2: pylint --recursive=y resources/test/cpython/
  Time (mean ± σ):     27.211 s ±  0.097 s    [User: 26.405 s, System: 0.799 s]
  Range (min  max):   27.056 s  27.349 s    10 runs

Benchmark 3: pyflakes resources/test/cpython
  Time (mean ± σ):     27.309 s ±  0.033 s    [User: 27.137 s, System: 0.169 s]
  Range (min  max):   27.267 s  27.372 s    10 runs

Benchmark 4: autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython
  Time (mean ± σ):      8.027 s ±  0.024 s    [User: 74.255 s, System: 0.953 s]
  Range (min  max):    7.969 s   8.052 s    10 runs

Benchmark 5: pycodestyle resources/test/cpython
  Time (mean ± σ):     41.666 s ±  0.266 s    [User: 41.531 s, System: 0.132 s]
  Range (min  max):   41.295 s  41.980 s    10 runs

Benchmark 6: pycodestyle --select E501 resources/test/cpython
  Time (mean ± σ):     14.547 s ±  0.077 s    [User: 14.466 s, System: 0.079 s]
  Range (min  max):   14.429 s  14.695 s    10 runs

Benchmark 7: flake8 resources/test/cpython
  Time (mean ± σ):     75.700 s ±  0.152 s    [User: 75.254 s, System: 0.440 s]
  Range (min  max):   75.513 s  76.014 s    10 runs

Benchmark 8: flake8 --select=F831,F541,F634,F403,F706,F901,E501 resources/test/cpython
  Time (mean ± σ):     75.122 s ±  0.532 s    [User: 74.677 s, System: 0.440 s]
  Range (min  max):   74.130 s  75.606 s    10 runs

Benchmark 9: python -m scripts.run_flake8 resources/test/cpython
  Time (mean ± σ):     12.794 s ±  0.147 s    [User: 90.792 s, System: 0.738 s]
  Range (min  max):   12.606 s  13.030 s    10 runs

Benchmark 10: python -m scripts.run_flake8 resources/test/cpython --select=F831,F541,F634,F403,F706,F901,E501
  Time (mean ± σ):     12.487 s ±  0.118 s    [User: 90.052 s, System: 0.714 s]
  Range (min  max):   12.265 s  12.665 s    10 runs

Summary
  './target/release/ruff ./resources/test/cpython/ --no-cache' ran
   17.10 ± 0.60 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'
   26.60 ± 0.96 times faster than 'python -m scripts.run_flake8 resources/test/cpython --select=F831,F541,F634,F403,F706,F901,E501'
   27.26 ± 1.00 times faster than 'python -m scripts.run_flake8 resources/test/cpython'
   30.99 ± 1.09 times faster than 'pycodestyle --select E501 resources/test/cpython'
   57.98 ± 2.03 times faster than 'pylint --recursive=y resources/test/cpython/'
   58.19 ± 2.02 times faster than 'pyflakes resources/test/cpython'
   88.77 ± 3.14 times faster than 'pycodestyle resources/test/cpython'
  160.06 ± 5.68 times faster than 'flake8 --select=F831,F541,F634,F403,F706,F901,E501 resources/test/cpython'
  161.29 ± 5.61 times faster than 'flake8 resources/test/cpython'

License

MIT

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

ruff-0.0.23.tar.gz (73.8 kB view details)

Uploaded Source

Built Distributions

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

ruff-0.0.23-py3-none-win_amd64.whl (1.7 MB view details)

Uploaded Python 3Windows x86-64

ruff-0.0.23-py3-none-win32.whl (1.6 MB view details)

Uploaded Python 3Windows x86

ruff-0.0.23-py3-none-musllinux_1_2_x86_64.whl (1.9 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ruff-0.0.23-py3-none-musllinux_1_2_i686.whl (1.8 MB view details)

Uploaded Python 3musllinux: musl 1.2+ i686

ruff-0.0.23-py3-none-musllinux_1_2_armv7l.whl (1.8 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

ruff-0.0.23-py3-none-musllinux_1_2_aarch64.whl (1.7 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ruff-0.0.23-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl (2.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ s390x

ruff-0.0.23-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl (2.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64le

ruff-0.0.23-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl (2.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ppc64

ruff-0.0.23-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

ruff-0.0.23-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.7 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ruff-0.0.23-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.8 MB view details)

Uploaded Python 3manylinux: glibc 2.12+ x86-64

ruff-0.0.23-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl (1.9 MB view details)

Uploaded Python 3manylinux: glibc 2.12+ i686

ruff-0.0.23-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl (3.4 MB view details)

Uploaded Python 3macOS 10.9+ universal2 (ARM64, x86-64)macOS 10.9+ x86-64macOS 11.0+ ARM64

ruff-0.0.23-py3-none-macosx_10_7_x86_64.whl (1.7 MB view details)

Uploaded Python 3macOS 10.7+ x86-64

File details

Details for the file ruff-0.0.23.tar.gz.

File metadata

  • Download URL: ruff-0.0.23.tar.gz
  • Upload date:
  • Size: 73.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.23.tar.gz
Algorithm Hash digest
SHA256 a93c9e1a969e01905154562412d2eeb9f5d473693054a7471b988a54c2b34e65
MD5 783dc4da88063200e0d812c58e77e6f1
BLAKE2b-256 fdc7522fc068aeb92b1c1ca5d6562aaf055e81442dfb67dd2241c9c3efa3b45f

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-win_amd64.whl.

File metadata

  • Download URL: ruff-0.0.23-py3-none-win_amd64.whl
  • Upload date:
  • Size: 1.7 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.23-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 00f90a2cbd278c3222f4109cf4d6a7ba695135863eba8ae8b47785b2136d1a77
MD5 d5b560a8ebd775a1721a84bc0e016084
BLAKE2b-256 8bc8a28441f460c9c47c1a038940808da00764ea50fe05e8605fd2b7a132b25e

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-win32.whl.

File metadata

  • Download URL: ruff-0.0.23-py3-none-win32.whl
  • Upload date:
  • Size: 1.6 MB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.23-py3-none-win32.whl
Algorithm Hash digest
SHA256 75875266be610025460402145c9ab97e5ebfc9f098aae19a8dbf664c969c8396
MD5 d4b8cf391ce313362cae580512edd270
BLAKE2b-256 ee0611ee174886173432e2447be8efc2cfd6e368c85e4cb436b2c623f801a0f9

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0ccdb700ea8a4ab4e684b51e979a29b20ace8c13b5a4cccafb1c3fa9a914ca30
MD5 69591db8e3035b2a6fc062d4148f1d39
BLAKE2b-256 90edda8ef02ebfb175635acc12efe67c8ed3c38bb12be2441ffba48da1c9adc4

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-musllinux_1_2_i686.whl.

File metadata

  • Download URL: ruff-0.0.23-py3-none-musllinux_1_2_i686.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: Python 3, musllinux: musl 1.2+ i686
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.8.10

File hashes

Hashes for ruff-0.0.23-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 4981771f34d319af3dba7642acb48fa8764189f410b6f6efeb608cc7de7c2bb0
MD5 382bde2526d2aa8edd9420e906635178
BLAKE2b-256 3cbfe2d9b7c7297621155891b83b80292dfd44af4b1d5e26d11fed7e53b71695

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-musllinux_1_2_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 390561dd41f9de08b517e2416250c297f2ad0e068d452561d76277bdc72a860d
MD5 c4748f4fc4fb8d1bcf1d5c2fe30fe386
BLAKE2b-256 2b02011dc42876661a2ae016c3af05c35eee7843785586b46e53354bf3f787a7

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 11ef357dddfbc541f1be081f52a4ea2b5d9c1f0c88e75629b500dffc92649a37
MD5 19809b584f8fe51bff10ad1d5206676e
BLAKE2b-256 87e4b3af204cecaa4da693ad3de5f531a4b4bc86f13aea7b4fd3e93ae6970bd1

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 20473b23d2c3840f15fba7a4697e3297a01d9d2635911aa5ed817c1bc64b92e5
MD5 ddcad8de75bcf905b75ca6e27dabf110
BLAKE2b-256 cf38885fad1d4ae59a19a5251180faefbc4096936bc41f447b56c4cfd842e6d0

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 b0a68e21d9632c9563e078224313c44f14cee558ef5cc700841c4fd269cd9395
MD5 a851e7ce3e65baf951f152377dc60210
BLAKE2b-256 83e7098ec68e4bc3e120b0b6721cd60d01130e6aa11c996aaecd9b2b681aed24

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 123e286248444a227564f3b4c5e6bfd15b660892f301c8a51e7b342bf00c6a02
MD5 f5b58612307ed48e6b9a7f0ce2288c89
BLAKE2b-256 df5df040df7348a86d4417946e023d610bbae88b1c8cc85fe9c546d16548400f

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 5f8df19f2fdcad76a6752e31d5a35ca76bee34eef11e3c9c977bdec59a2a0e6e
MD5 4bd8e458d96f68be8634c52a5a90419b
BLAKE2b-256 d55109d44750dd124b39a93a2a2cd7044629d16c0c8c847d7b1add970a39cf46

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 3d9306677bea221dd9638e9ae2f875cd63274b7a80a23b60bf65655aadffb2fc
MD5 ee5c018e85ad6fa979972bd0b7fd2fa1
BLAKE2b-256 40358996f590ca2964a5df293dc863f05a0eb9157ea99c898ee9acc7637d3d98

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 ad3336218028b0de87961802433b3ce12b7ad4916b2bdf595de1b9d39b512165
MD5 387a32d6b4ec80d9587f4f7b034cbed9
BLAKE2b-256 3ff15093da6f506780f941bf6a168352bf39dd0e6b8dee48ab7bfda23281d157

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 4324af612ad0dc117ea843c1b1fde6ba4181e77469ae970592d43025c64a0c10
MD5 a0635714c52324ccd1e0b526a6499910
BLAKE2b-256 33b0490ca87a767d3f1c810fff620d86af531dd18967d844a00d43cfe37417b5

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 00e3c415f7972d5c0cb908adc9dbb4a7d610c3746f1e05f985cd2507539cc276
MD5 a9433dc2922d101a2b8ac5c06fe99ff0
BLAKE2b-256 685c0c0252fa84dd239f9e03e315b9371e09d7af80e5c4f8e105a78e26f5e6b3

See more details on using hashes here.

File details

Details for the file ruff-0.0.23-py3-none-macosx_10_7_x86_64.whl.

File metadata

File hashes

Hashes for ruff-0.0.23-py3-none-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 aa91bd84cc470488ef1b23280b71af96e114b55b2901eeb42c39276e73ca5fe6
MD5 bd452dbd02fc6a2b55e52c26055d7db9
BLAKE2b-256 ffa394f85168bd8438d5357c6d3dcb4d59e709ab5064a541ec0e7592a515d02f

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