-
Notifications
You must be signed in to change notification settings - Fork 9
Developer Code Standards
Jason Rhubottom edited this page Apr 20, 2026
·
1 revision
We use Ruff for linting and formatting, configured in pyproject.toml.
Configuration:
- Select:
["ALL"]- Enable all rules by default - Specific ignores for formatter conflicts and false positives
- Home Assistant import conventions:
cv,dr,er,ir,vol - Force sorting within sections for imports
Run linting:
./scripts/lintImports are organized into sections:
"""Module docstring."""
# 1. Future imports
from __future__ import annotations
# 2. Standard library
import logging
from typing import Any
# 3. Third-party libraries
import voluptuous as vol
from astral import LocationInfo
# 4. Home Assistant core
from homeassistant.core import HomeAssistant, callback
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers import config_validation as cv
# 5. Local imports
from .const import DOMAIN, CONF_SENSOR_TYPE
from .coordinator import AdaptiveDataUpdateCoordinatorThis integration uses Home Assistant's async architecture:
DO:
async def async_my_function():
"""Async function."""
result = await some_async_call()
return result
@callback
def _sync_callback():
"""Callback function (no I/O)."""
return valueDON'T:
def blocking_function():
"""This blocks the event loop!"""
time.sleep(1) # β Never block!
return requests.get(url) # β Use aiohttp!Rules:
- Never block the event loop
- Use
async/awaitfor I/O operations - Use
@callbackdecorator for sync callbacks - Use
hass.async_add_executor_job()for blocking calls
Use the logging adapter with context:
from .config_context_adapter import get_adapter
_LOGGER = logging.getLogger(__name__)
# In your class
self._adapter = get_adapter(_LOGGER, self._name)
# Log with context
self._adapter.debug("Message here")Log levels:
-
debug()- Detailed diagnostic information -
info()- General informational messages -
warning()- Warning messages (recoverable issues) -
error()- Error messages (serious problems)
Follow Home Assistant conventions:
# Entity ID format
entity_id = f"{domain}.{type}_{description}_{name}"
# Examples
"sensor.adaptive_cover_position_living_room"
"switch.adaptive_cover_control_bedroom"
"binary_sensor.adaptive_cover_sun_in_window_office"Use Home Assistant's voluptuous integration:
import voluptuous as vol
from homeassistant.helpers import config_validation as cv
CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_NAME): cv.string,
vol.Optional(CONF_FOV, default=90): vol.All(
vol.Coerce(int),
vol.Range(min=1, max=180)
),
})π Getting Started
- Installation
- Migrating from Custom Repository
- Migrating from Adaptive Cover
- First-Time Setup
- Cover Types
π§ Core Concepts
π Cover Types
βοΈ Configuration
- Sun Tracking
- Position
- Glare Zones
- Automation
- Custom Position
- Force Override
- Weather Safety
- Climate
- Blindspot
- Summary Screen
- Debug & Diagnostics
π Entities & Services
π¨ Dashboard
π§ Advanced Use Cases
π οΈ Operations
π§ͺ Testing & Simulation
π Reference
π©βπ» For Developers