Skip to content

Commit

Permalink
Make all models initializable by kwargs only (#816)
Browse files Browse the repository at this point in the history
* Make all models initializable by kwargs only

* adjust existing code

* more adjustments

* MediaItemChapter

* ItemMapping

* PagedItems

* adjust log

* adjust log
  • Loading branch information
marcelveldt authored Aug 2, 2023
1 parent e5576a7 commit 3df3f13
Show file tree
Hide file tree
Showing 17 changed files with 116 additions and 69 deletions.
20 changes: 10 additions & 10 deletions music_assistant/common/models/media_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
MetadataTypes = int | bool | str | list[str]


@dataclass
@dataclass(kw_only=True)
class AudioFormat(DataClassDictMixin):
"""Model for AudioFormat details."""

Expand Down Expand Up @@ -54,7 +54,7 @@ def pcm_sample_size(self) -> int:
return int(self.sample_rate * (self.bit_depth / 8) * self.channels)


@dataclass(frozen=True)
@dataclass(frozen=True, kw_only=True)
class ProviderMapping(DataClassDictMixin):
"""Model for a MediaItem's provider mapping details."""

Expand Down Expand Up @@ -89,7 +89,7 @@ def __eq__(self, other: ProviderMapping) -> bool:
return self.provider_instance == other.provider_instance and self.item_id == other.item_id


@dataclass(frozen=True)
@dataclass(frozen=True, kw_only=True)
class MediaItemLink(DataClassDictMixin):
"""Model for a link."""

Expand All @@ -105,7 +105,7 @@ def __eq__(self, other: MediaItemLink) -> bool:
return self.url == other.url


@dataclass(frozen=True)
@dataclass(frozen=True, kw_only=True)
class MediaItemImage(DataClassDictMixin):
"""Model for a image."""

Expand All @@ -124,7 +124,7 @@ def __eq__(self, other: MediaItemImage) -> bool:
return self.__hash__() == other.__hash__()


@dataclass(frozen=True)
@dataclass(frozen=True, kw_only=True)
class MediaItemChapter(DataClassDictMixin):
"""Model for a chapter."""

Expand All @@ -142,7 +142,7 @@ def __eq__(self, other: MediaItemChapter) -> bool:
return self.chapter_id == other.chapter_id


@dataclass
@dataclass(kw_only=True)
class MediaItemMetadata(DataClassDictMixin):
"""Model for a MediaItem's metadata."""

Expand Down Expand Up @@ -247,7 +247,7 @@ def __eq__(self, other: ItemMapping) -> bool:
return self.uri == other.uri


@dataclass
@dataclass(kw_only=True)
class ItemMapping(DataClassDictMixin):
"""Representation of a minimized item object."""

Expand Down Expand Up @@ -395,7 +395,7 @@ def __post_init__(self):
MediaItemType = Artist | Album | Track | Radio | Playlist | BrowseFolder


@dataclass
@dataclass(kw_only=True)
class PagedItems(DataClassDictMixin):
"""Model for a paged listing."""

Expand All @@ -417,7 +417,7 @@ def parse(cls, raw: dict[str, Any], item_type: type) -> PagedItems:
)


@dataclass
@dataclass(kw_only=True)
class SearchResults(DataClassDictMixin):
"""Model for results from a search query."""

Expand All @@ -443,7 +443,7 @@ def media_from_dict(media_item: dict) -> MediaItemType:
return MediaItem.from_dict(media_item)


@dataclass
@dataclass(kw_only=True)
class StreamDetails(DataClassDictMixin):
"""Model for streamdetails."""

Expand Down
2 changes: 1 addition & 1 deletion music_assistant/server/controllers/media/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ async def library_items(
total = offset + count
else:
total = await self.mass.music.database.get_count_from_query(sql_query, params)
return PagedItems(items, count, limit, offset, total)
return PagedItems(items=items, count=count, limit=limit, offset=offset, total=total)

async def iter_library_items(
self,
Expand Down
4 changes: 3 additions & 1 deletion music_assistant/server/controllers/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ async def get_playlist_metadata(self, playlist: Playlist) -> None:
img_data = await create_collage(self.mass, list(images))
async with aiofiles.open(img_path, "wb") as _file:
await _file.write(img_data)
playlist.metadata.images = [MediaItemImage(ImageType.THUMB, img_path, "file")]
playlist.metadata.images = [
MediaItemImage(type=ImageType.THUMB, path=img_path, provider="file")
]
except Exception as err:
LOGGER.debug("Error while creating playlist image", exc_info=err)
# set timestamp, used to determine when this function was last called
Expand Down
4 changes: 3 additions & 1 deletion music_assistant/server/models/music_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,9 @@ async def sync_library(self, media_types: tuple[MediaType, ...]) -> None:
)
cur_db_ids.add(library_item.item_id)
except MusicAssistantError as err:
self.logger.warning("Skipping sync of item %s: %s", prov_item.uri, str(err))
self.logger.warning(
"Skipping sync of item %s - error details: %s", prov_item.uri, str(err)
)

# process deletions (= no longer in library)
cache_key = f"library_items.{media_type}.{self.instance_id}"
Expand Down
16 changes: 8 additions & 8 deletions music_assistant/server/providers/deezer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,17 +546,17 @@ def parse_track(
duration=track.duration,
artists=[
ItemMapping(
MediaType.ARTIST,
str(track.artist.id),
self.instance_id,
track.artist.name,
media_type=MediaType.ARTIST,
item_id=str(track.artist.id),
provider=self.domain,
name=track.artist.name,
)
],
album=ItemMapping(
MediaType.ALBUM,
str(track.album.id),
self.instance_id,
track.album.title,
media_type=MediaType.ALBUM,
item_id=str(track.album.id),
provider=self.domain,
name=track.album.title,
),
provider_mappings={
ProviderMapping(
Expand Down
4 changes: 2 additions & 2 deletions music_assistant/server/providers/fanarttv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async def get_artist_metadata(self, artist: Artist) -> MediaItemMetadata | None:
if not items:
continue
for item in items:
metadata.images.append(MediaItemImage(img_type, item["url"]))
metadata.images.append(MediaItemImage(type=img_type, path=item["url"]))
return metadata
return None

Expand All @@ -110,7 +110,7 @@ async def get_album_metadata(self, album: Album) -> MediaItemMetadata | None:
if not items:
continue
for item in items:
metadata.images.append(MediaItemImage(img_type, item["url"]))
metadata.images.append(MediaItemImage(type=img_type, path=item["url"]))
return metadata
return None

Expand Down
25 changes: 20 additions & 5 deletions music_assistant/server/providers/filesystem_local/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ async def _parse_track(
# much space and bandwidth. Instead we set the filename as value so the image can
# be retrieved later in realtime.
track.metadata.images = [
MediaItemImage(ImageType.THUMB, file_item.path, self.instance_id)
MediaItemImage(type=ImageType.THUMB, url=file_item.path, provider=self.instance_id)
]

if track.album and not track.album.metadata.images:
Expand Down Expand Up @@ -819,7 +819,12 @@ async def _parse_artist(
provider=self.instance_id,
name=name,
provider_mappings={
ProviderMapping(artist_path, self.instance_id, self.instance_id, url=artist_path)
ProviderMapping(
item_id=artist_path,
provider_domain=self.domain,
provider_instance=self.instance_id,
url=artist_path,
)
},
mbid=VARIOUS_ARTISTS_ID_MBID if compare_strings(name, VARIOUS_ARTISTS_NAME) else None,
)
Expand Down Expand Up @@ -876,7 +881,11 @@ async def _parse_album(
artists=artists,
provider_mappings={
ProviderMapping(
album_path, self.instance_id, self.instance_id, url=album_path, barcode=barcode
item_id=album_path,
provider_domain=self.instance_id,
provider_instance=self.instance_id,
url=album_path,
barcode=barcode,
)
},
)
Expand Down Expand Up @@ -933,12 +942,18 @@ async def _get_local_images(self, folder: str) -> list[MediaItemImage]:
if item.ext != ext:
continue
try:
images.append(MediaItemImage(ImageType(item.name), item.path, self.instance_id))
images.append(
MediaItemImage(
type=ImageType(item.name), path=item.path, provider=self.instance_id
)
)
except ValueError:
for filename in ("folder", "cover", "albumart", "artist"):
if item.name.lower().startswith(filename):
images.append(
MediaItemImage(ImageType.THUMB, item.path, self.instance_id)
MediaItemImage(
type=ImageType.THUMB, path=item.path, provider=self.instance_id
)
)
break
return images
33 changes: 23 additions & 10 deletions music_assistant/server/providers/plex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ async def _get_data(self, key, cls=None):

def _get_item_mapping(self, media_type: MediaType, key: str, name: str) -> ItemMapping:
return ItemMapping(
media_type,
key,
self.instance_id,
name,
media_type=media_type,
item_id=key,
provider=self.instance_id,
name=name,
)

async def _get_or_create_artist_by_name(self, artist_name) -> Artist:
Expand Down Expand Up @@ -318,12 +318,16 @@ async def _parse_album(self, plex_album: PlexAlbum) -> Album:
if plex_album.year:
album.year = plex_album.year
if thumb := plex_album.firstAttr("thumb", "parentThumb", "grandparentThumb"):
album.metadata.images = [MediaItemImage(ImageType.THUMB, thumb, self.instance_id)]
album.metadata.images = [
MediaItemImage(type=ImageType.THUMB, url=thumb, provider=self.instance_id)
]
if plex_album.summary:
album.metadata.description = plex_album.summary

album.artists.append(
self._get_item_mapping(MediaType.ARTIST, plex_album.parentKey, plex_album.parentTitle)
self._get_item_mapping(
type=MediaType.ARTIST, url=plex_album.parentKey, provider=plex_album.parentTitle
)
)
return album

Expand All @@ -348,7 +352,9 @@ async def _parse_artist(self, plex_artist: PlexArtist) -> Artist:
if plex_artist.summary:
artist.metadata.description = plex_artist.summary
if thumb := plex_artist.firstAttr("thumb", "parentThumb", "grandparentThumb"):
artist.metadata.images = [MediaItemImage(ImageType.THUMB, thumb, self.instance_id)]
artist.metadata.images = [
MediaItemImage(type=ImageType.THUMB, path=thumb, url=self.instance_id)
]
return artist

async def _parse_playlist(self, plex_playlist: PlexPlaylist) -> Playlist:
Expand All @@ -369,7 +375,9 @@ async def _parse_playlist(self, plex_playlist: PlexPlaylist) -> Playlist:
if plex_playlist.summary:
playlist.metadata.description = plex_playlist.summary
if thumb := plex_playlist.firstAttr("thumb", "parentThumb", "grandparentThumb"):
playlist.metadata.images = [MediaItemImage(ImageType.THUMB, thumb, self.instance_id)]
playlist.metadata.images = [
MediaItemImage(type=ImageType.THUMB, url=thumb, provider=self.instance_id)
]
playlist.is_editable = True
return playlist

Expand Down Expand Up @@ -429,7 +437,9 @@ async def _parse_track(
raise InvalidDataError("No artist was found for track")

if thumb := plex_track.firstAttr("thumb", "parentThumb", "grandparentThumb"):
track.metadata.images = [MediaItemImage(ImageType.THUMB, thumb, self.instance_id)]
track.metadata.images = [
MediaItemImage(type=ImageType.THUMB, url=thumb, provider=self.instance_id)
]
if plex_track.parentKey:
track.album = self._get_item_mapping(
MediaType.ALBUM, plex_track.parentKey, plex_track.parentKey
Expand All @@ -439,7 +449,10 @@ async def _parse_track(
if plex_track.chapters:
track.metadata.chapters = [
MediaItemChapter(
plex_chapter.id, plex_chapter.start, plex_chapter.end, plex_chapter.title
chapter_id=plex_chapter.id,
position_start=plex_chapter.start,
position_end=plex_chapter.end,
title=plex_chapter.title,
)
for plex_chapter in plex_track.chapters
]
Expand Down
8 changes: 4 additions & 4 deletions music_assistant/server/providers/qobuz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ async def _parse_artist(self, artist_obj: dict):
artist.mbid = VARIOUS_ARTISTS_ID_MBID
artist.name = VARIOUS_ARTISTS_NAME
if img := self.__get_image(artist_obj):
artist.metadata.images = [MediaItemImage(ImageType.THUMB, img)]
artist.metadata.images = [MediaItemImage(type=ImageType.THUMB, path=img)]
if artist_obj.get("biography"):
artist.metadata.description = artist_obj["biography"].get("content")
return artist
Expand Down Expand Up @@ -504,7 +504,7 @@ async def _parse_album(self, album_obj: dict, artist_obj: dict = None):
if "genre" in album_obj:
album.metadata.genres = {album_obj["genre"]["name"]}
if img := self.__get_image(album_obj):
album.metadata.images = [MediaItemImage(ImageType.THUMB, img)]
album.metadata.images = [MediaItemImage(type=ImageType.THUMB, path=img)]
if "label" in album_obj:
album.metadata.label = album_obj["label"]["name"]
if (released_at := album_obj.get("released_at")) and released_at != 0:
Expand Down Expand Up @@ -592,7 +592,7 @@ async def _parse_track(self, track_obj: dict) -> Track | AlbumTrack | PlaylistTr
if track_obj.get("parental_warning"):
track.metadata.explicit = True
if img := self.__get_image(track_obj):
track.metadata.images = [MediaItemImage(ImageType.THUMB, img)]
track.metadata.images = [MediaItemImage(type=ImageType.THUMB, path=img)]

return track

Expand All @@ -619,7 +619,7 @@ async def _parse_playlist(self, playlist_obj):
or playlist_obj["is_collaborative"]
)
if img := self.__get_image(playlist_obj):
playlist.metadata.images = [MediaItemImage(ImageType.THUMB, img)]
playlist.metadata.images = [MediaItemImage(type=ImageType.THUMB, path=img)]
playlist.metadata.checksum = str(playlist_obj["updated_at"])
return playlist

Expand Down
8 changes: 5 additions & 3 deletions music_assistant/server/providers/radiobrowser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ async def browse(self, path: str) -> BrowseFolder:
name="",
label=country.name,
)
folder.metadata.images = [MediaItemImage(ImageType.THUMB, country.favicon)]
folder.metadata.images = [
MediaItemImage(type=ImageType.THUMB, path=country.favicon)
]
sub_items.append(folder)
return BrowseFolder(
item_id="country",
Expand Down Expand Up @@ -313,8 +315,8 @@ async def _parse_radio(self, radio_obj: dict) -> Radio:
)
radio.metadata.label = radio_obj.tags
radio.metadata.popularity = radio_obj.votes
radio.metadata.links = [MediaItemLink(LinkType.WEBSITE, radio_obj.homepage)]
radio.metadata.images = [MediaItemImage(ImageType.THUMB, radio_obj.favicon)]
radio.metadata.links = [MediaItemLink(type=LinkType.WEBSITE, url=radio_obj.homepage)]
radio.metadata.images = [MediaItemImage(type=ImageType.THUMB, path=radio_obj.favicon)]

return radio

Expand Down
8 changes: 5 additions & 3 deletions music_assistant/server/providers/soundcloud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ async def _parse_artist(self, artist_obj: dict) -> Artist:
artist.metadata.description = artist_obj["description"]
if artist_obj.get("avatar_url"):
img_url = artist_obj["avatar_url"]
artist.metadata.images = [MediaItemImage(ImageType.THUMB, img_url)]
artist.metadata.images = [MediaItemImage(type=ImageType.THUMB, path=img_url)]
return artist

async def _parse_playlist(self, playlist_obj: dict) -> Playlist:
Expand All @@ -340,7 +340,7 @@ async def _parse_playlist(self, playlist_obj: dict) -> Playlist:
playlist.metadata.description = playlist_obj["description"]
if playlist_obj.get("artwork_url"):
playlist.metadata.images = [
MediaItemImage(ImageType.THUMB, playlist_obj["artwork_url"])
MediaItemImage(type=ImageType.THUMB, path=playlist_obj["artwork_url"])
]
if playlist_obj.get("genre"):
playlist.metadata.genres = playlist_obj["genre"]
Expand Down Expand Up @@ -380,7 +380,9 @@ async def _parse_track(
track.artists.append(artist)

if track_obj.get("artwork_url"):
track.metadata.images = [MediaItemImage(ImageType.THUMB, track_obj["artwork_url"])]
track.metadata.images = [
MediaItemImage(type=ImageType.THUMB, path=track_obj["artwork_url"])
]
if track_obj.get("description"):
track.metadata.description = track_obj["description"]
if track_obj.get("genre"):
Expand Down
Loading

0 comments on commit 3df3f13

Please sign in to comment.