Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/home-assistant/core/llms.txt

Use this file to discover all available pages before exploring further.

Home Assistant maintains high code quality standards through automated linting, formatting, and type checking.

Code Quality Tools

Ruff

Ruff is a fast Python linter and formatter that enforces code style and catches common issues.

Running Ruff

# Check for issues
ruff check .

# Check and automatically fix issues
ruff check --fix .

# Format code
ruff format .

# Check only changed files
prek run ruff-check

Configuration

Ruff is configured in pyproject.toml:
[tool.ruff]
required-version = ">=0.15.1"

[tool.ruff.lint]
select = [
  "E",      # pycodestyle errors
  "F",      # pyflakes/autoflake
  "W",      # pycodestyle warnings
  "I",      # isort (import sorting)
  "UP",     # pyupgrade (modern Python syntax)
  "ASYNC",  # flake8-async
  "B",      # flake8-bugbear
  "SIM",    # flake8-simplify
  "PL",     # pylint
  "RUF",    # ruff-specific rules
  # ... and many more
]

Pylint

Pylint provides deeper code analysis with custom Home Assistant plugins.

Running Pylint

# Lint a specific file
pylint homeassistant/components/light/init.py

# Lint changed files
script/lint

# Lint via pre-commit
prek run pylint

Custom Plugins

Home Assistant includes custom pylint plugins in pylint/plugins/:
  • hass_async_load_fixtures - Validates fixture loading patterns
  • hass_decorator - Checks decorator usage
  • hass_enforce_class_module - Ensures classes are in correct modules
  • hass_enforce_sorted_platforms - Enforces platform sorting
  • hass_enforce_type_hints - Requires type hints
  • hass_imports - Validates import patterns
  • hass_logger - Checks logger usage

Configuration

Pylint is configured in pyproject.toml:
[tool.pylint.MAIN]
py-version = "3.14"
jobs = 2
load-plugins = [
  "pylint.extensions.code_style",
  "pylint.extensions.typing",
  "hass_async_load_fixtures",
  "hass_decorator",
  # ... custom plugins
]

Mypy

Mypy performs static type checking to catch type-related bugs.

Running Mypy

# Check all files
mypy homeassistant/

# Check specific file
mypy homeassistant/components/light/__init__.py

# Via pre-commit
prek run mypy

Type Hints

All new code must include type hints:
from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry

async def async_setup_entry(
    hass: HomeAssistant,
    entry: ConfigEntry,
) -> bool:
    """Set up from a config entry."""
    return True

Strict Typing

Certain modules enforce strict typing. These are tracked in the .strict-typing file.

Codespell

Catches spelling mistakes in code, comments, and documentation.
# Check spelling
codespell

# Via pre-commit
prek run codespell
Configuration in .pre-commit-config.yaml:
- id: codespell
  args:
    - --ignore-words-list=aiport,astroid,checkin,currenty,hass,iif,incomfort,lookin,nam,NotIn
    - --skip="./.*,*.csv,*.json,*.ambr"
    - --quiet-level=2

Hassfest

Validates integration metadata, manifests, and configurations.
# Run hassfest checks
python3 -m script.hassfest

# Via pre-commit
prek run hassfest
Hashfest validates:
  • Integration manifests (manifest.json)
  • Service definitions (services.yaml)
  • String translations (strings.json)
  • Icons (icons.json)
  • Requirements and dependencies

Pre-commit Hooks

Home Assistant uses prek (a pre-commit hook manager) to run quality checks automatically.

Install Hooks

prek install

Hook Configuration

Hooks are defined in .pre-commit-config.yaml:
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    hooks:
      - id: ruff-check
        args: [--fix]
      - id: ruff-format

  - repo: https://github.com/codespell-project/codespell
    hooks:
      - id: codespell

  - repo: local
    hooks:
      - id: mypy
        entry: script/run-in-env.sh mypy
      - id: pylint
        entry: script/run-in-env.sh pylint --ignore-missing-annotations=y
      - id: hassfest
        entry: script/run-in-env.sh python3 -m script.hassfest

Running Hooks Manually

# Run all hooks on all files
prek run --all-files

# Run specific hook
prek run ruff-check --all-files

# Run hooks on specific files
prek run --files path/to/file.py

Code Style Guidelines

Imports

Imports should be organized and sorted:
"""Module docstring."""
# Standard library imports
import asyncio
import logging
from typing import Any

# Third-party imports
import voluptuous as vol

# Home Assistant imports
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
Ruff’s isort integration handles this automatically:
[tool.ruff.lint.isort]
force-sort-within-sections = true
known-first-party = ["homeassistant"]
combine-as-imports = true

Docstrings

Use Google-style docstrings:
def my_function(param1: str, param2: int) -> bool:
    """Brief description of function.

    Longer description if needed.

    Args:
        param1: Description of param1.
        param2: Description of param2.

    Returns:
        Description of return value.

    Raises:
        ValueError: When parameter is invalid.
    """
    return True
Configuration:
[tool.ruff.lint.pydocstyle]
convention = "google"

Line Length

Maximum line length is not strictly enforced (E501 is disabled), but keep lines reasonable for readability. Ruff’s formatter will handle most cases.

Naming Conventions

  • Variables and functions: snake_case
  • Classes: PascalCase
  • Constants: UPPER_CASE
  • Private methods: _leading_underscore

Async Code

Prefix async functions with async_:
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up from config entry."""
    await async_initialize()
    return True

Common Issues and Fixes

Import Sorting

If imports are out of order:
ruff check --select I --fix path/to/file.py

Type Hint Issues

Add missing type hints:
# Before
def my_function(hass, config):
    pass

# After
def my_function(hass: HomeAssistant, config: dict[str, Any]) -> None:
    pass

Pylint: Too Many Arguments

Refactor functions with too many parameters:
# Before: Too many arguments
def setup(hass, config, arg1, arg2, arg3, arg4, arg5, arg6):
    pass

# After: Use a config object or dataclass
from dataclasses import dataclass

@dataclass
class SetupConfig:
    arg1: str
    arg2: int
    # ...

def setup(hass: HomeAssistant, config: SetupConfig) -> None:
    pass

Complexity Issues

If code is too complex (McCabe complexity > 25), refactor:
# Break complex functions into smaller ones
def complex_function():
    result = _step_one()
    result = _step_two(result)
    return _step_three(result)

def _step_one():
    pass

def _step_two(data):
    pass

def _step_three(data):
    pass

Integration Quality Scale

Home Assistant uses a quality scale for integrations:
  • Platinum - Highest quality, exemplary code
  • Gold - High quality, good example to follow
  • Silver - Good quality
  • Bronze - Basic quality requirements met
Quality level is indicated in manifest.json:
{
  "domain": "example",
  "quality_scale": "gold"
}
When looking for code examples, refer to Platinum or Gold-level integrations.

Automated Checks

All checks run automatically in CI/CD:

On Pre-commit

  • Ruff formatting and linting
  • Codespell
  • Mypy type checking (for changed files)
  • Pylint (for changed files)
  • Hassfest validation

On Pull Request

  • All pre-commit checks
  • Full test suite
  • Coverage report
  • Additional validation checks

Best Practices

Write Clean Code

  • Keep it simple - Avoid unnecessary complexity
  • Be consistent - Follow existing patterns
  • Use type hints - Makes code self-documenting
  • Add docstrings - Explain what and why, not how
  • Handle errors - Don’t let exceptions crash Home Assistant

Performance

  • Avoid blocking I/O - Use async for I/O operations
  • Cache when appropriate - Don’t repeat expensive operations
  • Clean up resources - Implement proper shutdown handlers

Security

  • Validate input - Never trust user input
  • Use constants - Avoid hardcoded secrets
  • Handle credentials safely - Use config entries for sensitive data

Resources