Complete DevOps Bootcamp: Master DevOps in 12 Weeks
FastAPIProject Structure and Tooling

Code Formatting, Linting, and Typing

Introduction

Writing code that works is the first step. Writing code that is clean, consistent, and checked for errors is what makes it maintainable. FastAPI projects benefit from tooling that handles formatting, catches bugs through linting, and verifies type correctness.

Why This Matters

As a project grows and multiple developers contribute, consistent code style becomes critical. Without automated tools:

  • code style differs between files and contributors
  • common bugs get missed in review
  • type mismatches cause runtime errors that could have been caught earlier

These tools do not replace good thinking, but they catch a large category of mistakes automatically.

Code Formatting with Black

Black is an opinionated Python code formatter. It reformats your code to a consistent style with no configuration needed.

Installing Black

pip install black

Running Black

Format a single file:

black main.py

Format the entire project:

black .

Check what would change without actually changing it:

black --check .

What Black Does

# Before Black
def create_user(name:str,email:str,age:int)->dict:
    return {"name":name,"email":email,"age":age}

# After Black
def create_user(name: str, email: str, age: int) -> dict:
    return {"name": name, "email": email, "age": age}

Black applies consistent spacing, line length, and formatting rules across the entire codebase.

Linting with Ruff

Ruff is a fast Python linter. It checks your code for errors, unused imports, undefined variables, and style issues.

Installing Ruff

pip install ruff

Running Ruff

Check for issues:

ruff check .

Fix auto-fixable issues:

ruff check --fix .

What Ruff Catches

import os
import json  # unused import

def get_user(id):
    user = {"name": "Alice"}
    return user

Ruff flags import json as an unused import and can remove it automatically.

Configuring Ruff in pyproject.toml

[tool.ruff]
line-length = 88
select = ["E", "F", "I"]
ignore = ["E501"]

[tool.ruff.isort]
known-first-party = ["app"]
Rule setWhat it checks
EPEP 8 style errors
Fpyflakes errors like undefined names
Iimport sorting

Type Checking with mypy

FastAPI relies heavily on type hints. Mypy is a static type checker that verifies those hints are used consistently.

Installing mypy

pip install mypy

Running mypy

mypy app/

What mypy Catches

def add(a: int, b: int) -> int:
    return a + b

result = add("hello", 2)  # mypy catches this: expected int, got str

Mypy flags the incorrect argument type before the code ever runs.

Configuring mypy in pyproject.toml

[tool.mypy]
python_version = "3.11"
strict = false
ignore_missing_imports = true

Running mypy in strict mode catches more issues but requires all code to be fully annotated.

Combining the Tools

A typical setup runs all three tools together. You can add them to a development workflow or CI pipeline.

Example development check sequence:

black .
ruff check --fix .
mypy app/

Pre-commit Hooks

Pre-commit runs these tools automatically before every git commit, catching issues before they enter the repository.

Installing pre-commit

pip install pre-commit

Example .pre-commit-config.yaml

repos:
  - repo: https://github.com/psf/black
    rev: 24.3.0
    hooks:
      - id: black

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.3.5
    hooks:
      - id: ruff
        args: [--fix]

Activating the hooks

pre-commit install

After this, every git commit automatically runs Black and Ruff on staged files.

Tool Comparison

ToolPurposeSpeed
BlackCode formattingFast
RuffLinting and import sortingVery fast
mypyStatic type checkingModerate

Common Mistakes

Skipping type hints because mypy is optional

FastAPI uses type hints for request validation and documentation generation. Incomplete type hints mean missing validation and inaccurate docs.

Formatting and linting only locally

Add these checks to your CI pipeline so every pull request is verified automatically.

Using conflicting tools

Black and some older formatters conflict on line length. When using Black, configure Ruff to use the same line length (default is 88 for both).

Summary

Black formats code consistently, Ruff catches linting and import errors quickly, and mypy checks that type hints are correct. Together these tools keep a FastAPI project clean and prevent common mistakes from reaching production. Setting them up with pre-commit hooks ensures the checks run automatically before every commit.

How is this guide?

Last updated on

Telusko Docs