Skip to content

Commit a4388e4

Browse files
author
Tom Lasswell
committed
chore: Fix CI — lint, mypy, HACS bluetooth dep
- flake8: drop trailing blank lines in state.py; remove unused imports from test_auth.py and test_transport_health.py. - mypy: guard update_interval (DataUpdateCoordinator allows None), type the list[] and service_info/change callback parameters in setup_ble_subscriptions / _handle_ble_advertisement, add type-ignore for bleak_retry_connector's unmarked re-export, and guard self._email / self._password before passing into validate_govee_credentials from the 2FA step. - manifest: add "bluetooth" to after_dependencies — HACS validator was rejecting the manifest for referencing the component without declaring it (soft dep, since BLE is optional). - gitignore: exclude .cc-sessions/, .claude/, sprints/ session artifacts that shouldn't be in the repo. No behavioural changes. Bumps version to 2026.4.7 so users get the first green build since v2026.4.3. 658 tests passing. flake8 clean. mypy clean locally.
1 parent c44f56e commit a4388e4

8 files changed

Lines changed: 23 additions & 14 deletions

File tree

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,9 @@ docs/epic-*.md
155155
docs/legacy-*.md
156156

157157
# GitHub profile README (not part of this project)
158-
profile-README.md
158+
profile-README.md
159+
# Blitz / Claude session artifacts (local tooling, not repo state)
160+
.cc-sessions/
161+
.claude/
162+
sprints/
163+
sprint-registry.json

custom_components/govee/api/ble.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
from typing import TYPE_CHECKING
5252

5353
from bleak import BleakClient
54-
from bleak_retry_connector import (
54+
from bleak_retry_connector import ( # type: ignore[attr-defined]
5555
BleakClientWithServiceCache,
5656
BleakError,
5757
close_stale_connections_by_address,

custom_components/govee/config_flow.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ async def async_step_verification_code(
258258

259259
if user_input is not None:
260260
code = user_input["verification_code"].strip()
261+
if self._email is None or self._password is None:
262+
# Defensive — the verification step should never be reached
263+
# without these already set by the preceding account step.
264+
return self.async_abort(reason="missing_credentials")
261265
try:
262266
self._iot_credentials = await validate_govee_credentials(
263267
self._email,

custom_components/govee/coordinator.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ def unregister_observer(self, observer: IStateObserver) -> None:
390390
# BLE direct transport
391391
# ------------------------------------------------------------------ #
392392

393-
def setup_ble_subscriptions(self) -> list:
393+
def setup_ble_subscriptions(self) -> list[Any]:
394394
"""Subscribe to BLE advertisements for nearby Govee devices.
395395
396396
Called from ``async_setup_entry`` after the coordinator is created.
@@ -403,10 +403,10 @@ def setup_ble_subscriptions(self) -> list:
403403
if not HAS_BLUETOOTH:
404404
return []
405405

406-
unsubs = []
406+
unsubs: list[Any] = []
407407

408408
@callback
409-
def _on_ble_advertisement(service_info, change) -> None:
409+
def _on_ble_advertisement(service_info: Any, change: Any) -> None:
410410
self._handle_ble_advertisement(service_info)
411411

412412
for prefix in _BLE_NAME_PREFIXES:
@@ -439,7 +439,7 @@ def _on_ble_advertisement(service_info, change) -> None:
439439
return unsubs
440440

441441
@callback
442-
def _handle_ble_advertisement(self, service_info) -> None:
442+
def _handle_ble_advertisement(self, service_info: Any) -> None:
443443
"""Correlate a BLE advertisement with a known cloud device.
444444
445445
Matching strategy (see ``docs/_research/2026-04-09_multi-transport-single-entity.md``):
@@ -790,9 +790,12 @@ async def _fetch_device_state(
790790
# the optimistic power/brightness for a short window instead
791791
# of flipflopping the UI. MQTT pushes clear the window early.
792792
grace_cap = OPTIMISTIC_GRACE_CAP_SECONDS
793-
grace_window = min(
794-
2 * self.update_interval.total_seconds(), grace_cap
793+
poll_seconds = (
794+
self.update_interval.total_seconds()
795+
if self.update_interval is not None
796+
else 60.0
795797
)
798+
grace_window = min(2 * poll_seconds, grace_cap)
796799
optimistic_ts = existing_state.last_optimistic_update
797800
in_grace = (
798801
existing_state.source == "optimistic"

custom_components/govee/manifest.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"codeowners": ["@lasswellt"],
1111
"config_flow": true,
1212
"dependencies": [],
13+
"after_dependencies": ["bluetooth"],
1314
"documentation": "https://github.com/lasswellt/govee-homeassistant/blob/master/README.md",
1415
"homekit": {},
1516
"integration_type": "hub",
@@ -23,6 +24,6 @@
2324
"cryptography>=41.0.0"
2425
],
2526
"ssdp": [],
26-
"version": "2026.4.6",
27+
"version": "2026.4.7",
2728
"zeroconf": []
2829
}

custom_components/govee/models/state.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ def update_from_api(self, data: dict[str, Any]) -> None:
214214
except (TypeError, ValueError):
215215
pass
216216

217-
218217
def update_from_mqtt(self, data: dict[str, Any]) -> None:
219218
"""Update state from MQTT push message.
220219

tests/test_auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import json
1818
from contextlib import asynccontextmanager
1919
from typing import Any
20-
from unittest.mock import AsyncMock, MagicMock, patch
20+
from unittest.mock import AsyncMock, MagicMock
2121

2222
import aiohttp
2323
import pytest

tests/test_transport_health.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22

33
from __future__ import annotations
44

5-
import time
65
from datetime import datetime, timedelta, timezone
76
from unittest.mock import MagicMock
87

9-
import pytest
10-
118
from custom_components.govee.coordinator import GoveeCoordinator
129
from custom_components.govee.models import GoveeDeviceState, TransportHealth
1310

0 commit comments

Comments
 (0)