> ## 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.

# Code Quality

> Code quality standards and tools for Home Assistant Core

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

```bash theme={null}
# 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`:

```toml theme={null}
[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

```bash theme={null}
# 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`:

```toml theme={null}
[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

```bash theme={null}
# 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:

```python theme={null}
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.

```bash theme={null}
# Check spelling
codespell

# Via pre-commit
prek run codespell
```

Configuration in `.pre-commit-config.yaml`:

```yaml theme={null}
- 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.

```bash theme={null}
# 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

```bash theme={null}
prek install
```

### Hook Configuration

Hooks are defined in `.pre-commit-config.yaml`:

```yaml theme={null}
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

```bash theme={null}
# 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:

```python theme={null}
"""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:

```toml theme={null}
[tool.ruff.lint.isort]
force-sort-within-sections = true
known-first-party = ["homeassistant"]
combine-as-imports = true
```

### Docstrings

Use Google-style docstrings:

```python theme={null}
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:

```toml theme={null}
[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_`:

```python theme={null}
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:

```bash theme={null}
ruff check --select I --fix path/to/file.py
```

### Type Hint Issues

Add missing type hints:

```python theme={null}
# 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:

```python theme={null}
# 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:

```python theme={null}
# 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`:

```json theme={null}
{
  "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

* [Ruff documentation](https://docs.astral.sh/ruff/)
* [Pylint documentation](https://pylint.readthedocs.io/)
* [Mypy documentation](https://mypy.readthedocs.io/)
* [Home Assistant Developer Docs - Code Review](https://developers.home-assistant.io/docs/development_checklist)
* [Python Type Hints (PEP 484)](https://peps.python.org/pep-0484/)
