-
-
Notifications
You must be signed in to change notification settings - Fork 207
Add type hints to config controller functions #2639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,7 +5,7 @@ | |||||||
| import base64 | ||||||||
| import logging | ||||||||
| import os | ||||||||
| from typing import TYPE_CHECKING, Any, cast | ||||||||
| from typing import TYPE_CHECKING, Any, TypeVar, cast, overload | ||||||||
| from uuid import uuid4 | ||||||||
|
|
||||||||
| import aiofiles | ||||||||
|
|
@@ -82,6 +82,9 @@ | |||||||
|
|
||||||||
| BASE_KEYS = ("enabled", "name", "available", "default_name", "provider", "type") | ||||||||
|
|
||||||||
| # TypeVar for config value type inference | ||||||||
| _ConfigValueT = TypeVar("_ConfigValueT", bound=ConfigValueType) | ||||||||
|
|
||||||||
| isfile = wrap(os.path.isfile) | ||||||||
| remove = wrap(os.remove) | ||||||||
| rename = wrap(os.rename) | ||||||||
|
|
@@ -229,9 +232,31 @@ async def get_provider_config(self, instance_id: str) -> ProviderConfig: | |||||||
| msg = f"No config found for provider id {instance_id}" | ||||||||
| raise KeyError(msg) | ||||||||
|
|
||||||||
| @overload | ||||||||
| async def get_provider_config_value( | ||||||||
| self, instance_id: str, key: str, *, return_type: type[_ConfigValueT] = ... | ||||||||
| ) -> _ConfigValueT: ... | ||||||||
|
|
||||||||
| @overload | ||||||||
| async def get_provider_config_value( | ||||||||
| self, instance_id: str, key: str, *, return_type: None = ... | ||||||||
| ) -> ConfigValueType: ... | ||||||||
|
|
||||||||
| @api_command("config/providers/get_value") | ||||||||
| async def get_provider_config_value(self, instance_id: str, key: str) -> ConfigValueType: | ||||||||
| """Return single configentry value for a provider.""" | ||||||||
| async def get_provider_config_value( | ||||||||
| self, | ||||||||
| instance_id: str, | ||||||||
| key: str, | ||||||||
| *, | ||||||||
| return_type: type[_ConfigValueT | ConfigValueType] | None = None, | ||||||||
| ) -> _ConfigValueT | ConfigValueType: | ||||||||
| """ | ||||||||
| Return single configentry value for a provider. | ||||||||
|
|
||||||||
| :param instance_id: The provider instance ID. | ||||||||
| :param key: The config key to retrieve. | ||||||||
| :param return_type: Optional type hint for type inference (e.g., str, int, bool). | ||||||||
| """ | ||||||||
| cache_key = f"prov_conf_value_{instance_id}.{key}" | ||||||||
| if (cached_value := self._value_cache.get(cache_key)) is not None: | ||||||||
| return cached_value | ||||||||
|
|
@@ -481,14 +506,40 @@ async def get_player_config_entries( | |||||||
|
|
||||||||
| return await player.get_config_entries(action=action, values=values) | ||||||||
|
|
||||||||
| @overload | ||||||||
| async def get_player_config_value( | ||||||||
| self, | ||||||||
| player_id: str, | ||||||||
| key: str, | ||||||||
| unpack_splitted_values: bool = ..., | ||||||||
| return_type: type[_ConfigValueT] = ..., | ||||||||
| ) -> _ConfigValueT: ... | ||||||||
|
|
||||||||
| @overload | ||||||||
| async def get_player_config_value( | ||||||||
| self, | ||||||||
| player_id: str, | ||||||||
| key: str, | ||||||||
| unpack_splitted_values: bool = ..., | ||||||||
| return_type: None = ..., | ||||||||
| ) -> ConfigValueType | tuple[str, ...] | list[tuple[str, ...]]: ... | ||||||||
|
Comment on lines
+509
to
+525
|
||||||||
|
|
||||||||
| @api_command("config/players/get_value") | ||||||||
| async def get_player_config_value( | ||||||||
| self, | ||||||||
| player_id: str, | ||||||||
| key: str, | ||||||||
| unpack_splitted_values: bool = False, | ||||||||
|
||||||||
| unpack_splitted_values: bool = False, | |
| unpack_splitted_values: bool = False, | |
| *, |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -352,9 +352,8 @@ async def _serve_ugp_stream(self, request: web.Request) -> web.StreamResponse: | |||||
| content_sample_rate=UGP_FORMAT.sample_rate, | ||||||
| content_bit_depth=UGP_FORMAT.bit_depth, | ||||||
| ) | ||||||
| http_profile = cast( | ||||||
| "str", | ||||||
| await self.mass.config.get_player_config_value(child_player_id, CONF_HTTP_PROFILE), | ||||||
| http_profile = await self.mass.config.get_player_config_value( | ||||||
| child_player_id, CONF_HTTP_PROFILE, False, str | ||||||
|
||||||
| child_player_id, CONF_HTTP_PROFILE, False, str | |
| child_player_id, CONF_HTTP_PROFILE, False, return_type=str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The
return_typeparameter is used purely for type inference and doesn't perform runtime type validation. This means if a caller specifiesreturn_type=strbut the actual config value is anint, the type checker will assume it's astrwhile the runtime value will be anint, potentially causing type safety issues.Consider adding a note in the documentation to clarify that
return_typeis for static type checking only and callers are responsible for ensuring the specified type matches the actual config value type. Alternatively, consider adding runtime validation withisinstance()to catch type mismatches early.