From f19a0c5ff7cd716072a6fc8ed0818fc2f54889c9 Mon Sep 17 00:00:00 2001 From: cosven Date: Thu, 6 Mar 2025 02:19:42 +0800 Subject: [PATCH] serializer/library: serialize AlbumModel and more rpc API --- feeluown/library/library.py | 24 +++++++++++++++++++++++- feeluown/library/models.py | 8 +++++--- feeluown/serializers/python.py | 12 ++++++++++-- feeluown/serializers/typename.py | 2 ++ tests/serializers/test_serializers.py | 1 + 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/feeluown/library/library.py b/feeluown/library/library.py index e8d38f1990..be970e8ca4 100644 --- a/feeluown/library/library.py +++ b/feeluown/library/library.py @@ -16,13 +16,15 @@ from feeluown.library.models import ( ModelFlags as MF, BaseModel, SimpleSearchResult, BriefVideoModel, BriefSongModel, SongModel, - LyricModel, VideoModel, BriefAlbumModel, BriefArtistModel + LyricModel, VideoModel, BriefAlbumModel, BriefArtistModel, + AlbumModel, ) from feeluown.library.model_state import ModelState from feeluown.library.provider_protocol import ( check_flag as check_flag_impl, SupportsSongLyric, SupportsSongMV, SupportsSongMultiQuality, SupportsVideoMultiQuality, SupportsSongWebUrl, SupportsVideoWebUrl, + SupportsAlbumSongsReader, ) from feeluown.library.standby import ( get_standby_score, @@ -385,6 +387,26 @@ def song_get_lyric(self, song: BriefSongModel) -> Optional[LyricModel]: def album_upgrade(self, album: BriefAlbumModel): return self._model_upgrade(album) + def album_list_songs(self, album: BriefAlbumModel): + """ + :raises ResourceNotFound: + :raises ProviderIOError: + + .. versionadded:: 4.1.10 + """ + if not isinstance(album, AlbumModel): + ualbum = self.album_upgrade(album) + else: + ualbum = album + if ualbum.song_count == 0: + return [] + if ualbum.songs: + return ualbum.songs + provider = self.get(ualbum.source) + if isinstance(provider, SupportsAlbumSongsReader): + return list(provider.album_create_songs_rd(ualbum)) + raise ResourceNotFound(reason=ResourceNotFound.Reason.not_supported) + # -------- # Artist # -------- diff --git a/feeluown/library/models.py b/feeluown/library/models.py index a2cd5f1183..56c85c0c6e 100644 --- a/feeluown/library/models.py +++ b/feeluown/library/models.py @@ -56,7 +56,7 @@ from pydantic import ( ConfigDict, BaseModel as _BaseModel, PrivateAttr, - model_validator, model_serializer, + model_validator, model_serializer, Field, ) try: @@ -149,7 +149,9 @@ class BaseModel(_BaseModel): # For pydantic v2. if pydantic_version == 2: - model_config = ConfigDict(from_attributes=False, extra='forbid') + model_config = ConfigDict(from_attributes=False, + extra='forbid', + use_enum_values=True) else: # For pydantic v1. class Config: @@ -382,7 +384,7 @@ class AlbumModel(BriefAlbumModel, BaseNormalModel): meta: Any = ModelMeta.create(ModelType.album, is_normal=True) name: str cover: str - type_: AlbumType = AlbumType.standard + type_: AlbumType = Field(default=AlbumType.standard, validate_default=True) artists: List[BriefArtistModel] # One album usually has limited songs, and many providers' album_detail API # can return songs list. UPDATE(3.8.12): However, we found that albums diff --git a/feeluown/serializers/python.py b/feeluown/serializers/python.py index b6bb3b0a91..70ce0684d4 100644 --- a/feeluown/serializers/python.py +++ b/feeluown/serializers/python.py @@ -1,4 +1,4 @@ -from feeluown.library import BaseModel +from feeluown.library import BaseModel, AlbumType from .typename import attach_typename, get_type_by_name, model_cls_list from .base import Serializer, SerializerMeta, DeserializerError @@ -61,7 +61,7 @@ class ModelSerializer(PythonSerializer, metaclass=SerializerMeta): class Meta: types = (BaseModel, ) - def serialize(self, model): + def serialize(self, model: BaseModel): return model.model_dump() @@ -101,3 +101,11 @@ class Meta: def serialize(self, object): return object + + +class EnumSerializer(PythonSerializer, metaclass=SerializerMeta): + class Meta: + types = (AlbumType, ) + + def serialize(self, obj): + return obj.value diff --git a/feeluown/serializers/typename.py b/feeluown/serializers/typename.py index 903af3ebc2..fa8ad2b247 100644 --- a/feeluown/serializers/typename.py +++ b/feeluown/serializers/typename.py @@ -16,6 +16,7 @@ BriefAlbumModel, BriefPlaylistModel, BriefUserModel, + AlbumType, ) model_cls_list = [ @@ -38,6 +39,7 @@ _typenames = { 'player.Metadata': Metadata, 'app.App': App, # TODO: remove this + 'library.AlbumType': AlbumType, } for model_cls in model_cls_list: _typenames[f'library.{model_cls.__name__}'] = model_cls diff --git a/tests/serializers/test_serializers.py b/tests/serializers/test_serializers.py index b6d7c66ca7..bf52f1128d 100644 --- a/tests/serializers/test_serializers.py +++ b/tests/serializers/test_serializers.py @@ -51,6 +51,7 @@ def test_serialize_model(): assert song_js['__type__'] == 'feeluown.library.SongModel' assert song_js['album']['__type__'] == 'feeluown.library.AlbumModel' assert song_js['album']['uri'] == 'fuo://dummy/albums/1' + assert song_js['album']['type_'] == 'standard' def test_serialize_search_result():