Code Style

What is it? Why do it?

“Code style” describes the conventions you use in writing the source files for your code base. If there are multiple people working on a code base, it’s important to establish an agreeable code style so everyone can easily read and modify the code.

Linters

Linting is a form of static program checking, meaning that it analyzes code without running it.

A linter checks code for code errors, violations of some agreed-upon coding standards, or gives its opinion on code smells. A “code smell” is when something isn’t exactly wrong, but could be an indicator that your code is inefficient or could be refactored to be cleaner.

When code is reliably run through a linter, then code reviewers can assume that the code they’re looking at adheres to that agreed-upon coding standard. A code reviewer won’t be distracted by improper spacing, and can focus their reviewing effort on the meat of the code.

These tools often do not change your code to adhere to a standard, they just alert you to potential issues.

The template currently offers two tools for linting:

  • pylint - slow and thorough

  • ruff - very fast, usually good enough.

Auto-formatters

Auto-formatting tools will change your source files, to adhere to a consistent visual style. These tools often do not interpret your code for syntax errors or code smells.

The template currently offers three tools for auto-formatting:

  • black - general code formatting

  • isort - import statement sorting and organizing

  • ruff format - general code formatting

Different formatters share a lot of the same opinions, but we recommend picking a single standard for your project and sticking to it. If some folks use different formatters, this may cause undue churn in your source files as each developer creates some formatting changes each time they touch a file (and then another developer undoes them the next time they touch the same file). Two good configurations are to use ruff for all your code style needs OR use some combination of pylint, black, and isort.

Ruff

Ruff is a very performant and highly customizable linting tool, that can also perform auto-formatting.

This tool can be run on its own in linting (warning) mode with command like:

>> ruff check

This tool can be run on its own in auto-formatting mode with command like:

>> ruff format

Modifying ruff

The configuration for ruff is maintained in the pyproject.toml file. Ruff has many rules split into groups that can be selected to use when checking code. By default, we mostly follow the set of rules suggested by the ruff documentation, with a few extra rules as suggested by Rubin Data Management. For more information on configuration, see ruff’s documentation here: https://docs.astral.sh/ruff/configuration/

Pylint

pylint is a linting tool. It is fairly opinionated, but highly customizable. It’s very thorough, but that means it’s also among the slower of the linting options out there.

Modifying pylint

There are lots of errors and coding standards that the linter can search for, but you may not want to include all of them, or modify the values of certain checks such as line length to fit the agreed standards in your project. To do this, pylint allows project wide configuration in either the project’s pyproject.toml file, or in a separate .pylintrc file.

We have found in our projects that one configuration across both source and test files is inadequate, and that separate standards are needed in each, for example, in requiring that methods contain docstrings. So we generate two .pylintrc files, one under src and the other under tests. When pylint is run in the pre-commit hooks and the github actions, it is run twice, once on the source files with the src config, and once on the test files with the tests config.

For more on how to configure the pylint options, take a look at pylint’s documentation.

Black

Black is a very opinionated auto-formatting tool. It ensures that all code in your project uses consistent formatting (e.g. spacing, quote styles, line breaks).

This tool can be run on its own with command like:

>> black .

Modifying Black

Black and doesn’t permit much in the way of customization. The configurations that are available are defined in pyproject.toml under the [tool.black] section. For more details see Black’s documentation on configuration: https://black.readthedocs.io/en/latest/usage_and_configuration/the_basics.html#configuration-via-a-file

isort

isort is a standalone tool that will sort and organization imports in all the .py and .pyi files in your project.

This tool can be run on its own with command like:

>> isort .

How to switch or remove tools

If you started a project without selecting a linter, or you want to change or remove the linter entirely, use the copier update command to change the response to the “What tooling set would you like to use to enforce code style?” question. This will add or remove steps to check code style against the selected tools.