add most quality filters and test

merge-requests/2710/head
Petitminion 2024-01-29 19:53:21 +01:00
rodzic 7fcaa1fed2
commit 2532dbb4a5
3 zmienionych plików z 237 dodań i 0 usunięć

Wyświetl plik

@ -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(

Wyświetl plik

@ -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)

Wyświetl plik

@ -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