From: Marcel van der Veldt Date: Mon, 17 Nov 2025 22:25:55 +0000 (+0100) Subject: Add default value argument to get_*_config_value X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=4dbe945834363fdda1969509eae40cfd93fdc384;p=music-assistant-server.git Add default value argument to get_*_config_value --- diff --git a/music_assistant/controllers/config.py b/music_assistant/controllers/config.py index 765d4f62..95248658 100644 --- a/music_assistant/controllers/config.py +++ b/music_assistant/controllers/config.py @@ -234,12 +234,32 @@ class ConfigController: @overload async def get_provider_config_value( - self, instance_id: str, key: str, *, return_type: type[_ConfigValueT] = ... + self, + instance_id: str, + key: str, + *, + default: _ConfigValueT, + return_type: type[_ConfigValueT] = ..., + ) -> _ConfigValueT: ... + + @overload + async def get_provider_config_value( + self, + instance_id: str, + key: str, + *, + default: ConfigValueType = ..., + return_type: type[_ConfigValueT] = ..., ) -> _ConfigValueT: ... @overload async def get_provider_config_value( - self, instance_id: str, key: str, *, return_type: None = ... + self, + instance_id: str, + key: str, + *, + default: ConfigValueType = ..., + return_type: None = ..., ) -> ConfigValueType: ... @api_command("config/providers/get_value") @@ -248,6 +268,7 @@ class ConfigController: instance_id: str, key: str, *, + default: ConfigValueType = None, return_type: type[_ConfigValueT | ConfigValueType] | None = None, ) -> _ConfigValueT | ConfigValueType: """ @@ -255,6 +276,7 @@ class ConfigController: :param instance_id: The provider instance ID. :param key: The config key to retrieve. + :param default: Optional default value to return if key is not found. :param return_type: Optional type hint for type inference (e.g., str, int, bool). Note: This parameter is used purely for static type checking and does not perform runtime type validation. Callers are responsible for ensuring the @@ -264,6 +286,11 @@ class ConfigController: if (cached_value := self._value_cache.get(cache_key)) is not None: return cached_value conf = await self.get_provider_config(instance_id) + if key not in conf.values: + if default is not None: + return default + msg = f"Config key {key} not found for provider {instance_id}" + raise KeyError(msg) val = ( conf.values[key].value if conf.values[key].value is not None @@ -516,6 +543,7 @@ class ConfigController: key: str, unpack_splitted_values: Literal[True], *, + default: ConfigValueType = ..., return_type: type[_ConfigValueT] | None = ..., ) -> tuple[str, ...] | list[tuple[str, ...]]: ... @@ -526,6 +554,7 @@ class ConfigController: key: str, unpack_splitted_values: Literal[False] = False, *, + default: _ConfigValueT, return_type: type[_ConfigValueT] = ..., ) -> _ConfigValueT: ... @@ -536,6 +565,18 @@ class ConfigController: key: str, unpack_splitted_values: Literal[False] = False, *, + default: ConfigValueType = ..., + return_type: type[_ConfigValueT] = ..., + ) -> _ConfigValueT: ... + + @overload + async def get_player_config_value( + self, + player_id: str, + key: str, + unpack_splitted_values: Literal[False] = False, + *, + default: ConfigValueType = ..., return_type: None = ..., ) -> ConfigValueType: ... @@ -545,6 +586,8 @@ class ConfigController: player_id: str, key: str, unpack_splitted_values: bool = False, + *, + default: ConfigValueType = None, return_type: type[_ConfigValueT | ConfigValueType] | None = None, ) -> _ConfigValueT | ConfigValueType | tuple[str, ...] | list[tuple[str, ...]]: """ @@ -553,12 +596,18 @@ class ConfigController: :param player_id: The player ID. :param key: The config key to retrieve. :param unpack_splitted_values: Whether to unpack multi-value config entries. + :param default: Optional default value to return if key is not found. :param return_type: Optional type hint for type inference (e.g., str, int, bool). Note: This parameter is used purely for static type checking and does not perform runtime type validation. Callers are responsible for ensuring the specified type matches the actual config value type. """ conf = await self.get_player_config(player_id) + if key not in conf.values: + if default is not None: + return default + msg = f"Config key {key} not found for player {player_id}" + raise KeyError(msg) if unpack_splitted_values: return conf.values[key].get_splitted_values() return ( @@ -890,12 +939,32 @@ class ConfigController: @overload async def get_core_config_value( - self, domain: str, key: str, *, return_type: type[_ConfigValueT] = ... + self, + domain: str, + key: str, + *, + default: _ConfigValueT, + return_type: type[_ConfigValueT] = ..., ) -> _ConfigValueT: ... @overload async def get_core_config_value( - self, domain: str, key: str, *, return_type: None = ... + self, + domain: str, + key: str, + *, + default: ConfigValueType = ..., + return_type: type[_ConfigValueT] = ..., + ) -> _ConfigValueT: ... + + @overload + async def get_core_config_value( + self, + domain: str, + key: str, + *, + default: ConfigValueType = ..., + return_type: None = ..., ) -> ConfigValueType: ... @api_command("config/core/get_value") @@ -904,6 +973,7 @@ class ConfigController: domain: str, key: str, *, + default: ConfigValueType = None, return_type: type[_ConfigValueT | ConfigValueType] | None = None, ) -> _ConfigValueT | ConfigValueType: """ @@ -911,12 +981,18 @@ class ConfigController: :param domain: The core controller domain. :param key: The config key to retrieve. + :param default: Optional default value to return if key is not found. :param return_type: Optional type hint for type inference (e.g., str, int, bool). Note: This parameter is used purely for static type checking and does not perform runtime type validation. Callers are responsible for ensuring the specified type matches the actual config value type. """ conf = await self.get_core_config(domain) + if key not in conf.values: + if default is not None: + return default + msg = f"Config key {key} not found for core controller {domain}" + raise KeyError(msg) return ( conf.values[key].value if conf.values[key].value is not None diff --git a/music_assistant/helpers/api_docs.py b/music_assistant/helpers/api_docs.py index 1e561b1a..ba5dc6b2 100644 --- a/music_assistant/helpers/api_docs.py +++ b/music_assistant/helpers/api_docs.py @@ -428,6 +428,9 @@ def generate_openapi_spec( for param_name in handler.signature.parameters: if param_name == "self": continue + # Skip return_type parameter (used only for type hints) + if param_name == "return_type": + continue param_type = handler.type_hints.get(param_name, Any) # Skip Any types as they don't provide useful schema information if param_type is not Any and str(param_type) != "typing.Any": @@ -1186,6 +1189,9 @@ def generate_commands_reference( # noqa: PLR0915 for param_name, param in handler.signature.parameters.items(): if param_name == "self": continue + # Skip return_type parameter (used only for type hints) + if param_name == "return_type": + continue is_required = param.default is inspect.Parameter.empty param_type = handler.type_hints.get(param_name, Any) type_str = str(param_type) @@ -1495,6 +1501,9 @@ def generate_schemas_reference( # noqa: PLR0915 for param_name in handler.signature.parameters: if param_name == "self": continue + # Skip return_type parameter (used only for type hints) + if param_name == "return_type": + continue param_type = handler.type_hints.get(param_name, Any) if param_type is not Any and str(param_type) != "typing.Any": _get_type_schema(param_type, schemas) @@ -2317,6 +2326,9 @@ def generate_html_docs( # noqa: PLR0915 for param_name, param in handler.signature.parameters.items(): if param_name == "self": continue + # Skip return_type parameter (used only for type hints) + if param_name == "return_type": + continue param_type = handler.type_hints.get(param_name, Any) is_required = param.default is inspect.Parameter.empty diff --git a/music_assistant/providers/airplay/protocols/airplay2.py b/music_assistant/providers/airplay/protocols/airplay2.py index a55a9e49..fe3f5df2 100644 --- a/music_assistant/providers/airplay/protocols/airplay2.py +++ b/music_assistant/providers/airplay/protocols/airplay2.py @@ -60,7 +60,7 @@ class AirPlay2Stream(AirPlayProtocol): sync_adjust = self.mass.config.get_raw_player_config_value(player_id, CONF_SYNC_ADJUST, 0) assert isinstance(sync_adjust, int) read_ahead = await self.mass.config.get_player_config_value( - player_id, CONF_READ_AHEAD_BUFFER + player_id, CONF_READ_AHEAD_BUFFER, return_type=int ) txt_kv: str = ""