Record a timezone-only admin update as an explicit choice (task 45243478) (#277)

Co-authored-by: Joshua <joshua@cnjmail.com>
Co-committed-by: Joshua <joshua@cnjmail.com>
This commit was merged in pull request #277.
This commit is contained in:
2026-09-28 23:43:42 -04:00
committed by approver_agent
parent 40d0e5d8f6
commit 49f40d99b6
2 changed files with 47 additions and 0 deletions
@@ -184,6 +184,11 @@ async def update_settings(
in one atomic upsert; the updated settings are returned. The whole
read → merge → write span runs inside the per-database settings
lock, so concurrent updates queue instead of interleaving.
Supplying ``timezone`` without ``timezone_configured`` records the
zone as the admin's explicit choice (``timezone_configured`` is
persisted ``True`` in the same write); an explicitly supplied
``timezone_configured`` is kept exactly as given.
"""
if not isinstance(changes, Mapping):
raise ValueError(
@@ -199,6 +204,10 @@ async def update_settings(
raise ValueError(
f"unknown settings field(s): {listed}; known fields: {known}"
)
if "timezone" in changes and "timezone_configured" not in changes:
# An admin-supplied zone is an explicit choice, so Home
# Assistant's reported zone must no longer replace it.
changes = {**changes, "timezone_configured": True}
async with _settings_lock(database):
current = await load_settings(database)
return await _write_merged(database, current, changes)
+38
View File
@@ -445,6 +445,44 @@ async def test_admin_chosen_zone_wins_over_reported_zone(
assert stored["timezone_configured"] is True
# --- a timezone-only admin update is an explicit choice (task 45243478) ------
@pytest.mark.parametrize("chosen", ["America/Los_Angeles", ""])
async def test_timezone_only_admin_update_is_an_explicit_choice(
household: SimpleNamespace, chosen: str
) -> None:
"""``PATCH {"timezone": ...}`` alone marks the zone admin-chosen."""
await _adopt_new_york(household)
response = await household.client.patch(
"/api/v1/admin/settings",
json={"timezone": chosen},
headers=_admin_headers(),
)
assert response.status_code == 200
assert response.json()["timezone_configured"] is True
# A conflicting report is no longer adopted.
await _panel_pack_bag(household, "America/Chicago")
stored = await _stored_settings(household)
assert stored["timezone"] == chosen
assert stored["timezone_configured"] is True
async def test_explicit_timezone_configured_false_is_respected(
household: SimpleNamespace,
) -> None:
"""A supplied ``timezone_configured`` is persisted exactly as given."""
response = await household.client.patch(
"/api/v1/admin/settings",
json={"timezone": "America/Chicago", "timezone_configured": False},
headers=_admin_headers(),
)
assert response.status_code == 200
assert response.json()["timezone_configured"] is False
await _panel_pack_bag(household, HOUSEHOLD_ZONE)
assert (await _stored_settings(household))["timezone"] == HOUSEHOLD_ZONE
async def test_invalid_reported_zone_is_ignored(
household: SimpleNamespace,
) -> None: