kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
add most quality filters and test
rodzic
7fcaa1fed2
commit
2532dbb4a5
|
@ -1,6 +1,7 @@
|
|||
import django_filters
|
||||
from django.db.models import Q
|
||||
from django_filters import rest_framework as filters
|
||||
from django_filters import widgets
|
||||
|
||||
from funkwhale_api.audio import filters as audio_filters
|
||||
from funkwhale_api.audio import models as audio_models
|
||||
|
@ -115,6 +116,11 @@ class ArtistFilter(
|
|||
)
|
||||
)
|
||||
|
||||
has_mbid = filters.BooleanFilter(
|
||||
field_name="_",
|
||||
method="filter_has_mbid",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = models.Artist
|
||||
fields = {
|
||||
|
@ -132,6 +138,12 @@ class ArtistFilter(
|
|||
def filter_has_albums(self, queryset, name, value):
|
||||
return queryset.filter(albums__isnull=not value)
|
||||
|
||||
def filter_has_mbid(self, queryset, name, value):
|
||||
return queryset.filter(mbid__isnull=(not value))
|
||||
|
||||
|
||||
quality_choices = ("low", "medium", "high", "very_high")
|
||||
|
||||
|
||||
class TrackFilter(
|
||||
RelatedFilterSet,
|
||||
|
@ -171,6 +183,20 @@ class TrackFilter(
|
|||
("tag_matches", "related"),
|
||||
)
|
||||
)
|
||||
format = filters.CharFilter(
|
||||
field_name="_",
|
||||
method="filter_format",
|
||||
)
|
||||
|
||||
has_mbid = filters.BooleanFilter(
|
||||
field_name="_",
|
||||
method="filter_has_mbid",
|
||||
)
|
||||
|
||||
quality = filters.ChoiceFilter(
|
||||
choices=quality_choices,
|
||||
method="filter_quality",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = models.Track
|
||||
|
@ -193,6 +219,51 @@ class TrackFilter(
|
|||
def filter_artist(self, queryset, name, value):
|
||||
return queryset.filter(Q(artist=value) | Q(album__artist=value))
|
||||
|
||||
def filter_format(self, queryset, name, value):
|
||||
mimetypes = [utils.get_type_from_ext(e) for e in value.split(",")]
|
||||
return queryset.filter(uploads__mimetype__in=mimetypes)
|
||||
|
||||
def filter_has_mbid(self, queryset, name, value):
|
||||
return queryset.filter(mbid__isnull=(not value))
|
||||
|
||||
def filter_quality(self, queryset, name, value):
|
||||
extension_to_mimetypes = utils.get_extension_to_mimetype_dict()
|
||||
|
||||
if value == "low":
|
||||
mp3_query = Q(
|
||||
uploads__mimetype=extension_to_mimetypes["mp3"],
|
||||
uploads__bitrate__lte=192,
|
||||
)
|
||||
OpusAACOGG_mimetypes = (
|
||||
extension_to_mimetypes["mp3"]
|
||||
.extend(extension_to_mimetypes["ogg"])
|
||||
.extend(extension_to_mimetypes["aac"])
|
||||
)
|
||||
|
||||
OpusAACOGG_query = Q(
|
||||
uploads__mimetype__in=OpusAACOGG_mimetypes, uploads__bitrate__lte=96
|
||||
)
|
||||
|
||||
queryset.filter(mp3_query | OpusAACOGG_query)
|
||||
|
||||
if value == "medium":
|
||||
mp3_query = Q(
|
||||
uploads__mimetype=extension_to_mimetypes["mp3"],
|
||||
uploads__bitrate__lte=256,
|
||||
)
|
||||
ogg_query = Q(
|
||||
uploads__mimetype=extension_to_mimetypes["ogg"],
|
||||
uploads__bitrate__lte=192,
|
||||
)
|
||||
|
||||
aacopus_query = Q(
|
||||
uploads__mimetype=extension_to_mimetypes["aac"].extend(
|
||||
extension_to_mimetypes["opus"]
|
||||
),
|
||||
uploads__bitrate__lte=128,
|
||||
)
|
||||
queryset.filter(mp3_query | ogg_query | aacopus_query)
|
||||
|
||||
|
||||
class UploadFilter(audio_filters.IncludeChannelsFilterSet):
|
||||
library = filters.CharFilter("library__uuid")
|
||||
|
@ -270,6 +341,25 @@ class AlbumFilter(
|
|||
("tag_matches", "related"),
|
||||
)
|
||||
)
|
||||
has_tags = filters.BooleanFilter(
|
||||
field_name="_",
|
||||
method="filter_has_tags",
|
||||
)
|
||||
|
||||
has_mbid = filters.BooleanFilter(
|
||||
field_name="_",
|
||||
method="filter_has_mbid",
|
||||
)
|
||||
|
||||
has_cover = filters.BooleanFilter(
|
||||
field_name="_",
|
||||
method="filter_has_cover",
|
||||
)
|
||||
|
||||
has_release_date = filters.BooleanFilter(
|
||||
field_name="_",
|
||||
method="filter_has_release_date",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = models.Album
|
||||
|
@ -283,6 +373,18 @@ class AlbumFilter(
|
|||
actor = utils.get_actor_from_request(self.request)
|
||||
return queryset.playable_by(actor, value)
|
||||
|
||||
def filter_has_tags(self, queryset, name, value):
|
||||
return queryset.filter(tagged_items__isnull=(not value))
|
||||
|
||||
def filter_has_mbid(self, queryset, name, value):
|
||||
return queryset.filter(mbid__isnull=(not value))
|
||||
|
||||
def filter_has_cover(self, queryset, name, value):
|
||||
return queryset.filter(attachment_cover__isnull=(not value))
|
||||
|
||||
def filter_has_release_date(self, queryset, name, value):
|
||||
return queryset.filter(release_date__isnull=(not value))
|
||||
|
||||
|
||||
class LibraryFilter(filters.FilterSet):
|
||||
q = fields.SearchFilter(
|
||||
|
|
|
@ -70,6 +70,17 @@ MIMETYPE_TO_EXTENSION = {mt: ext for ext, mt in AUDIO_EXTENSIONS_AND_MIMETYPE}
|
|||
SUPPORTED_EXTENSIONS = list(sorted({ext for ext, _ in AUDIO_EXTENSIONS_AND_MIMETYPE}))
|
||||
|
||||
|
||||
def get_extension_to_mimetype_dict():
|
||||
extension_dict = {}
|
||||
|
||||
for ext, mimetype in AUDIO_EXTENSIONS_AND_MIMETYPE:
|
||||
if ext not in extension_dict:
|
||||
extension_dict[ext] = []
|
||||
extension_dict[ext].append(mimetype)
|
||||
|
||||
return extension_dict
|
||||
|
||||
|
||||
def get_ext_from_type(mimetype):
|
||||
return MIMETYPE_TO_EXTENSION.get(mimetype)
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import os
|
||||
import pytest
|
||||
|
||||
from funkwhale_api.music import filters, models
|
||||
|
||||
DATA_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def test_artist_filter_ordering(factories, mocker):
|
||||
# Lista de prueba
|
||||
|
@ -263,3 +266,124 @@ def test_filter_tag_related(
|
|||
queryset=obj.__class__.objects.all(),
|
||||
)
|
||||
assert filterset.qs == matches
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"extension, mimetype", [("ogg", "audio/ogg"), ("mp3", "audio/mpeg")]
|
||||
)
|
||||
def test_track_filter_format(extension, mimetype, factories, mocker, anonymous_user):
|
||||
track_expected = factories["music.Track"]()
|
||||
name = ".".join(["test", extension])
|
||||
path = os.path.join(DATA_DIR, name)
|
||||
factories["music.Upload"](
|
||||
audio_file__from_path=path, track=track_expected, mimetype=mimetype
|
||||
)
|
||||
|
||||
track_unexpected = factories["music.Track"]()
|
||||
path_wrong_ext = os.path.join(DATA_DIR, "test.m4a")
|
||||
factories["music.Upload"](
|
||||
audio_file__from_path=path_wrong_ext,
|
||||
track=track_unexpected,
|
||||
mimetype="audio/x-m4a",
|
||||
)
|
||||
|
||||
qs = models.Track.objects.all()
|
||||
filterset = filters.TrackFilter(
|
||||
{"format": "ogg,mp3"},
|
||||
request=mocker.Mock(user=anonymous_user),
|
||||
queryset=qs,
|
||||
)
|
||||
|
||||
assert filterset.qs[0] == track_expected
|
||||
|
||||
|
||||
def test_album_filter_has_tags(factories, anonymous_user, mocker):
|
||||
album_expected = factories["music.Album"]()
|
||||
factories["music.Album"]()
|
||||
|
||||
factories["tags.TaggedItem"](content_object=album_expected)
|
||||
|
||||
qs = models.Album.objects.all()
|
||||
filterset = filters.AlbumFilter(
|
||||
{"has_tags": True},
|
||||
request=mocker.Mock(user=anonymous_user),
|
||||
queryset=qs,
|
||||
)
|
||||
|
||||
assert filterset.qs[0] == album_expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("fwobj", ["Album", "Track", "Artist"])
|
||||
def test_filter_has_mbid(fwobj, factories, anonymous_user, mocker):
|
||||
obj_expected = factories[f"music.{fwobj}"](
|
||||
mbid="e9b9d574-537d-4d2d-a4c7-6f6c91eaf4e0"
|
||||
)
|
||||
|
||||
factories[f"music.{fwobj}"](mbid=None)
|
||||
model_class = getattr(models, fwobj)
|
||||
qs = model_class.objects.all()
|
||||
|
||||
filter_class = getattr(filters, f"{fwobj}Filter")
|
||||
filterset = filter_class(
|
||||
data={"has_mbid": True},
|
||||
request=mocker.Mock(user=anonymous_user),
|
||||
queryset=qs,
|
||||
)
|
||||
|
||||
assert filterset.qs[0] == obj_expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("quality", ["low", "medium", "high", "very_high"])
|
||||
def test_track_quality_filter(factories, quality, mocker, anonymous_user):
|
||||
track_low = factories["music.Track"]()
|
||||
factories["music.Upload"](track=track_low, mimetype="audio/mp3", bitrate="20")
|
||||
|
||||
track_low_aac = factories["music.Track"]()
|
||||
factories["music.Upload"](track=track_low_aac, mimetype="audio/x-m4a", bitrate="20")
|
||||
|
||||
track_medium = factories["music.Track"]()
|
||||
factories["music.Upload"](track=track_medium, mimetype="audio/mp3", bitrate=194)
|
||||
|
||||
qs = models.Track.objects.all()
|
||||
filterset = filters.TrackFilter(
|
||||
{"quality": quality},
|
||||
request=mocker.Mock(user=anonymous_user),
|
||||
queryset=qs,
|
||||
)
|
||||
|
||||
if quality == "low":
|
||||
assert track_low in filterset.qs
|
||||
assert track_low_aac in filterset.qs
|
||||
|
||||
if quality == "medium":
|
||||
assert filterset.qs[0] == track_medium
|
||||
|
||||
if quality == "hight":
|
||||
assert filterset.qs[0] == track_medium
|
||||
|
||||
|
||||
def test_album_has_cover(factories, mocker, anonymous_user):
|
||||
attachment_cover = factories["common.Attachment"]()
|
||||
album = factories["music.Album"](attachment_cover=attachment_cover)
|
||||
factories["music.Album"].create_batch(5)
|
||||
qs = models.Album.objects.all()
|
||||
filterset = filters.AlbumFilter(
|
||||
{"has_cover": True},
|
||||
request=mocker.Mock(user=anonymous_user),
|
||||
queryset=qs,
|
||||
)
|
||||
|
||||
assert filterset.qs[0] == album
|
||||
|
||||
|
||||
def test_album_has_release_date(factories, mocker, anonymous_user):
|
||||
album = factories["music.Album"]()
|
||||
factories["music.Album"](release_date=None)
|
||||
qs = models.Album.objects.all()
|
||||
filterset = filters.AlbumFilter(
|
||||
{"has_release_date": True},
|
||||
request=mocker.Mock(user=anonymous_user),
|
||||
queryset=qs,
|
||||
)
|
||||
|
||||
assert filterset.qs[0] == album
|
||||
|
|
Ładowanie…
Reference in New Issue