---
comments: false
---

# Coding Guidelines

> **Note:** For complete coding standards, see [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.28.0/AGENTS.md).

## Code Style

- **Formatter/Linter**: Ruff (replaces Black, Flake8, isort)
- **Max line length**: 120 characters
- **Max complexity**: 25 (McCabe)
- **Target**: Python 3.13

Run before committing:

```bash
./scripts/lint        # Auto-fix issues
./scripts/release/hassfest    # Validate integration structure
```

## Naming Conventions

### Class Names

**All public classes MUST use the integration name as prefix.**

This is a Home Assistant standard to avoid naming conflicts between integrations.

```python
# ✅ CORRECT
class TibberPricesApiClient:
class TibberPricesDataUpdateCoordinator:
class TibberPricesSensor:

# ❌ WRONG - Missing prefix
class ApiClient:
class DataFetcher:
class TimeService:
```

**When prefix is required:**

- Public classes used across multiple modules
- All exception classes
- All coordinator and entity classes
- Data classes (dataclasses, NamedTuples) used as public APIs

**When prefix can be omitted:**

- Private helper classes within a single module (prefix with `_` underscore)
- Type aliases and callbacks (e.g., `TimeServiceCallback`)
- Small internal NamedTuples for function returns

**Private Classes:**

If a helper class is ONLY used within a single module file, prefix it with underscore:

```python
# ✅ Private class - used only in this file
class _InternalHelper:
    """Helper used only within this module."""
    pass

# ❌ Wrong - no prefix but used across modules
class DataFetcher:  # Should be TibberPricesDataFetcher
    pass
```

**Note:** Currently (Nov 2025), this project has **NO private classes** - all classes are used across module boundaries.

**Current Technical Debt:**

Many existing classes lack the `TibberPrices` prefix. Before refactoring:

1. Document the plan in `/planning/class-naming-refactoring.md`
2. Use `multi_replace_string_in_file` for bulk renames
3. Test thoroughly after each module

See [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.28.0/AGENTS.md) for complete list of classes needing rename.

## Import Order

1. Python stdlib (specific types only)
2. Third-party (`homeassistant.*`, `aiohttp`)
3. Local (`.api`, `.const`)

## Critical Patterns

### Time Handling

Always use `dt_util` from `homeassistant.util`:

```python
from homeassistant.util import dt as dt_util

price_time = dt_util.parse_datetime(starts_at)
price_time = dt_util.as_local(price_time)  # Convert to HA timezone
now = dt_util.now()
```

### Translation Loading

```python
# In __init__.py async_setup_entry:
await async_load_translations(hass, "en")
await async_load_standard_translations(hass, "en")
```

### Price Data Enrichment

Always enrich raw API data:

```python
from .price_utils import enrich_price_info_with_differences

enriched = enrich_price_info_with_differences(
    price_info_data,
    thresholds,
)
```

See [`AGENTS.md`](https://github.com/jpawlowski/hass.tibber_prices/blob/v0.28.0/AGENTS.md) for complete guidelines.
