def test_channel_serializer_representation(factories, to_api_date): content = factories["common.Content"]() channel = factories["audio.Channel"](artist__description=content) expected = { "artist": music_serializers.serialize_artist_simple(channel.artist), "uuid": str(channel.uuid), "creation_date": to_api_date(channel.creation_date), "actor": federation_serializers.APIActorSerializer(channel.actor).data, "attributed_to": federation_serializers.APIActorSerializer(channel.attributed_to).data, "metadata": {}, "rss_url": channel.get_rss_url(), "url": channel.actor.url, } expected["artist"]["description"] = common_serializers.ContentSerializer( content).data assert serializers.ChannelSerializer(channel).data == expected
def test_album_serializer(factories, to_api_date): actor = factories["federation.Actor"]() track1 = factories["music.Track"](position=2, album__attributed_to=actor, album__with_cover=True) factories["music.Track"](position=1, album=track1.album) album = track1.album expected = { "id": album.id, "fid": album.fid, "mbid": str(album.mbid), "title": album.title, "artist": serializers.serialize_artist_simple(album.artist), "creation_date": to_api_date(album.creation_date), "is_playable": False, "cover": common_serializers.AttachmentSerializer(album.attachment_cover).data, "release_date": to_api_date(album.release_date), "tracks_count": 2, "is_local": album.is_local, "tags": [], "attributed_to": federation_serializers.APIActorSerializer(actor).data, } serializer = serializers.AlbumSerializer( album.__class__.objects.with_tracks_count().get(pk=album.pk)) assert serializer.data == expected
def test_artist_with_albums_serializer_channel(factories, to_api_date): actor = factories["federation.Actor"]() channel = factories["audio.Channel"](attributed_to=actor, artist__with_cover=True) track = factories["music.Track"](album__artist=channel.artist) artist = track.artist artist = artist.__class__.objects.with_albums().get(pk=artist.pk) album = list(artist.albums.all())[0] setattr(artist, "_prefetched_tracks", range(42)) expected = { "id": artist.id, "fid": artist.fid, "mbid": str(artist.mbid), "name": artist.name, "is_local": artist.is_local, "content_category": artist.content_category, "creation_date": to_api_date(artist.creation_date), "albums": [serializers.ArtistAlbumSerializer(album).data], "tags": [], "attributed_to": federation_serializers.APIActorSerializer(actor).data, "tracks_count": 42, "cover": common_serializers.AttachmentSerializer(artist.attachment_cover).data, "channel": { "uuid": str(channel.uuid), "actor": { "full_username": channel.actor.full_username, "preferred_username": channel.actor.preferred_username, "domain": channel.actor.domain_id, }, }, } serializer = serializers.ArtistWithAlbumsSerializer(artist) assert serializer.data == expected
def test_track_serializer(factories, to_api_date): actor = factories["federation.Actor"]() upload = factories["music.Upload"]( track__license="cc-by-4.0", track__copyright="test", track__disc_number=2, track__attributed_to=actor, track__with_cover=True, ) track = upload.track setattr(track, "playable_uploads", [upload]) expected = { "id": track.id, "fid": track.fid, "artist": serializers.serialize_artist_simple(track.artist), "album": serializers.TrackAlbumSerializer(track.album).data, "mbid": str(track.mbid), "title": track.title, "position": track.position, "disc_number": track.disc_number, "uploads": [serializers.serialize_upload(upload)], "creation_date": to_api_date(track.creation_date), "listen_url": track.listen_url, "license": upload.track.license.code, "copyright": upload.track.copyright, "is_local": upload.track.is_local, "tags": [], "attributed_to": federation_serializers.APIActorSerializer(actor).data, "cover": common_serializers.AttachmentSerializer(track.attachment_cover).data, "downloads_count": track.downloads_count, } serializer = serializers.TrackSerializer(track) assert serializer.data == expected
def serialize_attributed_to(self, obj): # Import at runtime to avoid a circular import issue from funkwhale_api.federation import serializers as federation_serializers if not obj.attributed_to_id: return return federation_serializers.APIActorSerializer(obj.attributed_to).data
def test_fetch_serializer_unhandled_obj(factories, to_api_date): fetch = factories["federation.Fetch"](object=factories["users.User"]()) expected = { "id": fetch.pk, "url": fetch.url, "creation_date": to_api_date(fetch.creation_date), "fetch_date": None, "status": fetch.status, "detail": fetch.detail, "object": None, "actor": serializers.APIActorSerializer(fetch.actor).data, } assert api_serializers.FetchSerializer(fetch).data == expected
def test_track_favorite_serializer(factories, to_api_date): favorite = factories["favorites.TrackFavorite"]() actor = favorite.user.create_actor() expected = { "id": favorite.pk, "creation_date": to_api_date(favorite.creation_date), "track": music_serializers.TrackSerializer(favorite.track).data, "actor": federation_serializers.APIActorSerializer(actor).data, "user": users_serializers.UserBasicSerializer(favorite.user).data, } serializer = serializers.UserTrackFavoriteSerializer(favorite) assert serializer.data == expected
def test_listening_serializer(factories, to_api_date): listening = factories["history.Listening"]() actor = listening.user.create_actor() expected = { "id": listening.pk, "creation_date": to_api_date(listening.creation_date), "track": music_serializers.TrackSerializer(listening.track).data, "actor": federation_serializers.APIActorSerializer(actor).data, "user": users_serializers.UserBasicSerializer(listening.user).data, } serializer = serializers.ListeningSerializer(listening) assert serializer.data == expected
def test_library_serializer(factories, to_api_date): library = factories["music.Library"](uploads_count=5678) expected = { "fid": library.fid, "uuid": str(library.uuid), "actor": serializers.APIActorSerializer(library.actor).data, "name": library.name, "description": library.description, "creation_date": to_api_date(library.creation_date), "uploads_count": library.uploads_count, "privacy_level": library.privacy_level, "follow": None, "latest_scan": None, } serializer = api_serializers.LibrarySerializer(library) assert serializer.data == expected
class ChannelSerializer(serializers.ModelSerializer): artist = serializers.SerializerMethodField() actor = serializers.SerializerMethodField() downloads_count = serializers.SerializerMethodField() attributed_to = federation_serializers.APIActorSerializer() rss_url = serializers.CharField(source="get_rss_url") url = serializers.SerializerMethodField() class Meta: model = models.Channel fields = [ "uuid", "artist", "attributed_to", "actor", "creation_date", "metadata", "rss_url", "url", "downloads_count", ] def get_artist(self, obj): return music_serializers.serialize_artist_simple(obj.artist) def to_representation(self, obj): data = super().to_representation(obj) if self.context.get("subscriptions_count"): data["subscriptions_count"] = self.get_subscriptions_count(obj) return data def get_subscriptions_count(self, obj): return obj.actor.received_follows.exclude(approved=False).count() def get_downloads_count(self, obj): return getattr(obj, "_downloads_count", None) def get_actor(self, obj): if obj.attributed_to == actors.get_service_actor(): return None return federation_serializers.APIActorSerializer(obj.actor).data def get_url(self, obj): return obj.actor.url
def test_fetch_serializer_with_object(object_factory, expected_type, expected_id, factories, to_api_date): obj = factories[object_factory]() fetch = factories["federation.Fetch"](object=obj) expected = { "id": fetch.pk, "url": fetch.url, "creation_date": to_api_date(fetch.creation_date), "fetch_date": None, "status": fetch.status, "detail": fetch.detail, "object": { "type": expected_type, expected_id: getattr(obj, expected_id) }, "actor": serializers.APIActorSerializer(fetch.actor).data, } assert api_serializers.FetchSerializer(fetch).data == expected
class APIMutationSerializer(serializers.ModelSerializer): created_by = federation_serializers.APIActorSerializer(read_only=True) target = serializers.SerializerMethodField() class Meta: model = models.Mutation fields = [ "fid", "uuid", "type", "creation_date", "applied_date", "is_approved", "is_applied", "created_by", "approved_by", "summary", "payload", "previous_state", "target", ] read_only_fields = [ "uuid", "creation_date", "fid", "is_applied", "created_by", "approved_by", "previous_state", ] def get_target(self, obj): target = obj.target if not target: return id_field, type = TARGET_ID_TYPE_MAPPING[target._meta.label] return {"type": type, "id": getattr(target, id_field), "repr": str(target)} def validate_type(self, value): if value not in self.context["registry"]: raise serializers.ValidationError("Invalid mutation type {}".format(value)) return value
def test_playlist_serializer(factories, to_api_date): playlist = factories["playlists.Playlist"]() actor = playlist.user.create_actor() expected = { "id": playlist.pk, "name": playlist.name, "privacy_level": playlist.privacy_level, "is_playable": None, "creation_date": to_api_date(playlist.creation_date), "modification_date": to_api_date(playlist.modification_date), "actor": federation_serializers.APIActorSerializer(actor).data, "user": users_serializers.UserBasicSerializer(playlist.user).data, "duration": 0, "tracks_count": 0, "album_covers": [], } serializer = serializers.PlaylistSerializer(playlist) assert serializer.data == expected
def test_library_serializer_with_follow(factories, to_api_date): library = factories["music.Library"](uploads_count=5678) follow = factories["federation.LibraryFollow"](target=library) setattr(library, "_follows", [follow]) expected = { "fid": library.fid, "uuid": str(library.uuid), "actor": serializers.APIActorSerializer(library.actor).data, "name": library.name, "description": library.description, "creation_date": to_api_date(library.creation_date), "uploads_count": library.uploads_count, "privacy_level": library.privacy_level, "follow": api_serializers.NestedLibraryFollowSerializer(follow).data, "latest_scan": None, } serializer = api_serializers.LibrarySerializer(library) assert serializer.data == expected
def get_actor(self, o): # Import at runtime to avoid a circular import issue from funkwhale_api.federation import serializers as federation_serializers return federation_serializers.APIActorSerializer(o.actor).data
def get_actor(self, obj): actor = obj.user.actor if actor: return federation_serializers.APIActorSerializer(actor).data
def get_actor(self, obj): if obj.attributed_to == actors.get_service_actor(): return None return federation_serializers.APIActorSerializer(obj.actor).data