Make release channel a hardcoded enum rather than a free form string (#115595)

* Make release channel a hardcoded enum rather than a free form string

* Update enum comparison to remove equality and us identity comparison

* Fix comparison condition to match the previous implementation

* Update tests to use Enum instead of string
This commit is contained in:
Alberto Montes 2024-04-20 20:01:49 +02:00 committed by GitHub
parent c753093741
commit c94b0a82ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 50 additions and 29 deletions

View File

@ -36,7 +36,6 @@ from typing import (
TYPE_CHECKING, TYPE_CHECKING,
Any, Any,
Generic, Generic,
Literal,
NotRequired, NotRequired,
ParamSpec, ParamSpec,
Self, Self,
@ -279,17 +278,24 @@ def async_get_hass() -> HomeAssistant:
return _hass.hass return _hass.hass
class ReleaseChannel(enum.StrEnum):
BETA = "beta"
DEV = "dev"
NIGHTLY = "nightly"
STABLE = "stable"
@callback @callback
def get_release_channel() -> Literal["beta", "dev", "nightly", "stable"]: def get_release_channel() -> ReleaseChannel:
"""Find release channel based on version number.""" """Find release channel based on version number."""
version = __version__ version = __version__
if "dev0" in version: if "dev0" in version:
return "dev" return ReleaseChannel.DEV
if "dev" in version: if "dev" in version:
return "nightly" return ReleaseChannel.NIGHTLY
if "b" in version: if "b" in version:
return "beta" return ReleaseChannel.BETA
return "stable" return ReleaseChannel.STABLE
@enum.unique @enum.unique

View File

@ -13,7 +13,13 @@ import attr
from yarl import URL from yarl import URL
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import Event, HomeAssistant, callback, get_release_channel from homeassistant.core import (
Event,
HomeAssistant,
ReleaseChannel,
callback,
get_release_channel,
)
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.loader import async_suggest_report_issue from homeassistant.loader import async_suggest_report_issue
from homeassistant.util.event_type import EventType from homeassistant.util.event_type import EventType
@ -608,7 +614,7 @@ class DeviceRegistry(BaseRegistry[dict[str, list[dict[str, Any]]]]):
try: try:
return name.format(**translation_placeholders) return name.format(**translation_placeholders)
except KeyError as err: except KeyError as err:
if get_release_channel() != "stable": if get_release_channel() is not ReleaseChannel.STABLE:
raise HomeAssistantError("Missing placeholder %s" % err) from err raise HomeAssistantError("Missing placeholder %s" % err) from err
report_issue = async_suggest_report_issue( report_issue = async_suggest_report_issue(
self.hass, integration_domain=domain self.hass, integration_domain=domain
@ -963,12 +969,16 @@ class DeviceRegistry(BaseRegistry[dict[str, list[dict[str, Any]]]]):
tuple(conn) # type: ignore[misc] tuple(conn) # type: ignore[misc]
for conn in device["connections"] for conn in device["connections"]
}, },
disabled_by=DeviceEntryDisabler(device["disabled_by"]) disabled_by=(
if device["disabled_by"] DeviceEntryDisabler(device["disabled_by"])
else None, if device["disabled_by"]
entry_type=DeviceEntryType(device["entry_type"]) else None
if device["entry_type"] ),
else None, entry_type=(
DeviceEntryType(device["entry_type"])
if device["entry_type"]
else None
),
hw_version=device["hw_version"], hw_version=device["hw_version"],
id=device["id"], id=device["id"],
identifiers={ identifiers={

View File

@ -52,6 +52,7 @@ from homeassistant.core import (
Event, Event,
HassJobType, HassJobType,
HomeAssistant, HomeAssistant,
ReleaseChannel,
callback, callback,
get_hassjob_callable_job_type, get_hassjob_callable_job_type,
get_release_channel, get_release_channel,
@ -657,7 +658,7 @@ class Entity(
return name.format(**self.translation_placeholders) return name.format(**self.translation_placeholders)
except KeyError as err: except KeyError as err:
if not self._name_translation_placeholders_reported: if not self._name_translation_placeholders_reported:
if get_release_channel() != "stable": if get_release_channel() is not ReleaseChannel.STABLE:
raise HomeAssistantError("Missing placeholder %s" % err) from err raise HomeAssistantError("Missing placeholder %s" % err) from err
report_issue = self._suggest_report_issue() report_issue = self._suggest_report_issue()
_LOGGER.warning( _LOGGER.warning(

View File

@ -11,7 +11,7 @@ from yarl import URL
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import CoreState, HomeAssistant from homeassistant.core import CoreState, HomeAssistant, ReleaseChannel
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import ( from homeassistant.helpers import (
area_registry as ar, area_registry as ar,
@ -2390,7 +2390,7 @@ async def test_device_name_translation_placeholders(
}, },
}, },
{"placeholder": "special"}, {"placeholder": "special"},
"stable", ReleaseChannel.STABLE,
nullcontext(), nullcontext(),
( (
"has translation placeholders '{'placeholder': 'special'}' which do " "has translation placeholders '{'placeholder': 'special'}' which do "
@ -2405,7 +2405,7 @@ async def test_device_name_translation_placeholders(
}, },
}, },
{"placeholder": "special"}, {"placeholder": "special"},
"beta", ReleaseChannel.BETA,
pytest.raises( pytest.raises(
HomeAssistantError, match="Missing placeholder '2ndplaceholder'" HomeAssistantError, match="Missing placeholder '2ndplaceholder'"
), ),
@ -2419,7 +2419,7 @@ async def test_device_name_translation_placeholders(
}, },
}, },
None, None,
"stable", ReleaseChannel.STABLE,
nullcontext(), nullcontext(),
( (
"has translation placeholders '{}' which do " "has translation placeholders '{}' which do "
@ -2434,7 +2434,7 @@ async def test_device_name_translation_placeholders_errors(
translation_key: str | None, translation_key: str | None,
translations: dict[str, str] | None, translations: dict[str, str] | None,
placeholders: dict[str, str] | None, placeholders: dict[str, str] | None,
release_channel: str, release_channel: ReleaseChannel,
expectation: AbstractContextManager, expectation: AbstractContextManager,
expected_error: str, expected_error: str,
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,

View File

@ -28,6 +28,7 @@ from homeassistant.core import (
HassJobType, HassJobType,
HomeAssistant, HomeAssistant,
HomeAssistantError, HomeAssistantError,
ReleaseChannel,
callback, callback,
) )
from homeassistant.helpers import device_registry as dr, entity, entity_registry as er from homeassistant.helpers import device_registry as dr, entity, entity_registry as er
@ -1249,7 +1250,7 @@ async def test_entity_name_translation_placeholders(
}, },
}, },
{"placeholder": "special"}, {"placeholder": "special"},
"stable", ReleaseChannel.STABLE,
( (
"has translation placeholders '{'placeholder': 'special'}' which do " "has translation placeholders '{'placeholder': 'special'}' which do "
"not match the name '{placeholder} English ent {2ndplaceholder}'" "not match the name '{placeholder} English ent {2ndplaceholder}'"
@ -1263,7 +1264,7 @@ async def test_entity_name_translation_placeholders(
}, },
}, },
{"placeholder": "special"}, {"placeholder": "special"},
"beta", ReleaseChannel.BETA,
"HomeAssistantError: Missing placeholder '2ndplaceholder'", "HomeAssistantError: Missing placeholder '2ndplaceholder'",
), ),
( (
@ -1274,7 +1275,7 @@ async def test_entity_name_translation_placeholders(
}, },
}, },
None, None,
"stable", ReleaseChannel.STABLE,
( (
"has translation placeholders '{}' which do " "has translation placeholders '{}' which do "
"not match the name '{placeholder} English ent'" "not match the name '{placeholder} English ent'"
@ -1287,7 +1288,7 @@ async def test_entity_name_translation_placeholder_errors(
translation_key: str | None, translation_key: str | None,
translations: dict[str, str] | None, translations: dict[str, str] | None,
placeholders: dict[str, str] | None, placeholders: dict[str, str] | None,
release_channel: str, release_channel: ReleaseChannel,
expected_error: str, expected_error: str,
caplog: pytest.LogCaptureFixture, caplog: pytest.LogCaptureFixture,
) -> None: ) -> None:

View File

@ -42,6 +42,7 @@ from homeassistant.core import (
CoreState, CoreState,
HassJob, HassJob,
HomeAssistant, HomeAssistant,
ReleaseChannel,
ServiceCall, ServiceCall,
ServiceResponse, ServiceResponse,
State, State,
@ -3060,13 +3061,15 @@ async def test_validate_state(hass: HomeAssistant) -> None:
@pytest.mark.parametrize( @pytest.mark.parametrize(
("version", "release_channel"), ("version", "release_channel"),
[ [
("0.115.0.dev20200815", "nightly"), ("0.115.0.dev20200815", ReleaseChannel.NIGHTLY),
("0.115.0", "stable"), ("0.115.0", ReleaseChannel.STABLE),
("0.115.0b4", "beta"), ("0.115.0b4", ReleaseChannel.BETA),
("0.115.0dev0", "dev"), ("0.115.0dev0", ReleaseChannel.DEV),
], ],
) )
async def test_get_release_channel(version: str, release_channel: str) -> None: async def test_get_release_channel(
version: str, release_channel: ReleaseChannel
) -> None:
"""Test if release channel detection works from Home Assistant version number.""" """Test if release channel detection works from Home Assistant version number."""
with patch("homeassistant.core.__version__", f"{version}"): with patch("homeassistant.core.__version__", f"{version}"):
assert get_release_channel() == release_channel assert get_release_channel() == release_channel