Skip to content

4.5. Formatting

What is software formatting?

Software formatting refers to the process of organizing and structuring code in a way that makes it readable and maintainable. It involves adhering to a set of stylistic rules and conventions that cover aspects such as indentation, line length, variable naming, and the placement of braces and comments. Good formatting improves the clarity of the code, making it easier for developers to understand, navigate, and modify.

Why is software formatting important?

  1. Enhances Readability: Proper formatting makes code easier to read and understand. Consistent indentation and spacing help delineate code blocks, functions, and logical sections at a glance.
  2. Facilitates Collaboration: When working in a team, standardized formatting ensures that everyone can easily work with and understand each other's code, reducing the learning curve for new team members.
  3. Improves Maintainability: Well-formatted code is easier to debug, update, and extend. It helps developers identify structural and syntactic errors more quickly, and adhering to common conventions makes the code more predictable.

Since the inception of programming, there have been several debates, such as tabs vs. spaces or single quote vs. double quote. Having common conventions ensures we can standardize the Python codebase without rehashing these debates.

Is there a convention for formatting Python codebases?

The default convention for formatting Python codebases is PEP 8. It provides guidelines on various formatting issues such as naming conventions, indentation, line length, and comments. Following PEP 8 helps Python developers maintain a uniform coding style, enhancing code readability and maintainability.

Some conventions of PEP 8 might be adjusted to your environment (e.g., screen size). For instance, the default line length is 79, which may be a bit short for modern monitor widths. You can increase this setting to a more comfortable value, such as 100.

Which tools should you use to format a codebase in Python?

In recent years, black and isort have been the core tools for formatting Python codebases. Black specializes in code formatting, applying a consistent style to your Python code, while isort focuses on sorting and formatting import statements. However, Ruff offers a faster alternative that combines the benefits of both black and isort.

You can format your codebase as follows:

# ruff installation (one-time)
uv add --group checkers ruff
# format the imports
uv run ruff check --select you --fix src/ tests/
# format the sources
uv run ruff format src/ tests/

How can you automate the formatting of your codebase as you type?

Instead of formatting your codebase periodically from the command line, you can configure your code editor, such as VS Code, to automatically format code when you save a file.

Below is an example configuration for your [project].code-workspace file to automatically format files using VS Code's Ruff extension:

{
    "settings": {
        "editor.formatOnSave": true,
        "[python]": {
            "editor.codeActionsOnSave": {
                "source.organizeImports": true
            },
            "editor.defaultFormatter": "charliermarsh.ruff",
        },
    },
    "extensions": {
        "recommendations": [
            "charliermarsh.ruff",
        ]
    }
}

Should you change the default formatting proposed by the tools?

We recommend keeping the default settings in most cases to avoid debates on how your codebase should be formatted, with few exceptions.

In your pyproject.toml, you can configure Ruff formatting, such as the line length and docstring convention, to suit your project:

[tool.ruff]
fix = true
indent-width = 4
line-length = 100
target-version = "py312"

[tool.ruff.format]
docstring-code-format = true

[tool.ruff.lint.pydocstyle]
convention = "google"

Can you disable change or suppress formatting in some code location?

Sometimes, you might want to change or disable formatting to improve the readability of your code, such as in unit tests. You can do this in two ways:

  • Use soft instructions to force certain formatting, like adding a comma at the end of an enumeration to force one line per item:
items = {
    "a": 1,
    "b": 2,
    "c": 3,
}
# With the last comma, this dict will not be formatted as a single line:
# items = {"a": 1, "b": 2, "c": 3}
  • Use explicit instructions not to format a block of code with comments:
# fmt: off
not_formatted=3
also_not_formatted=4
# fmt: on

Formatting additional resources