From be146090f18e482214ea99b62397d8b2af87b284 Mon Sep 17 00:00:00 2001 From: Matthias Meulien Date: Fri, 9 Jun 2023 22:41:35 +0200 Subject: [PATCH] Make model helper collect artist models Refs: #143 --- argos/controllers/albums.py | 2 +- argos/controllers/base.py | 4 +- argos/controllers/library.py | 4 +- argos/controllers/playlists.py | 4 +- argos/controllers/tracklist.py | 2 +- argos/controllers/visitors.py | 2 +- argos/{controllers => model}/helper.py | 41 ++++++++++++++++----- argos/model/model.py | 9 ++++- tests/controllers/test_visitors.py | 2 +- tests/{controllers => model}/test_helper.py | 4 +- 10 files changed, 52 insertions(+), 22 deletions(-) rename argos/{controllers => model}/helper.py (72%) rename tests/{controllers => model}/test_helper.py (93%) diff --git a/argos/controllers/albums.py b/argos/controllers/albums.py index 61a73bb..b96ceef 100644 --- a/argos/controllers/albums.py +++ b/argos/controllers/albums.py @@ -50,7 +50,7 @@ async def complete_album_description(self, message: Message) -> None: length_acc = LengthAcc() metadata_collector = AlbumMetadataCollector() - parsed_tracks = self.helper.parse_tracks( + parsed_tracks = self._helper.parse_tracks( tracks_dto, visitors=[length_acc, metadata_collector] ).get(album_uri, []) diff --git a/argos/controllers/base.py b/argos/controllers/base.py index b61f9c1..1a0260b 100644 --- a/argos/controllers/base.py +++ b/argos/controllers/base.py @@ -6,10 +6,10 @@ if TYPE_CHECKING: from argos.app import Application -from argos.controllers.helper import ModelHelper from argos.http import MopidyHTTPClient from argos.message import Message, MessageType from argos.model import Model +from argos.model.helper import ModelHelper from argos.notify import Notifier @@ -36,7 +36,7 @@ def __init__( self._notifier: Notifier = application.props.notifier self._settings: Gio.Settings = application.props.settings - self.helper = ModelHelper() + self._helper: ModelHelper = self._model.helper def send_message( self, message_type: MessageType, data: Optional[Dict[str, Any]] = None diff --git a/argos/controllers/library.py b/argos/controllers/library.py index 2f2e8ef..9e4f31d 100644 --- a/argos/controllers/library.py +++ b/argos/controllers/library.py @@ -315,7 +315,7 @@ async def _complete_albums( ) LOGGER.debug("Parsing albums tracks") - parsed_tracks = self.helper.parse_tracks( + parsed_tracks = self._helper.parse_tracks( directory_tracks_dto, visitors=[length_acc, metadata_collector] ) @@ -438,7 +438,7 @@ async def _complete_tracks( LOGGER.debug("Parsing tracks") parsed_tracks: List[TrackModel] = [] - for tracks in self.helper.parse_tracks(directory_tracks_dto).values(): + for tracks in self._helper.parse_tracks(directory_tracks_dto).values(): for track in tracks: track_uri = track.uri if images is not None and len(images.get(track_uri, [])) > 0: diff --git a/argos/controllers/playlists.py b/argos/controllers/playlists.py index d6a1d10..b084546 100644 --- a/argos/controllers/playlists.py +++ b/argos/controllers/playlists.py @@ -206,7 +206,7 @@ async def _complete_playlist_from( params=track_uris, ) parsed_tracks: List[TrackModel] = [] - for tracks in self.helper.parse_tracks( + for tracks in self._helper.parse_tracks( found_tracks_dto, visitors=[PlaylistTrackNameFix(playlist_dto)] ).values(): parsed_tracks += tracks @@ -269,7 +269,7 @@ async def __complete_history_playlist(self) -> None: ) parsed_history_tracks_with_duplicates: List[TrackModel] = [] - parsed_history_tracks: Dict[str, List[TrackModel]] = self.helper.parse_tracks( + parsed_history_tracks: Dict[str, List[TrackModel]] = self._helper.parse_tracks( history_tracks_dto ) for history_item in history: diff --git a/argos/controllers/tracklist.py b/argos/controllers/tracklist.py index 4ac5c05..d382859 100644 --- a/argos/controllers/tracklist.py +++ b/argos/controllers/tracklist.py @@ -81,7 +81,7 @@ async def get_tracklist(self, message: Message) -> None: tl_tracks = ( [ - self.helper.convert_tl_track(tl_track_dto) + self._helper.convert_tl_track(tl_track_dto) for tl_track_dto in tl_tracks_dto ] if tl_tracks_dto is not None diff --git a/argos/controllers/visitors.py b/argos/controllers/visitors.py index 50b27ab..49ca697 100644 --- a/argos/controllers/visitors.py +++ b/argos/controllers/visitors.py @@ -1,6 +1,6 @@ """Visitors for tracks DTOs. -See ``argos.controllers.helper.ModelHelper.parse_tracks()``. +See ``argos.model.helper.ModelHelper.parse_tracks()``. """ import logging diff --git a/argos/controllers/helper.py b/argos/model/helper.py similarity index 72% rename from argos/controllers/helper.py rename to argos/model/helper.py index b8ab17a..e916ece 100644 --- a/argos/controllers/helper.py +++ b/argos/model/helper.py @@ -1,8 +1,12 @@ from collections import defaultdict +from itertools import chain from typing import Callable, Dict, List, Mapping, Optional, Sequence from argos.dto import AlbumDTO, ArtistDTO, TlTrackDTO, TrackDTO -from argos.model import AlbumModel, ArtistModel, TracklistTrackModel, TrackModel +from argos.model.album import AlbumModel +from argos.model.artist import ArtistModel +from argos.model.track import TrackModel +from argos.model.tracklist import TracklistTrackModel class ModelHelper: @@ -12,7 +16,13 @@ class ModelHelper: """ + def __init__(self): + self._artists: Dict[str, ArtistModel] = {} + def convert_album(self, album_dto: AlbumDTO) -> AlbumModel: + for artist_dto in album_dto.artists: + self.convert_artist(artist_dto) + album = AlbumModel( uri=album_dto.uri, name=album_dto.name, @@ -20,19 +30,29 @@ def convert_album(self, album_dto: AlbumDTO) -> AlbumModel: num_discs=album_dto.num_discs, date=album_dto.date, ) - # TODO album dto has artists + return album def convert_artist(self, artist_dto: ArtistDTO) -> ArtistModel: - artist = ArtistModel( - uri=artist_dto.uri, - name=artist_dto.name, - sortname=artist_dto.name, - artist_mbid=artist_dto.musicbrainz_id, - ) - return artist + if artist_dto.uri not in self._artists: + artist = ArtistModel( + uri=artist_dto.uri, + name=artist_dto.name, + sortname=artist_dto.name, + artist_mbid=artist_dto.musicbrainz_id, + ) + self._artists[artist_dto.uri] = artist + + return self._artists[artist_dto.uri] def convert_track(self, track_dto: TrackDTO) -> TrackModel: + for artist_dto in chain( + track_dto.artists, + track_dto.composers, + track_dto.performers, + ): + self.convert_artist(artist_dto) + track = TrackModel( uri=track_dto.uri, name=track_dto.name, @@ -83,3 +103,6 @@ def parse_tracks( parsed_tracks[uri].append(self.convert_track(track_dto)) return parsed_tracks + + def get_artist(self, uri: str) -> Optional[ArtistModel]: + return self._artists.get(uri) diff --git a/argos/model/model.py b/argos/model/model.py index 68499e4..68e8df4 100644 --- a/argos/model/model.py +++ b/argos/model/model.py @@ -1,5 +1,4 @@ import logging -import random import threading from datetime import datetime from functools import partial @@ -15,6 +14,7 @@ compare_albums_by_name_func, compare_albums_by_publication_date_func, ) +from argos.model.artist import ArtistModel from argos.model.backends import ( GenericBackend, MopidyBackend, @@ -22,6 +22,7 @@ MopidyPodcastBackend, ) from argos.model.directory import DirectoryModel, compare_directories_func +from argos.model.helper import ModelHelper from argos.model.library import LibraryModel from argos.model.mixer import MixerModel from argos.model.playback import PlaybackModel @@ -61,6 +62,7 @@ class Model(WithThreadSafePropertySetter, GObject.Object): tracklist: TracklistModel playlists: Gio.ListStore backends: Gio.ListStore + helper: ModelHelper def __init__(self, application: "Application", *args, **kwargs): super().__init__(*args, **kwargs) @@ -80,6 +82,8 @@ def __init__(self, application: "Application", *args, **kwargs): self.backends.append(GenericBackend()) # Must be the last one! + self.helper = ModelHelper() + application._nm.connect("network-changed", self._on_nm_network_changed) self.playback.connect( @@ -390,6 +394,9 @@ def _complete_playlist_description() -> None: def get_album(self, uri: str) -> Optional[AlbumModel]: return self.library.get_album(uri) + def get_artist(self, uri: str) -> Optional[ArtistModel]: + return self.helper.get_artist(uri) + def get_directory(self, uri: Optional[str]) -> Optional[DirectoryModel]: return self.library.get_directory(uri) diff --git a/tests/controllers/test_visitors.py b/tests/controllers/test_visitors.py index 8e14f4b..daf29fa 100644 --- a/tests/controllers/test_visitors.py +++ b/tests/controllers/test_visitors.py @@ -3,13 +3,13 @@ import unittest from copy import copy -from argos.controllers.helper import ModelHelper from argos.controllers.visitors import ( AlbumMetadataCollector, LengthAcc, PlaylistTrackNameFix, ) from argos.dto import PlaylistDTO, TrackDTO, cast_seq_of +from argos.model.helper import ModelHelper def load_json_data(filename: str): diff --git a/tests/controllers/test_helper.py b/tests/model/test_helper.py similarity index 93% rename from tests/controllers/test_helper.py rename to tests/model/test_helper.py index 12e0eac..7987a76 100644 --- a/tests/controllers/test_helper.py +++ b/tests/model/test_helper.py @@ -1,10 +1,10 @@ import json import pathlib import unittest -from unittest.mock import Mock, call +from unittest.mock import Mock -from argos.controllers.helper import ModelHelper from argos.dto import TrackDTO +from argos.model.helper import ModelHelper from argos.model.track import TrackModel