chore(quality): manifest keys, ConfigEntryNotReady, remove dead sqlite code
- manifest: add single_config_entry, integration_type "device", loggers ["aioecowitt"]; drop empty homekit/ssdp/zeroconf placeholders. - Q10: raise ConfigEntryNotReady (not PlatformNotReady) when route registration fails in async_setup_entry; drop the now-unused import. - Q11: delete the ~105-line commented-out sqlite3 statistics-migration block in utils.py (would have been blocking I/O in the event loop) and its dead import. Deferred (with reason): quality_scale (needs a rule audit + quality_scale.yaml), device-identifier 2-tuple and suggested_entity_id (entity-naming/identity changes, to land with the planned integration rename), CoordinatorEntity generics in sensor.py (would introduce a circular import - intentionally untyped). Note: the health-probe protocol gate was reverted - the proxy add-on can front WU/WSLink/Ecowitt, so polling must stay unconditional. 308 passing, 100% coverage; ruff clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>ecowitt_support
parent
f4da5fdb27
commit
f6088e86ab
|
|
@ -36,7 +36,7 @@ from py_typecheck import checked, checked_or
|
|||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import ConfigEntryNotReady, PlatformNotReady
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
|
||||
from .const import (
|
||||
|
|
@ -178,7 +178,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: SWSConfigEntry) -> bool:
|
|||
else:
|
||||
if not register_path(hass, coordinator, coordinator_health, entry):
|
||||
_LOGGER.error("Fatal: path not registered!")
|
||||
raise PlatformNotReady
|
||||
raise ConfigEntryNotReady("Webhook routes could not be registered")
|
||||
|
||||
routes = hass.data[DOMAIN].get("routes")
|
||||
if routes is not None:
|
||||
|
|
|
|||
|
|
@ -226,7 +226,11 @@ class HealthCoordinator(DataUpdateCoordinator):
|
|||
)
|
||||
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
"""Refresh add-on health metadata from the WSLink proxy."""
|
||||
"""Refresh add-on health metadata from the WSLink proxy.
|
||||
|
||||
The proxy add-on can front any protocol (WU / WSLink / Ecowitt), so the probe
|
||||
is not gated on a specific protocol option - it always runs.
|
||||
"""
|
||||
session = async_get_clientsession(self.hass, False)
|
||||
url = get_url(self.hass)
|
||||
ip = await async_get_source_ip(self.hass)
|
||||
|
|
|
|||
|
|
@ -9,14 +9,16 @@
|
|||
"http"
|
||||
],
|
||||
"documentation": "https://github.com/schizza/SWS-12500-custom-component",
|
||||
"homekit": {},
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"issue_tracker": "https://github.com/schizza/SWS-12500-custom-component/issues",
|
||||
"loggers": [
|
||||
"aioecowitt"
|
||||
],
|
||||
"requirements": [
|
||||
"typecheck-runtime==0.2.0",
|
||||
"aioecowitt==2025.9.2"
|
||||
],
|
||||
"ssdp": [],
|
||||
"version": "2.0.0-pre1",
|
||||
"zeroconf": []
|
||||
"single_config_entry": true,
|
||||
"version": "2.0.0-pre1"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ from homeassistant.helpers.translation import async_get_translations
|
|||
from .const import (
|
||||
AZIMUT,
|
||||
CONNECTION_GATED_SENSORS,
|
||||
# DATABASE_PATH,
|
||||
DEV_DBG,
|
||||
OUTSIDE_HUMIDITY,
|
||||
OUTSIDE_TEMP,
|
||||
|
|
@ -397,110 +396,3 @@ def battery_5step_to_pct(value: str) -> int | None:
|
|||
return None
|
||||
|
||||
return round(int(value) / 5 * 100)
|
||||
|
||||
|
||||
#
|
||||
# def long_term_units_in_statistics_meta():
|
||||
# """Get units in long term statitstics."""
|
||||
# sensor_units = []
|
||||
# if not Path(DATABASE_PATH).exists():
|
||||
# _LOGGER.error("Database file not found: %s", DATABASE_PATH)
|
||||
# return False
|
||||
#
|
||||
# conn = sqlite3.connect(DATABASE_PATH)
|
||||
# db = conn.cursor()
|
||||
#
|
||||
# try:
|
||||
# db.execute(
|
||||
# """
|
||||
# SELECT statistic_id, unit_of_measurement from statistics_meta
|
||||
# WHERE statistic_id LIKE 'sensor.weather_station_sws%'
|
||||
# """
|
||||
# )
|
||||
# rows = db.fetchall()
|
||||
# sensor_units = {
|
||||
# statistic_id: f"{statistic_id} ({unit})" for statistic_id, unit in rows
|
||||
# }
|
||||
#
|
||||
# except sqlite3.Error as e:
|
||||
# _LOGGER.error("Error during data migration: %s", e)
|
||||
# finally:
|
||||
# conn.close()
|
||||
#
|
||||
# return sensor_units
|
||||
#
|
||||
#
|
||||
# async def migrate_data(hass: HomeAssistant, sensor_id: str | None = None) -> int | bool:
|
||||
# """Migrate data from mm/d to mm."""
|
||||
#
|
||||
# _LOGGER.debug("Sensor %s is required for data migration", sensor_id)
|
||||
# updated_rows = 0
|
||||
#
|
||||
# if not Path(DATABASE_PATH).exists():
|
||||
# _LOGGER.error("Database file not found: %s", DATABASE_PATH)
|
||||
# return False
|
||||
#
|
||||
# conn = sqlite3.connect(DATABASE_PATH)
|
||||
# db = conn.cursor()
|
||||
#
|
||||
# try:
|
||||
# _LOGGER.info(sensor_id)
|
||||
# db.execute(
|
||||
# """
|
||||
# UPDATE statistics_meta
|
||||
# SET unit_of_measurement = 'mm'
|
||||
# WHERE statistic_id = ?
|
||||
# AND unit_of_measurement = 'mm/d';
|
||||
# """,
|
||||
# (sensor_id,),
|
||||
# )
|
||||
# updated_rows = db.rowcount
|
||||
# conn.commit()
|
||||
# _LOGGER.info(
|
||||
# "Data migration completed successfully. Updated rows: %s for %s",
|
||||
# updated_rows,
|
||||
# sensor_id,
|
||||
# )
|
||||
#
|
||||
# except sqlite3.Error as e:
|
||||
# _LOGGER.error("Error during data migration: %s", e)
|
||||
# finally:
|
||||
# conn.close()
|
||||
# return updated_rows
|
||||
#
|
||||
#
|
||||
# def migrate_data_old(sensor_id: str | None = None):
|
||||
# """Migrate data from mm/d to mm."""
|
||||
# updated_rows = 0
|
||||
#
|
||||
# if not Path(DATABASE_PATH).exists():
|
||||
# _LOGGER.error("Database file not found: %s", DATABASE_PATH)
|
||||
# return False
|
||||
#
|
||||
# conn = sqlite3.connect(DATABASE_PATH)
|
||||
# db = conn.cursor()
|
||||
#
|
||||
# try:
|
||||
# _LOGGER.info(sensor_id)
|
||||
# db.execute(
|
||||
# """
|
||||
# UPDATE statistics_meta
|
||||
# SET unit_of_measurement = 'mm'
|
||||
# WHERE statistic_id = ?
|
||||
# AND unit_of_measurement = 'mm/d';
|
||||
# """,
|
||||
# (sensor_id,),
|
||||
# )
|
||||
# updated_rows = db.rowcount
|
||||
# conn.commit()
|
||||
# _LOGGER.info(
|
||||
# "Data migration completed successfully. Updated rows: %s for %s",
|
||||
# updated_rows,
|
||||
# sensor_id,
|
||||
# )
|
||||
#
|
||||
# except sqlite3.Error as e:
|
||||
# _LOGGER.error("Error during data migration: %s", e)
|
||||
# finally:
|
||||
# conn.close()
|
||||
# return updated_rows
|
||||
|
|
|
|||
|
|
@ -199,8 +199,8 @@ async def test_async_setup_entry_creates_runtime_data_and_forwards_platforms(
|
|||
async def test_async_setup_entry_fatal_when_register_path_returns_false(
|
||||
hass_with_http, monkeypatch
|
||||
):
|
||||
"""Cover the fatal branch when `register_path` returns False -> PlatformNotReady."""
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
"""Cover the fatal branch when `register_path` returns False -> ConfigEntryNotReady."""
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
|
|
@ -223,7 +223,7 @@ async def test_async_setup_entry_fatal_when_register_path_returns_false(
|
|||
AsyncMock(return_value=True),
|
||||
)
|
||||
|
||||
with pytest.raises(PlatformNotReady):
|
||||
with pytest.raises(ConfigEntryNotReady):
|
||||
await async_setup_entry(hass_with_http, entry)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue