Why Ruff
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.
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