Apply PR #144 review fixes: per-field settings fallback, strict validation, hardened AST scan (task 4dd8f870)
P2-1: replace the all-or-nothing from_options try/except in setup with from_options_resilient, which falls back PER FIELD (logging a warning naming the bad field) so a malformed sibling (e.g. morning_summary_time '25:00') cannot silently reset horizon_days/day_rollover_time. P2-2: drop _run_horizon_materialization's legacy horizon_days keyword and branch; default settings to NestQuestSettings(); remove the legacy paragraph. P2-3: _run_horizon_materialization now calls settings.horizon_window(today) so the helper is real and shared; extend tests to run the integration path (_run_horizon_materialization + _register_day_rollover_listener) with horizon_days=3 / day_rollover_time='03:30'. P2-4: harden the AST scan to forbid hass/config_entry names, .hass/.entry/ .config_entry and .config/.options/.data attributes, and getattr/hasattr calls with those string args; add a negative-control test for each shape. P2-5: __post_init__ is strict (rejects None for every field); the None->default mapping lives ONLY in from_options via _option_value. P3: remove dead shims (_day_rollover_hour_minute, _configured_horizon_days) and repoint test_lifecycle at from_options; de-dup the two HH:MM validators into one using a shared TIME_PATTERN in core/const; make horizon_window's today required; reword the notify_target docstring to not claim options-flow parity; document _option_value's None-as-absent semantics; remove unused test helpers.
This commit is contained in:
+17
-12
@@ -526,24 +526,29 @@ async def test_setup_backfills_configured_horizon_days(hass, make_entry) -> None
|
||||
).list_by_date_range(child_id, beyond, beyond_end) == []
|
||||
|
||||
|
||||
def test_configured_horizon_days_validates_and_falls_back() -> None:
|
||||
"""The configured horizon is validated; a malformed value uses the default."""
|
||||
import custom_components.nestquest as nestquest
|
||||
def test_from_options_horizon_validates_and_defaults() -> None:
|
||||
"""from_options returns the configured horizon, defaulting when absent/None.
|
||||
|
||||
assert nestquest._configured_horizon_days({CONF_HORIZON_DAYS: 5}) == 5
|
||||
assert nestquest._configured_horizon_days({}) == DEFAULT_HORIZON_DAYS
|
||||
Repointed from the removed ``_configured_horizon_days`` shim: a valid
|
||||
horizon is read, an absent or None key falls back to the default, and
|
||||
a malformed value RAISES (the integration's ``from_options_resilient``
|
||||
handles the per-field fall-back at setup, not this strict path).
|
||||
"""
|
||||
from custom_components.nestquest.settings import NestQuestSettings
|
||||
|
||||
assert NestQuestSettings.from_options({CONF_HORIZON_DAYS: 5}).horizon_days == 5
|
||||
assert (
|
||||
nestquest._configured_horizon_days({CONF_HORIZON_DAYS: True})
|
||||
== DEFAULT_HORIZON_DAYS
|
||||
NestQuestSettings.from_options({}).horizon_days == DEFAULT_HORIZON_DAYS
|
||||
)
|
||||
assert (
|
||||
nestquest._configured_horizon_days({CONF_HORIZON_DAYS: "5"})
|
||||
== DEFAULT_HORIZON_DAYS
|
||||
)
|
||||
assert (
|
||||
nestquest._configured_horizon_days({CONF_HORIZON_DAYS: 0})
|
||||
NestQuestSettings.from_options(
|
||||
{CONF_HORIZON_DAYS: None}
|
||||
).horizon_days
|
||||
== DEFAULT_HORIZON_DAYS
|
||||
)
|
||||
for bad in (True, "5", 0):
|
||||
with pytest.raises(ValueError):
|
||||
NestQuestSettings.from_options({CONF_HORIZON_DAYS: bad})
|
||||
|
||||
|
||||
async def test_regenerate_service_registered_and_materializes(
|
||||
|
||||
Reference in New Issue
Block a user