Add type hints to fields
This commit is contained in:
parent
6dcfe012f8
commit
a47080ab7d
|
@ -15,6 +15,8 @@ from funkwhale_api.federation import models as federation_models
|
|||
from funkwhale_api.federation import utils as federation_utils
|
||||
from funkwhale_api.users import models as user_models
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
def empty_dict():
|
||||
return {}
|
||||
|
@ -81,6 +83,7 @@ class Channel(models.Model):
|
|||
return self.actor.fid
|
||||
|
||||
@property
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(self):
|
||||
return self.actor.is_local
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@ from funkwhale_api.tags import models as tags_models
|
|||
from funkwhale_api.tags import serializers as tags_serializers
|
||||
from funkwhale_api.users import serializers as users_serializers
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import categories
|
||||
from . import models
|
||||
|
||||
|
@ -255,6 +258,7 @@ class ChannelSerializer(serializers.ModelSerializer):
|
|||
"downloads_count",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_artist(self, obj):
|
||||
return music_serializers.serialize_artist_simple(obj.artist)
|
||||
|
||||
|
@ -264,17 +268,21 @@ class ChannelSerializer(serializers.ModelSerializer):
|
|||
data["subscriptions_count"] = self.get_subscriptions_count(obj)
|
||||
return data
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_subscriptions_count(self, obj):
|
||||
return obj.actor.received_follows.exclude(approved=False).count()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_downloads_count(self, obj):
|
||||
return getattr(obj, "_downloads_count", None) or 0
|
||||
|
||||
@extend_schema_field(federation_serializers.APIActorSerializer)
|
||||
def get_actor(self, obj):
|
||||
if obj.attributed_to == actors.get_service_actor():
|
||||
return None
|
||||
return federation_serializers.APIActorSerializer(obj.actor).data
|
||||
|
||||
@extend_schema_field(OpenApiTypes.URI)
|
||||
def get_url(self, obj):
|
||||
return obj.actor.url
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ from django.urls import reverse
|
|||
from versatileimagefield.fields import VersatileImageField
|
||||
from versatileimagefield.image_warmer import VersatileImageFieldWarmer
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from funkwhale_api.federation import utils as federation_utils
|
||||
|
||||
from . import utils
|
||||
|
@ -240,6 +243,7 @@ class Attachment(models.Model):
|
|||
return super().save()
|
||||
|
||||
@property
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(self):
|
||||
return federation_utils.is_local(self.fid)
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@ from django.core.files.uploadedfile import SimpleUploadedFile
|
|||
from django.utils.encoding import smart_text
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import models
|
||||
from . import utils
|
||||
|
||||
|
@ -270,6 +273,7 @@ class APIMutationSerializer(serializers.ModelSerializer):
|
|||
"previous_state",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_target(self, obj):
|
||||
target = obj.target
|
||||
if not target:
|
||||
|
@ -292,6 +296,7 @@ class AttachmentSerializer(serializers.Serializer):
|
|||
file = StripExifImageField(write_only=True)
|
||||
urls = serializers.SerializerMethodField()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_urls(self, o):
|
||||
urls = {}
|
||||
urls["source"] = o.url
|
||||
|
@ -315,6 +320,7 @@ class ContentSerializer(serializers.Serializer):
|
|||
)
|
||||
html = serializers.SerializerMethodField()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def get_html(self, o):
|
||||
return utils.render_html(o.text, o.content_type)
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ from funkwhale_api.federation import serializers as federation_serializers
|
|||
from funkwhale_api.music.serializers import TrackActivitySerializer, TrackSerializer
|
||||
from funkwhale_api.users.serializers import UserActivitySerializer, UserBasicSerializer
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
|
@ -35,6 +37,7 @@ class UserTrackFavoriteSerializer(serializers.ModelSerializer):
|
|||
fields = ("id", "user", "track", "creation_date", "actor")
|
||||
actor = serializers.SerializerMethodField()
|
||||
|
||||
@extend_schema_field(federation_serializers.APIActorSerializer)
|
||||
def get_actor(self, obj):
|
||||
actor = obj.user.actor
|
||||
if actor:
|
||||
|
|
|
@ -13,6 +13,9 @@ from funkwhale_api.common import serializers as common_serializers
|
|||
from funkwhale_api.music import models as music_models
|
||||
from funkwhale_api.users import serializers as users_serializers
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import filters
|
||||
from . import models
|
||||
from . import serializers as federation_serializers
|
||||
|
@ -62,15 +65,18 @@ class LibrarySerializer(serializers.ModelSerializer):
|
|||
"latest_scan",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_uploads_count(self, o):
|
||||
return max(getattr(o, "_uploads_count", 0), o.uploads_count)
|
||||
|
||||
@extend_schema_field(NestedLibraryFollowSerializer)
|
||||
def get_follow(self, o):
|
||||
try:
|
||||
return NestedLibraryFollowSerializer(o._follows[0]).data
|
||||
except (AttributeError, IndexError):
|
||||
return None
|
||||
|
||||
@extend_schema_field(LibraryScanSerializer)
|
||||
def get_latest_scan(self, o):
|
||||
scan = o.scans.order_by("-creation_date").first()
|
||||
if scan:
|
||||
|
@ -95,6 +101,7 @@ class LibraryFollowSerializer(serializers.ModelSerializer):
|
|||
raise serializers.ValidationError("You are already following this library")
|
||||
return v
|
||||
|
||||
@extend_schema_field(federation_serializers.APIActorSerializer)
|
||||
def get_actor(self, o):
|
||||
return federation_serializers.APIActorSerializer(o.actor).data
|
||||
|
||||
|
@ -135,14 +142,17 @@ class ActivitySerializer(serializers.ModelSerializer):
|
|||
"type",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_object(self, o):
|
||||
if o.object:
|
||||
return serialize_generic_relation(o, o.object)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_related_object(self, o):
|
||||
if o.related_object:
|
||||
return serialize_generic_relation(o, o.related_object)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_target(self, o):
|
||||
if o.target:
|
||||
return serialize_generic_relation(o, o.target)
|
||||
|
@ -268,6 +278,7 @@ class FullActorSerializer(serializers.Serializer):
|
|||
summary = common_serializers.ContentSerializer(source="summary_obj")
|
||||
icon = common_serializers.AttachmentSerializer(source="attachment_icon")
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def get_is_channel(self, o):
|
||||
try:
|
||||
return bool(o.channel)
|
||||
|
|
|
@ -19,6 +19,9 @@ from funkwhale_api.common import utils as common_utils
|
|||
from funkwhale_api.common import validators as common_validators
|
||||
from funkwhale_api.music import utils as music_utils
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import utils as federation_utils
|
||||
|
||||
TYPE_CHOICES = [
|
||||
|
@ -48,6 +51,7 @@ class FederationMixin(models.Model):
|
|||
abstract = True
|
||||
|
||||
@property
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(self):
|
||||
return federation_utils.is_local(self.fid)
|
||||
|
||||
|
@ -172,6 +176,7 @@ class Domain(models.Model):
|
|||
return data
|
||||
|
||||
@property
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(self):
|
||||
return self.name == settings.FEDERATION_HOSTNAME
|
||||
|
||||
|
@ -232,6 +237,7 @@ class Actor(models.Model):
|
|||
return "{}#main-key".format(self.fid)
|
||||
|
||||
@property
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def full_username(self):
|
||||
return "{}@{}".format(self.preferred_username, self.domain_id)
|
||||
|
||||
|
@ -239,13 +245,16 @@ class Actor(models.Model):
|
|||
return "{}@{}".format(self.preferred_username, self.domain_id)
|
||||
|
||||
@property
|
||||
def is_local(self):
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(self) -> bool:
|
||||
return self.domain_id == settings.FEDERATION_HOSTNAME
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'object'}})
|
||||
def get_approved_followers(self):
|
||||
follows = self.received_follows.filter(approved=True)
|
||||
return self.followers.filter(pk__in=follows.values_list("actor", flat=True))
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def should_autoapprove_follow(self, actor):
|
||||
if self.get_channel():
|
||||
return True
|
||||
|
|
|
@ -11,6 +11,9 @@ from django.db.models import CharField, Q, Value
|
|||
from funkwhale_api.common import session
|
||||
from funkwhale_api.moderation import mrf
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import exceptions
|
||||
from . import signing
|
||||
|
||||
|
@ -138,7 +141,7 @@ def local_qs(queryset, url_field="fid", include=True):
|
|||
query = ~query
|
||||
return queryset.filter(query)
|
||||
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(url):
|
||||
if not url:
|
||||
return True
|
||||
|
|
|
@ -5,6 +5,8 @@ from funkwhale_api.federation import serializers as federation_serializers
|
|||
from funkwhale_api.music.serializers import TrackActivitySerializer, TrackSerializer
|
||||
from funkwhale_api.users.serializers import UserActivitySerializer, UserBasicSerializer
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
|
@ -39,6 +41,7 @@ class ListeningSerializer(serializers.ModelSerializer):
|
|||
|
||||
return super().create(validated_data)
|
||||
|
||||
@extend_schema_field(federation_serializers.APIActorSerializer)
|
||||
def get_actor(self, obj):
|
||||
actor = obj.user.actor
|
||||
if actor:
|
||||
|
|
|
@ -18,6 +18,9 @@ from funkwhale_api.music import serializers as music_serializers
|
|||
from funkwhale_api.tags import models as tags_models
|
||||
from funkwhale_api.users import models as users_models
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import filters
|
||||
|
||||
|
||||
|
@ -90,6 +93,7 @@ class ManageUserSerializer(serializers.ModelSerializer):
|
|||
)
|
||||
return instance
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_actor(self, obj):
|
||||
if obj.actor:
|
||||
return ManageBaseActorSerializer(obj.actor).data
|
||||
|
@ -151,9 +155,11 @@ class ManageDomainSerializer(serializers.ModelSerializer):
|
|||
"nodeinfo_fetch_date",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_actors_count(self, o):
|
||||
return getattr(o, "actors_count", 0)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_outbox_activities_count(self, o):
|
||||
return getattr(o, "outbox_activities_count", 0)
|
||||
|
||||
|
@ -211,6 +217,7 @@ class ManageBaseActorSerializer(serializers.ModelSerializer):
|
|||
]
|
||||
read_only_fields = ["creation_date", "instance_policy"]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def get_is_local(self, o):
|
||||
return o.domain_id == settings.FEDERATION_HOSTNAME
|
||||
|
||||
|
@ -228,6 +235,7 @@ class ManageActorSerializer(ManageBaseActorSerializer):
|
|||
]
|
||||
read_only_fields = ["creation_date", "instance_policy"]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_uploads_count(self, o):
|
||||
return getattr(o, "uploads_count", 0)
|
||||
|
||||
|
@ -353,6 +361,7 @@ class ManageBaseAlbumSerializer(serializers.ModelSerializer):
|
|||
"tracks_count",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, o):
|
||||
return getattr(o, "_tracks_count", None)
|
||||
|
||||
|
@ -385,6 +394,7 @@ class ManageNestedAlbumSerializer(ManageBaseAlbumSerializer):
|
|||
model = music_models.Album
|
||||
fields = ManageBaseAlbumSerializer.Meta.fields + ["tracks_count"]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, obj):
|
||||
return getattr(obj, "tracks_count", None)
|
||||
|
||||
|
@ -411,16 +421,20 @@ class ManageArtistSerializer(
|
|||
"content_category",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, obj):
|
||||
return getattr(obj, "_tracks_count", None)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_albums_count(self, obj):
|
||||
return getattr(obj, "_albums_count", None)
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'string'}})
|
||||
def get_tags(self, obj):
|
||||
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
|
||||
return [ti.tag.name for ti in tagged_items]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def get_channel(self, obj):
|
||||
if "channel" in obj._state.fields_cache and obj.get_channel():
|
||||
return str(obj.channel.uuid)
|
||||
|
@ -446,9 +460,11 @@ class ManageAlbumSerializer(
|
|||
"tracks_count",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, o):
|
||||
return len(o.tracks.all())
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'string'}})
|
||||
def get_tags(self, obj):
|
||||
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
|
||||
return [ti.tag.name for ti in tagged_items]
|
||||
|
@ -483,9 +499,11 @@ class ManageTrackSerializer(
|
|||
"cover",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_uploads_count(self, obj):
|
||||
return getattr(obj, "uploads_count", None)
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'string'}})
|
||||
def get_tags(self, obj):
|
||||
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
|
||||
return [ti.tag.name for ti in tagged_items]
|
||||
|
@ -570,9 +588,11 @@ class ManageLibrarySerializer(serializers.ModelSerializer):
|
|||
"creation_date",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_uploads_count(self, obj):
|
||||
return getattr(obj, "_uploads_count", obj.uploads_count)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_followers_count(self, obj):
|
||||
return getattr(obj, "followers_count", None)
|
||||
|
||||
|
@ -652,12 +672,15 @@ class ManageTagSerializer(ManageBaseAlbumSerializer):
|
|||
"artists_count",
|
||||
]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, obj):
|
||||
return getattr(obj, "_tracks_count", None)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_albums_count(self, obj):
|
||||
return getattr(obj, "_albums_count", None)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_artists_count(self, obj):
|
||||
return getattr(obj, "_artists_count", None)
|
||||
|
||||
|
@ -728,6 +751,7 @@ class ManageReportSerializer(serializers.ModelSerializer):
|
|||
"summary",
|
||||
]
|
||||
|
||||
@extend_schema_field(ManageBaseNoteSerializer)
|
||||
def get_notes(self, o):
|
||||
notes = getattr(o, "_prefetched_notes", [])
|
||||
return ManageBaseNoteSerializer(notes, many=True).data
|
||||
|
@ -761,6 +785,7 @@ class ManageUserRequestSerializer(serializers.ModelSerializer):
|
|||
"metadata",
|
||||
]
|
||||
|
||||
@extend_schema_field(ManageBaseNoteSerializer)
|
||||
def get_notes(self, o):
|
||||
notes = getattr(o, "_prefetched_notes", [])
|
||||
return ManageBaseNoteSerializer(notes, many=True).data
|
||||
|
|
|
@ -35,6 +35,9 @@ from funkwhale_api.federation import utils as federation_utils
|
|||
from funkwhale_api.tags import models as tags_models
|
||||
from . import importers, metadata, utils
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
MAX_LENGTHS = {
|
||||
|
@ -137,6 +140,7 @@ class APIModelMixin(models.Model):
|
|||
return super().save(**kwargs)
|
||||
|
||||
@property
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(self):
|
||||
return federation_utils.is_local(self.fid)
|
||||
|
||||
|
@ -148,6 +152,7 @@ class APIModelMixin(models.Model):
|
|||
parsed = urllib.parse.urlparse(self.fid)
|
||||
return parsed.hostname
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'string'}})
|
||||
def get_tags(self):
|
||||
return list(sorted(self.tagged_items.values_list("tag__name", flat=True)))
|
||||
|
||||
|
@ -652,7 +657,7 @@ class Track(APIModelMixin):
|
|||
)
|
||||
|
||||
@property
|
||||
def listen_url(self):
|
||||
def listen_url(self) -> str:
|
||||
# Not using reverse because this is slow
|
||||
return "/api/v1/listen/{}/".format(self.uuid)
|
||||
|
||||
|
@ -782,6 +787,7 @@ class Upload(models.Model):
|
|||
objects = UploadQuerySet.as_manager()
|
||||
|
||||
@property
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def is_local(self):
|
||||
return federation_utils.is_local(self.fid)
|
||||
|
||||
|
@ -834,7 +840,7 @@ class Upload(models.Model):
|
|||
)
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
def filename(self) -> str:
|
||||
return "{}.{}".format(self.track.full_name, self.extension)
|
||||
|
||||
@property
|
||||
|
@ -910,10 +916,10 @@ class Upload(models.Model):
|
|||
return metadata.Metadata(audio_file)
|
||||
|
||||
@property
|
||||
def listen_url(self):
|
||||
def listen_url(self) -> str:
|
||||
return self.track.listen_url + "?upload={}".format(self.uuid)
|
||||
|
||||
def get_listen_url(self, to=None, download=True):
|
||||
def get_listen_url(self, to=None, download=True) -> str:
|
||||
url = self.listen_url
|
||||
if to:
|
||||
url += "&to={}".format(to)
|
||||
|
@ -1019,7 +1025,7 @@ class UploadVersion(models.Model):
|
|||
unique_together = ("upload", "mimetype", "bitrate")
|
||||
|
||||
@property
|
||||
def filename(self):
|
||||
def filename(self) -> str:
|
||||
try:
|
||||
return (
|
||||
self.upload.track.full_name
|
||||
|
@ -1211,15 +1217,15 @@ class Library(federation_models.FederationMixin):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_moderation_url(self):
|
||||
def get_moderation_url(self) -> str:
|
||||
return "/manage/library/libraries/{}".format(self.uuid)
|
||||
|
||||
def get_federation_id(self):
|
||||
def get_federation_id(self) -> str:
|
||||
return federation_utils.full_url(
|
||||
reverse("federation:music:libraries-detail", kwargs={"uuid": self.uuid})
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
def get_absolute_url(self) -> str:
|
||||
return "/library/{}".format(self.uuid)
|
||||
|
||||
def save(self, **kwargs):
|
||||
|
@ -1229,7 +1235,7 @@ class Library(federation_models.FederationMixin):
|
|||
|
||||
return super().save(**kwargs)
|
||||
|
||||
def should_autoapprove_follow(self, actor):
|
||||
def should_autoapprove_follow(self, actor) -> bool:
|
||||
if self.privacy_level == "everyone":
|
||||
return True
|
||||
if self.privacy_level == "instance" and actor.get_user():
|
||||
|
|
|
@ -17,6 +17,9 @@ from funkwhale_api.tags import serializers as tags_serializers
|
|||
|
||||
from . import filters, models, tasks, utils
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
NOOP = object()
|
||||
|
||||
COVER_WRITE_FIELD = common_serializers.RelatedField(
|
||||
|
@ -38,7 +41,7 @@ class CoverField(common_serializers.AttachmentSerializer):
|
|||
|
||||
cover_field = CoverField()
|
||||
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def serialize_attributed_to(self, obj):
|
||||
# Import at runtime to avoid a circular import issue
|
||||
from funkwhale_api.federation import serializers as federation_serializers
|
||||
|
@ -74,6 +77,7 @@ class LicenseSerializer(serializers.Serializer):
|
|||
attribution = serializers.BooleanField()
|
||||
copyleft = serializers.BooleanField()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def get_id(self, obj):
|
||||
return obj["identifiers"][0]
|
||||
|
||||
|
@ -94,12 +98,15 @@ class ArtistAlbumSerializer(serializers.Serializer):
|
|||
release_date = serializers.DateField()
|
||||
creation_date = serializers.DateTimeField()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_artist(self, o):
|
||||
return o.artist_id
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, o):
|
||||
return len(o.tracks.all())
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def get_is_playable(self, obj):
|
||||
try:
|
||||
return bool(obj.is_playable_by_actor)
|
||||
|
@ -125,16 +132,19 @@ class ArtistWithAlbumsSerializer(OptionalDescriptionMixin, serializers.Serialize
|
|||
is_local = serializers.BooleanField()
|
||||
cover = cover_field
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'string'}})
|
||||
def get_tags(self, obj):
|
||||
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
|
||||
return [ti.tag.name for ti in tagged_items]
|
||||
|
||||
get_attributed_to = serialize_attributed_to
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, o):
|
||||
tracks = getattr(o, "_prefetched_tracks", None)
|
||||
return len(tracks) if tracks else None
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_channel(self, o):
|
||||
channel = o.get_channel()
|
||||
if not channel:
|
||||
|
@ -205,12 +215,11 @@ class AlbumSerializer(OptionalDescriptionMixin, serializers.Serializer):
|
|||
|
||||
get_attributed_to = serialize_attributed_to
|
||||
|
||||
def get_artist(self, o):
|
||||
return serialize_artist_simple(o.artist)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, o):
|
||||
return len(o.tracks.all())
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def get_is_playable(self, obj):
|
||||
try:
|
||||
return any(
|
||||
|
@ -222,10 +231,12 @@ class AlbumSerializer(OptionalDescriptionMixin, serializers.Serializer):
|
|||
except AttributeError:
|
||||
return None
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'string'}})
|
||||
def get_tags(self, obj):
|
||||
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
|
||||
return [ti.tag.name for ti in tagged_items]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_duration(self, obj):
|
||||
try:
|
||||
return obj.duration
|
||||
|
@ -239,6 +250,7 @@ class TrackAlbumSerializer(serializers.ModelSerializer):
|
|||
cover = cover_field
|
||||
tracks_count = serializers.SerializerMethodField()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, o):
|
||||
return getattr(o, "_prefetched_tracks_count", len(o.tracks.all()))
|
||||
|
||||
|
@ -257,10 +269,7 @@ class TrackAlbumSerializer(serializers.ModelSerializer):
|
|||
"tracks_count",
|
||||
)
|
||||
|
||||
def get_artist(self, o):
|
||||
return serialize_artist_simple(o.artist)
|
||||
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def serialize_upload(upload):
|
||||
return {
|
||||
"uuid": str(upload.uuid),
|
||||
|
@ -314,12 +323,11 @@ class TrackSerializer(OptionalDescriptionMixin, serializers.Serializer):
|
|||
get_attributed_to = serialize_attributed_to
|
||||
is_playable = serializers.SerializerMethodField()
|
||||
|
||||
def get_artist(self, o):
|
||||
return serialize_artist_simple(o.artist)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.URI)
|
||||
def get_listen_url(self, obj):
|
||||
return obj.listen_url
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'object'}})
|
||||
def get_uploads(self, obj):
|
||||
uploads = getattr(obj, "playable_uploads", [])
|
||||
# we put local uploads first
|
||||
|
@ -327,13 +335,16 @@ class TrackSerializer(OptionalDescriptionMixin, serializers.Serializer):
|
|||
uploads = sorted(uploads, key=lambda u: u["is_local"], reverse=True)
|
||||
return list(uploads)
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'str'}})
|
||||
def get_tags(self, obj):
|
||||
tagged_items = getattr(obj, "_prefetched_tagged_items", [])
|
||||
return [ti.tag.name for ti in tagged_items]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def get_license(self, o):
|
||||
return o.license_id
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def get_is_playable(self, obj):
|
||||
return bool(getattr(obj, "playable_uploads", []))
|
||||
|
||||
|
@ -359,9 +370,11 @@ class LibraryForOwnerSerializer(serializers.ModelSerializer):
|
|||
]
|
||||
read_only_fields = ["fid", "uuid", "creation_date", "actor"]
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_uploads_count(self, o):
|
||||
return getattr(o, "_uploads_count", o.uploads_count)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_size(self, o):
|
||||
return getattr(o, "_size", 0)
|
||||
|
||||
|
@ -370,6 +383,7 @@ class LibraryForOwnerSerializer(serializers.ModelSerializer):
|
|||
{"type": "Update", "object": {"type": "Library"}}, context={"library": obj}
|
||||
)
|
||||
|
||||
@extend_schema_field(OpenApiTypes.OBJECT)
|
||||
def get_actor(self, o):
|
||||
# Import at runtime to avoid a circular import issue
|
||||
from funkwhale_api.federation import serializers as federation_serializers
|
||||
|
|
|
@ -5,6 +5,9 @@ from funkwhale_api.music.models import Track
|
|||
from funkwhale_api.music.serializers import TrackSerializer
|
||||
from funkwhale_api.users.serializers import UserBasicSerializer
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
|
@ -46,17 +49,20 @@ class PlaylistSerializer(serializers.ModelSerializer):
|
|||
)
|
||||
read_only_fields = ["id", "modification_date", "creation_date"]
|
||||
|
||||
@extend_schema_field(federation_serializers.APIActorSerializer)
|
||||
def get_actor(self, obj):
|
||||
actor = obj.user.actor
|
||||
if actor:
|
||||
return federation_serializers.APIActorSerializer(actor).data
|
||||
|
||||
@extend_schema_field(OpenApiTypes.BOOL)
|
||||
def get_is_playable(self, obj):
|
||||
try:
|
||||
return bool(obj.playable_plts)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_tracks_count(self, obj):
|
||||
try:
|
||||
return obj.tracks_count
|
||||
|
@ -64,6 +70,7 @@ class PlaylistSerializer(serializers.ModelSerializer):
|
|||
# no annotation?
|
||||
return obj.playlist_tracks.count()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT)
|
||||
def get_duration(self, obj):
|
||||
try:
|
||||
return obj.duration
|
||||
|
@ -71,6 +78,7 @@ class PlaylistSerializer(serializers.ModelSerializer):
|
|||
# no annotation?
|
||||
return 0
|
||||
|
||||
@extend_schema_field({'type': 'array', 'items': {'type': 'uri'}})
|
||||
def get_album_covers(self, obj):
|
||||
try:
|
||||
plts = obj.plts_for_cover
|
||||
|
|
|
@ -29,6 +29,8 @@ from funkwhale_api.federation import keys
|
|||
from funkwhale_api.federation import models as federation_models
|
||||
from funkwhale_api.federation import utils as federation_utils
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
def get_token(length=5):
|
||||
wordlist_path = os.path.join(
|
||||
|
@ -307,6 +309,7 @@ class User(AbstractUser):
|
|||
|
||||
return groups
|
||||
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def full_username(self):
|
||||
return "{}@{}".format(self.username, settings.FEDERATION_HOSTNAME)
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ from funkwhale_api.moderation import models as moderation_models
|
|||
from funkwhale_api.moderation import tasks as moderation_tasks
|
||||
from funkwhale_api.moderation import utils as moderation_utils
|
||||
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
|
||||
from . import adapters
|
||||
from . import models
|
||||
from . import authentication as users_authentication
|
||||
|
@ -205,6 +208,7 @@ class UserReadSerializer(serializers.ModelSerializer):
|
|||
def get_permissions(self, o):
|
||||
return o.get_permissions()
|
||||
|
||||
@extend_schema_field(OpenApiTypes.STR)
|
||||
def get_full_username(self, o):
|
||||
if o.actor:
|
||||
return o.actor.full_username
|
||||
|
|
Loading…
Reference in New Issue