Chore: Return more detailed exceptions in builtin provider
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Wed, 5 Feb 2025 18:27:03 +0000 (19:27 +0100)
committerMarcel van der Veldt <m.vanderveldt@outlook.com>
Wed, 5 Feb 2025 18:27:03 +0000 (19:27 +0100)
music_assistant/helpers/tags.py
music_assistant/providers/builtin/__init__.py

index e63afbb50f9b2143e97ff417246ba6cba789b980..6ff8ece5d099cde88bfd870cb58a0fa457001aed 100644 (file)
@@ -8,6 +8,7 @@ import logging
 import os
 import subprocess
 from collections.abc import Iterable
+from contextlib import suppress
 from dataclasses import dataclass
 from json import JSONDecodeError
 from typing import Any
@@ -17,6 +18,7 @@ from music_assistant_models.enums import AlbumType
 from music_assistant_models.errors import InvalidDataError
 
 from music_assistant.constants import MASS_LOGGER_NAME, UNKNOWN_ARTIST
+from music_assistant.helpers.json import json_loads
 from music_assistant.helpers.process import AsyncProcess
 from music_assistant.helpers.util import try_parse_int
 
@@ -478,6 +480,13 @@ def parse_tags(input_file: str, file_size: int | None = None) -> AudioTags:
                         break
             del audiofile
         return tags
+    except subprocess.CalledProcessError as err:
+        error_msg = f"Unable to retrieve info for {input_file}"
+        if output := getattr(err, "stdout", None):
+            err_details = json_loads(output)
+            with suppress(KeyError):
+                error_msg = f"{error_msg} ({err_details['error']['string']})"
+        raise InvalidDataError(error_msg) from err
     except (KeyError, ValueError, JSONDecodeError, InvalidDataError) as err:
         msg = f"Unable to retrieve info for {input_file}: {err!s}"
         raise InvalidDataError(msg) from err
index f8b44288345672d74efea38d23e1b35240f07578..d53f9dec4214d167b006310a5bb08e971fc4d3bb 100644 (file)
@@ -312,7 +312,10 @@ class BuiltinProvider(MusicProvider):
         """Retrieve library tracks from the provider."""
         stored_items: list[StoredItem] = self.mass.config.get(CONF_KEY_TRACKS, [])
         for item in stored_items:
-            yield await self.get_track(item["item_id"])
+            try:
+                yield await self.get_track(item["item_id"])
+            except MediaNotFoundError as err:
+                self.logger.warning("Track %s not found: %s", item, err)
 
     async def get_library_playlists(self) -> AsyncGenerator[Playlist, None]:
         """Retrieve library/subscribed playlists from the provider."""
@@ -330,7 +333,10 @@ class BuiltinProvider(MusicProvider):
         """Retrieve library/subscribed radio stations from the provider."""
         stored_items: list[StoredItem] = self.mass.config.get(CONF_KEY_RADIOS, [])
         for item in stored_items:
-            yield await self.get_radio(item["item_id"])
+            try:
+                yield await self.get_radio(item["item_id"])
+            except MediaNotFoundError as err:
+                self.logger.warning("Radio station %s not found: %s", item, err)
 
     async def library_add(self, item: MediaItemType) -> bool:
         """Add item to provider's library. Return true on success."""
@@ -454,10 +460,7 @@ class BuiltinProvider(MusicProvider):
         force_radio: bool = False,
     ) -> Track | Radio:
         """Parse plain URL to MediaItem of type Radio or Track."""
-        try:
-            media_info = await self._get_media_info(url, force_refresh)
-        except Exception as err:
-            raise MediaNotFoundError from err
+        media_info = await self._get_media_info(url, force_refresh)
         is_radio = media_info.get("icyname") or not media_info.duration
         provider_mappings = {
             ProviderMapping(