Ruff

Ruff is a fast, Python-native linter and code analyzer that focuses on speed and functionality. It provides linting, auto-fixing, and even some formatting capabilities, acting as a lightweight alternative or complement to tools like flake8, pylint, and even Black.
Author

Benedict Thekkel

1. What is Ruff?

  • Purpose: Ruff is a Python linter designed to enforce style guides and find potential bugs in your code.
  • Performance: Written in Rust, Ruff is extremely fast and can lint large codebases quickly.
  • Features: Combines functionality from multiple tools like flake8, pylint, mypy, and isort into one package.

2. Key Features

  • Speed: Ruff is significantly faster than traditional Python linters due to its Rust implementation.
  • All-in-One: Supports rules from:
    • flake8 (and many of its plugins)
    • isort (import sorting)
    • pylint (selected rules)
    • mypy (type-related linting)
  • Auto-fixes: Ruff can automatically fix some linting issues.
  • Highly Configurable: You can customize rules, exclude files, and more.

3. Installation

Install Ruff using pip:

pip install ruff

Alternatively, install Ruff via pipx for isolated environments:

pipx install ruff

4. Basic Usage

Run Ruff on your project directory:

ruff .

Common Commands:

  • Check for Issues:

    ruff check .
  • Auto-Fix Issues:

    ruff check . --fix
  • Specify Files:

    ruff path/to/file.py
  • Exclude Files or Directories:

    ruff check . --exclude path/to/exclude

5. Configuration

Ruff can be configured using a pyproject.toml or .ruff.toml file in your project root. Example configuration:

pyproject.toml

[tool.ruff]
select = ["E", "F", "W"]  # Enable specific linting rules
ignore = ["W503"]         # Ignore specific rules
exclude = ["migrations", "__init__.py"]
line-length = 88          # Set maximum line length
fixable = ["F401", "E501"] # Rules that Ruff is allowed to fix

.ruff.toml

If you prefer a standalone file:

[tool.ruff]
select = ["E", "F", "I"]
exclude = ["migrations"]
line-length = 88

6. Rules

Ruff supports a wide range of rules, including those from common tools:

Supported Plugins:

  • flake8 Rules:
    • F (pyflakes)
    • E/W (pep8)
    • C90 (McCabe complexity)
  • isort Rules:
    • Automatically sort and organize imports.
  • pylint Rules:
    • Includes rules like unused imports, variable naming, etc.
  • mypy Rules:
    • Linting based on type annotations.

For a full list of supported rules, refer to the official Ruff rules documentation.

7. Integrating Ruff into Your Workflow

a. Pre-commit Hooks

  1. Install pre-commit:

    pip install pre-commit
  2. Add Ruff to your .pre-commit-config.yaml:

    repos:
      - repo: https://github.com/charliermarsh/ruff-pre-commit
        rev: v0.0.289  # Use the latest version
        hooks:
          - id: ruff
            args: ["--fix"]  # Optional: Auto-fix issues
  3. Install the pre-commit hooks:

    pre-commit install

Now, Ruff will run automatically before every commit.

b. CI/CD Integration

GitHub Actions Example:

name: Lint Code with Ruff

on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: 3.9
      - name: Install Ruff
        run: pip install ruff
      - name: Run Ruff
        run: ruff check .

c. IDE Integration

  • VS Code:
    1. Install the Python extension.

    2. Configure the Python linter in settings.json:

      "python.linting.enabled": true,
      "python.linting.ruffEnabled": true,
      "python.linting.ruffPath": "ruff",  // Path to the Ruff executable
      "editor.codeActionsOnSave": {
          "source.organizeImports": true
      }
  • PyCharm:
    1. Install Ruff globally or in your virtual environment.
    2. Configure a File Watcher for Ruff:
      • Go to File > Settings > Tools > File Watchers.
      • Add a new File Watcher for Ruff.

8. Comparing Ruff to Other Tools

Advantages

  1. Speed: Faster than Python-based linters like flake8 or pylint.
  2. Multi-tool Functionality: Combines features from multiple tools.
  3. Auto-fixing: Handles both linting and some formatting issues.

Disadvantages

  1. Rule Overlap: May conflict with Black, especially on formatting rules.
  2. Limited Plugins: Ruff doesn’t support every plugin that flake8 does (e.g., flake8-docstrings).

9. Combining Ruff with Other Tools

With Black

  • Use Black for formatting and Ruff for linting.

  • Configure Ruff to ignore Black’s formatting rules:

    [tool.ruff]
    select = ["F", "E"]
    line-length = 88

With isort

  • Ruff includes import sorting rules similar to isort. Disable isort separately or rely on Ruff’s functionality.

10. FAQ

Q1: Does Ruff replace Black?

Ruff can handle some formatting tasks, but it doesn’t fully replace Black. Use Ruff for linting and Black for formatting.

Q2: Can Ruff work with type checking?

Yes, Ruff supports some type-related checks via mypy-like rules.

Q3: How do I exclude specific directories or files?

Use the --exclude flag or add exclusions in pyproject.toml.

Summary of Commands

Command Description
ruff . Lint all files in the directory.
ruff check . Check for issues without fixing.
ruff check . --fix Fix issues automatically.
ruff --config pyproject.toml Use a specific config file.
Back to top