Why Ruff

collaboration
development
workflow
standardisation

Enforcing style of code with automatic linters and formatters is important for code reviews to focus on content, not style. This post covers the reasons why we decided on Ruff for our linting and formatting purposes.

Published

November 27, 2023

Context and problem statement

Humans are prone to error when writing, whether it is code or text. In a team setting, more people working on the same things increase the chance of more issues occurring. And writing code is not done for the computer, but for other humans to read, so readability and consistency in style become important when reviewing that code. So our problem is:

How do we enforce a consistent style across people and code? And how do we catch simple errors that happen because of the style or format of the code?

Decision drivers

  • We want to review content and logical of code, not code style.
  • We want an automated way of fixing simple typographical errors and issues.
  • We want an automated way of enforcing a standard style.

Considered options

The terms “linting” or “formatting” are used to describe scanning, analysing, and (potentially) fixing code for style and typographical issues. The important difference between linting and formatting is that linting only tells you about the issues while formatting will fix (many of) the issues. Some issues can’t be solved from formatting alone, so both linting and formatting are often used together.

There are many tools available for Python, with many websites that have detailed comparisons of them (like this, this, or this website). Based on this list and based on quick searches on Google, these are the tools that come up the most often:

Below is a detailed description of the pros and cons based on what others have written about them.

Pylint

Benefits

  • Very old, well-established linter
  • Large community of users and contributors
  • Very comprehensive list of checks
  • Highly configurable
  • Is integrated into many other tools (like flake8, black, and ruff)
  • Linting feedback is extensive

Drawbacks

  • Too much configuration needed
  • Slow to run
  • Is often not needed to use on it’s own because it is integrated with other tools
  • Linting feedback is extensive and a bit overwhelming

Flake8

Benefits

  • Extensive list of checks
  • Includes many other linters
  • Often used with formatters like Black
  • Customizable
  • Large user base and community
  • Can use plugins to expand functionality

Drawbacks

  • Only lints and doesn’t format
  • Is integrated into newer tools (like Ruff), so might not need to be used on it’s own

Black

Benefits

  • Is a code formatter, not linter
  • Opinionated set of rules for code formatting, so removes need to configure things
  • Recommend to use with a linter (often suggested to use flake8 or pylint)

Drawbacks

  • Difficult to configure customizations
  • Integrated/compatible with newer tools (like Ruff)

Ruff

Benefits

  • Very fast
  • Implements almost all of Black and flake8 features
  • Implements many other features from other code analysis and checking tools
  • Is in very active development
  • Newer and has more modern development
  • Configuration is available and relatively straightforward to use
  • Can be implemented alongside other tools

Drawbacks

  • Is still new, so bugs and other features are still being developed
  • Does not yet have all of pylint features implemented

Decision outcome

We decided on Ruff because it is a newer tool that implements many of the other tools that exist. It also is designed to be mostly used “as is”, without needing to customize many things. It is also seems to be design in a way that makes customizations relatively easy to set up.

Potential consequences

  • We might miss out on some features from pylint (since right now we won’t include pylint)
  • There may be some bugs along the way because Ruff is relatively new, though this can be minimized by relying on more stable versions of it