# Ruff [![image](https://img.shields.io/pypi/v/ruff.svg)](https://pypi.python.org/pypi/ruff) [![image](https://img.shields.io/pypi/l/ruff.svg)](https://pypi.python.org/pypi/ruff) [![image](https://img.shields.io/pypi/pyversions/ruff.svg)](https://pypi.python.org/pypi/ruff) [![Actions status](https://github.com/charliermarsh/ruff/workflows/CI/badge.svg)](https://github.com/charliermarsh/ruff/actions) 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 - πŸ“¦ Built-in caching, to avoid re-analyzing unchanged files - πŸ”§ Autofix support, for automatic error correction (e.g., automatically remove unused imports) - βš–οΈ [Near-parity](#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set - πŸ”Œ Native re-implementations of popular Flake8 plugins, like [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/) Ruff aims to be orders of magnitude faster than alternative tools while integrating more functionality behind a single, common interface. Ruff can be used to replace Flake8 (plus a variety of plugins), [`isort`](https://pypi.org/project/isort/), [`pydocstyle`](https://pypi.org/project/pydocstyle/), [`yesqa`](https://github.com/asottile/yesqa), and even a subset of [`pyupgrade`](https://pypi.org/project/pyupgrade/) and [`autoflake`](https://pypi.org/project/autoflake/) all while executing tens or hundreds of times faster than any individual tool. Ruff is extremely actively developed and used in major open-source projects like: - [FastAPI](https://github.com/tiangolo/fastapi) - [Bokeh](https://github.com/bokeh/bokeh) - [Zulip](https://github.com/zulip/zulip) - [Pydantic](https://github.com/pydantic/pydantic) - [Saleor](https://github.com/saleor/saleor) - [Hatch](https://github.com/pypa/hatch) Read the [launch blog post](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster). ## Testimonials [**SebastiΓ‘n RamΓ­rez**](https://twitter.com/tiangolo/status/1591912354882764802), creator of [FastAPI](https://github.com/tiangolo/fastapi): > Ruff is so fast that sometimes I add an intentional bug in the code just to confirm it's actually > running and checking the code. [**Bryan Van de Ven**](https://github.com/bokeh/bokeh/pull/12605), co-creator of [Bokeh](https://github.com/bokeh/bokeh/), original author of [Conda](https://docs.conda.io/en/latest/): > Ruff is ~150-200x faster than flake8 on my machine, scanning the whole repo takes ~0.2s instead of > ~20s. This is an enormous quality of life improvement for local dev. It's fast enough that I added > it as an actual commit hook, which is terrific. [**Tim Abbott**](https://github.com/charliermarsh/ruff/issues/465#issuecomment-1317400028), lead developer of [Zulip](https://github.com/zulip/zulip): > This is just ridiculously fast... `ruff` is amazing. ## Table of Contents 1. [Installation and Usage](#installation-and-usage) 1. [Configuration](#configuration) 1. [Supported Rules](#supported-rules) 1. [Pyflakes (F)](#pyflakes) 1. [pycodestyle (E)](#pycodestyle) 1. [isort (I)](#isort) 1. [pydocstyle (D)](#pydocstyle) 1. [pyupgrade (U)](#pyupgrade) 1. [pep8-naming (N)](#pep8-naming) 1. [flake8-bandit (S)](#flake8-bandit) 1. [flake8-comprehensions (C)](#flake8-comprehensions) 1. [flake8-boolean-trap (FBT)](#flake8-boolean-trap) 1. [flake8-bugbear (B)](#flake8-bugbear) 1. [flake8-builtins (A)](#flake8-builtins) 1. [flake8-debugger (T)](#flake8-debugger) 1. [flake8-tidy-imports (I25)](#flake8-tidy-imports) 1. [flake8-print (T)](#flake8-print) 1. [flake8-quotes (Q)](#flake8-quotes) 1. [flake8-annotations (ANN)](#flake8-annotations) 1. [flake8-2020 (YTT)](#flake8-2020) 1. [flake8-blind-except (BLE)](#flake8-blind-except) 1. [mccabe (C90)](#mccabe) 1. [Ruff-specific rules (RUF)](#ruff-specific-rules) 1. [Meta rules (M)](#meta-rules) 1. [Editor Integrations](#editor-integrations) 1. [FAQ](#faq) 1. [Development](#development) 1. [Releases](#releases) 1. [Benchmarks](#benchmarks) 1. [Reference](#reference) 1. [License](#license) 1. [Contributing](#contributing) ## Installation and Usage ### Installation Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI: ```shell pip install ruff ``` If you're a **macOS Homebrew** or a **Linuxbrew** user, you can also install `ruff` via Homebrew: ```shell brew install ruff ``` ### Usage To run Ruff, try any of the following: ```shell 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: ```shell ruff path/to/code/ --watch ``` Ruff also works with [pre-commit](https://pre-commit.com): ```yaml repos: - repo: https://github.com/charliermarsh/ruff-pre-commit rev: v0.0.142 hooks: - id: ruff ``` _Note: prior to `v0.0.86`, `ruff-pre-commit` used `lint` (rather than `ruff`) as the hook ID._ ## Configuration Ruff is configurable both via `pyproject.toml` and the command line. For a full list of configurable options, see the [API reference](#reference). If left unspecified, the default configuration is equivalent to: ```toml [tool.ruff] line-length = 88 # Enable Pyflakes `E` and `F` codes by default. select = ["E", "F"] ignore = [] # Exclude a variety of commonly ignored directories. exclude = [ ".bzr", ".direnv", ".eggs", ".git", ".hg", ".mypy_cache", ".nox", ".pants.d", ".ruff_cache", ".svn", ".tox", ".venv", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "venv", ] per-file-ignores = {} # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" # Assume Python 3.10. target-version = "py310" [tool.ruff.mccabe] # Unlike Flake8, default to a complexity level of 10. max-complexity = 10 ``` As an example, the following would configure Ruff to: (1) avoid checking for line-length violations (`E501`); (2), always autofix, but never remove unused imports (`F401`); and (3) ignore import-at-top-of-file errors (`E402`) in `__init__.py` files: ```toml [tool.ruff] # Enable Pyflakes and pycodestyle rules. select = ["E", "F"] # Never enforce `E501` (line length violations). ignore = ["E501"] # Always autofix, but never try to fix `F401` (unused imports). fix = true unfixable = ["F401"] # Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`. [tool.ruff.per-file-ignores] "__init__.py" = ["E402"] "path/to/file.py" = ["E402"] ``` Plugin configurations should be expressed as subsections, e.g.: ```toml [tool.ruff] # Add "Q" to the list of enabled codes. select = ["E", "F", "Q"] [tool.ruff.flake8-quotes] docstring-quotes = "double" ``` For a full list of configurable options, see the [API reference](#reference). Some common configuration settings can be provided via the command-line: ```shell ruff path/to/code/ --select F401 --select F403 ``` See `ruff --help` for more: ```shell Ruff: An extremely fast Python linter. Usage: ruff [OPTIONS] ... Arguments: ... Options: --config Path to the `pyproject.toml` file to use for configuration -v, --verbose Enable verbose logging -q, --quiet Only log errors -s, --silent Disable all logging (but still exit with status code "1" upon detecting errors) -e, --exit-zero Exit with status code "0", even upon detecting errors -w, --watch Run in watch mode by re-running whenever files change --fix Attempt to automatically fix lint errors -n, --no-cache Disable cache reads --select