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

ruff also works with Pre-Commit (requires Cargo on system):

repos:
- repo: https://github.com/charliermarsh/ruff
  rev: v0.0.24
  hooks:
    - id: lint

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.24.tar.gz (75.3 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.24-py3-none-win_amd64.whl (1.7 MB view details)

Uploaded Python 3Windows x86-64

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

Uploaded Python 3Windows x86

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

Uploaded Python 3musllinux: musl 1.2+ x86-64

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

Uploaded Python 3musllinux: musl 1.2+ i686

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

Uploaded Python 3musllinux: musl 1.2+ ARMv7l

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

Uploaded Python 3musllinux: musl 1.2+ ARM64

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

Uploaded Python 3manylinux: glibc 2.17+ s390x

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

Uploaded Python 3manylinux: glibc 2.17+ ppc64le

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

Uploaded Python 3manylinux: glibc 2.17+ ppc64

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

Uploaded Python 3manylinux: glibc 2.17+ ARMv7l

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

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ruff-0.0.24-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.24-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl (1.9 MB view details)

Uploaded Python 3manylinux: glibc 2.12+ i686

ruff-0.0.24-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.24-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.24.tar.gz.

File metadata

  • Download URL: ruff-0.0.24.tar.gz
  • Upload date:
  • Size: 75.3 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.24.tar.gz
Algorithm Hash digest
SHA256 db2e628ef5c7e712ce8c4d1783e6a8b606db2372e64a0c10b47bb2ac6bcc997c
MD5 0532c1da68af05f61e7b219b5e925630
BLAKE2b-256 7fc2c87bb38f63ce83408c46ce90b0242dbd6adffd62fa8593db25274cf0d2d3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.0.24-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.24-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 fcdc7fa3563bb58bead73726222db20e813130a5d953ed0dafb7c6a873da07b4
MD5 23263dbe4075130e7880bce4367bd617
BLAKE2b-256 849d18c65ad0865bb7dd82575a7c6cd8fcd6f43516819ddd0bba3ed5035c7e81

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.0.24-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.24-py3-none-win32.whl
Algorithm Hash digest
SHA256 20ed8bdfae5f506cf769327bcb430b5f99def970c82844a4c0223056a8a8d5b3
MD5 ead1b36368df13d8a71aa75596287780
BLAKE2b-256 079cb89d236157ad9a4819f8a3258793677ac8fdec2119106e6a95a46f6afcdb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 fccf093d14de15b90a77f366e011874e482f578f936a91a39c0cbf1704e329c7
MD5 eaa492fdf9570a49132167a434943632
BLAKE2b-256 1459adefb1328341d72ce101eecf86fecf3f177e6b1f5fc461b3daf30b36f665

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ruff-0.0.24-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.24-py3-none-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 135620cc9ab270ef15a8d7c6117c18a8ff431ddefc6c629e838b9d482b4ffa39
MD5 54c8b9ec93a60611c1d30a2de62ab9e1
BLAKE2b-256 ad0fe074ca03f6a4e5493e1a8b508c553e358908cb844a4e9c202ae19bbd26be

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-musllinux_1_2_armv7l.whl
Algorithm Hash digest
SHA256 e83337ab097acff2438e7837f01479c98040b4e5e85d865ce0bb72d6fc25cdaa
MD5 d713a987992d65ed5978cf42eca66d22
BLAKE2b-256 804a25038a98f4a9ba9fad5abc8a9fcff91c77e933901f85daa67162cccef384

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 817fc70a55ee10d72147901bf9cc0bb432845f3e408ac028d9d90c70377cce1c
MD5 23b241f44a9502903a1d2556120e8da1
BLAKE2b-256 c092822d6c45b40758dbb22fc7ad80454bd6b9c1a2b1047cc7eecd35331b26e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl
Algorithm Hash digest
SHA256 a948bb3ddbb6ffa97a9e6ad364c5707817c53890ffc8e2090b5eca8206246634
MD5 0d224958d399aecc954bd691673bc83b
BLAKE2b-256 5ff94b883cb94b301702c668cca5dd6831b667429279c7a4dab533dd975b2560

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
Algorithm Hash digest
SHA256 a3cb9531bc7fa58b5d64c920f20fda4d31c099835b67d187ebd5230ad23a6bb5
MD5 f8dbbdff04c34e32e4d124b32081727c
BLAKE2b-256 12551ff945ec4e480d8fa477cfefb873139ec55ab0edd3efa4016f77e832d677

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl
Algorithm Hash digest
SHA256 ce84a674e3945d053127f251279ab730937fa5b356b56fd76cb033f597bf0962
MD5 d35f2f91aab41f1600d7a0ad2abcfa0c
BLAKE2b-256 0e8178114d9512dcb573122518c0dc9123726b6a0c91cac531518cea30b17153

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 dc7e7e087509da6d4b7aad49616906ae4cabf8173ca5993d8d3c6e038941ef54
MD5 20f80452d161f8440e5ffa1a24a1513c
BLAKE2b-256 6231fab32df5090bacc106c56963167d896594d787d1ac3218447f809d8bca13

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 c74ede2a272229af9fddbf7dc2fc6e7653a6423abf0f9f2017fe4fdd5f855200
MD5 412c0eaa84089d94e474a447b1768f8e
BLAKE2b-256 bf1e78bc7c30ada8d1379f37329f51a78e8897c88db4ca7651deb6f6976ae705

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 ec099bf4a147b917bb870335557e734855a7d4a3b745065e2d5fe4659fca20b2
MD5 8b3c7855754099138e089baba76c13f1
BLAKE2b-256 e3525a44217c324bc64924b9c43b8fa9d7bd134a8bf53ba0a5d406d37b467bff

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 8436a8b76e276f32768ece4b9d41ffda9600c4edb4f31d018d545590ecc3f7c5
MD5 5c8aa94a9c8ba0c2d3c716481f2a280b
BLAKE2b-256 6acc009fe06114b3d1a399cde52b179b06a2b3c531a1a13f54e797637e2277b2

See more details on using hashes here.

File details

Details for the file ruff-0.0.24-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.24-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl
Algorithm Hash digest
SHA256 52df360a633335bf62d8e039e6f764c52fbeae2363cefb7287ffaa3b32c9cf50
MD5 44e639bb558b249666961b87092bb2cd
BLAKE2b-256 889bd626ee9c1ec36c0e962efce568a81c5f29684a6e1f1b10e6970ba6275946

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ruff-0.0.24-py3-none-macosx_10_7_x86_64.whl
Algorithm Hash digest
SHA256 7f9f459031b12121d692052175b9269beceaec85f808ea55b21413129fe4de07
MD5 92e14426efe957a833de06df9b447f02
BLAKE2b-256 90c6708c5d292fb2f300b6014c79c35670c1262a63c2bc66d2d616f583866687

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