Code Standards and Consistency with Ruff Linter and Formatter
Tags: python, opensource, tutorial, beginners
Published: 2023-11-03 09:47:48

This week, I decided to add a Linter and Formatter to my codebase. I've used them previously with a project called fragments, which was handy for keeping JavaScript and HTML code standards in check. However, using it for Python is completely foreign to me, especially considering how much easier it is to write stronger code using Python. 

## Adding CONTRIBUTING.md

Outside of adding a linter and formatter, I finally added a CONTRIBUTING.md file to my project, in hopes that anyone who wishes to make it better than it is, can do so easily. I learned of a very awesome [generator for these md files](https://generator.contributing.md/) and decided to use it for mine.

## Adding Ruff

[Ruff](https://docs.astral.sh/ruff/) is a dual linter and code formatter made in Rust for Python. Very helpful for what I needed and a huge change from previously using eslint and prettier for everything. Also unlike eslint and prettier, ruff comes pre-packaged to work right off the installation. Another interesting aspect of ruff's formatter is that it's actually compatible with [Black](https://pypi.org/project/black/) another code formatter used in Python. For ease of use and limiting the amount required to install, I just decided to use Ruff. 

The formatter is extremely easy to use - simply running `ruff format .` will fix formatting for a file - and highly customizable and can easily be adjusted by creating a `pyproject.toml` file, though, the only customization I needed was to exclude certain files and folders from being formatted done as shown below: 

```toml
[tool.ruff.format]
exclude = ["examples/", ".venv/", ".ruff_cache/", "*.md", "*.txt", "LICENSE", ".gitignore"]
```

The linter was also just as easy to use - simply running `ruff check . --fix` linted a directory and instantly fixed standard errors - and came with a slew of options for customization and configuration. For the ruff-lint configuration, I used one of the templated setups found in the [official configuring ruff page](https://docs.astral.sh/ruff/configuration/#using-pyprojecttoml) to handle all the linting needs. 

Another benefit to using ruff is that I simply added it to my requirements.txt file allowing anyone who may want to run the app to install it and be able to utilize it. VSCode has an official plugin for it as well which allowed me to turn on automatic linting:


![RuffAutoLint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61jwbm1o6a9re53qiy8h.png)

Ruff features a neat feature where it will check for specific comments to skip over re-formatting a specific chunk of code. Adding `# fmt: off` and `# fmt: on` around a code block would prevent it from getting formatted.

## How effective were they?

Well to be quite honest, linting my file didn't do too much, mostly because I tried to keep my implementation as bare-bones as possible but there was one error, which was an unused import:
```
main.py:14:31: F401 [*] `typing_extensions.Annotated` imported but unused
Found 1 error.
[*] 1 fixable with the `--fix` option.
```
When formatting my file, it changed a good deal, mainly in the way it handled my main function header and the formatting for it. Other than that, it seemed to have changed mostly small indentation errors here and there.

## What's next?

I want to try and implement a pre-commit hook onto my code, so that it can auto-lint and format everything before each commit. I wasn't able to get it this time around due to time constraints but it's definitely something I'd love to look into since it's very foreign to me. 

## TIL

Today I learned about Ruff, a very awesome library that contains not only a source code formatter, but a linter as well! I learned the basics of utilizing the formatter and the linter as well as basic setup for both. It's awesome stuff and really goes to show just how amazing Python and the community surrounding it is.