Skip to content

Commit ff7f528

Browse files
committed
Merge branch 'develop' into feature/search
2 parents 4a261bd + 29f447b commit ff7f528

11 files changed

Lines changed: 92 additions & 30 deletions

File tree

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v5.0.0
3+
rev: v6.0.0
44
hooks:
55
- id: trailing-whitespace
66
- id: end-of-file-fixer

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ Any important notes regarding the update.
3434

3535
## Unreleased
3636

37+
### Added
38+
39+
- Allow to fetch full lyrics of a song at URL `api/library/songs/lyrics/<id>/`.
40+
3741
## 1.9.2 - 2025-03-22
3842

3943
## 1.9.1 - 2025-03-15

dakara_server/dakara_server/urls.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@
102102
library_views.SongView.as_view(),
103103
name="library-song",
104104
),
105+
path(
106+
"api/library/songs/lyrics/<int:pk>/",
107+
library_views.SongLyricsView.as_view(),
108+
name="library-song-lyrics",
109+
),
105110
path(
106111
"api/library/songs/retrieve/",
107112
library_views.SongRetrieveListView.as_view(),

dakara_server/internal/query_language.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ def __init__(self, keywords):
2525
|
2626
(?P<contains2>(?:\\\s|\S)+) # contains with no quotes
2727
)
28-
""".format(
29-
keywords_regex=r"|".join(self.keywords)
30-
)
28+
""".format(keywords_regex=r"|".join(self.keywords))
3129

3230
self.language_matcher = re.compile(regex, re.I | re.X)
3331

dakara_server/internal/tests/base_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def check_query(self, query, expected, remaining=None):
8585
self.assertEqual(response.data["count"], len(expected))
8686
results = response.data["results"]
8787
self.assertEqual(len(results), len(expected))
88-
for item, expected_item in zip(results, expected):
88+
for item, expected_item in zip(results, expected, strict=False):
8989
self.assertEqual(item["id"], expected_item.id)
9090

9191
if remaining is not None:

dakara_server/library/serializers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,14 @@ def update(self, song, validated_data):
403403
return song
404404

405405

406+
class SongLyricsSerializer(serializers.ModelSerializer):
407+
"""Song lyrics field serializer."""
408+
409+
class Meta:
410+
model = Song
411+
fields = ("id", "lyrics")
412+
413+
406414
class SongForPlayerSerializer(serializers.ModelSerializer):
407415
"""Song serializer.
408416

dakara_server/library/tests/base_test.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,21 @@ def check_song_json(self, json, expected_song):
8585
# tags
8686
expected_tags = expected_song.tags.all()
8787
self.assertEqual(len(json["tags"]), len(expected_tags))
88-
for tag, expected_tag in zip(json["tags"], expected_tags):
88+
for tag, expected_tag in zip(json["tags"], expected_tags, strict=False):
8989
self.check_tag_json(tag, expected_tag)
9090

9191
# artists
9292
expected_artists = expected_song.artists.all()
9393
self.assertEqual(len(json["artists"]), len(expected_artists))
94-
for artist, expected_artist in zip(json["artists"], expected_artists):
94+
for artist, expected_artist in zip(
95+
json["artists"], expected_artists, strict=False
96+
):
9597
self.check_artist_json(artist, expected_artist)
9698

9799
# works
98100
expected_works = expected_song.songworklink_set.all()
99101
self.assertEqual(len(json["works"]), len(expected_works))
100-
for work, expected_work in zip(json["works"], expected_works):
102+
for work, expected_work in zip(json["works"], expected_works, strict=False):
101103
self.check_work_json(work["work"], expected_work.work)
102104
self.assertEqual(work["link_type"], expected_work.link_type)
103105
self.assertEqual(work["link_type_number"], expected_work.link_type_number)
@@ -125,7 +127,7 @@ def check_work_json(self, json, expected_work):
125127
expected_alt_titles = expected_work.alternative_titles.all()
126128
self.assertEqual(len(json["alternative_titles"]), len(expected_alt_titles))
127129
for alt_title, expected_alt_title in zip(
128-
json["alternative_titles"], expected_alt_titles
130+
json["alternative_titles"], expected_alt_titles, strict=False
129131
):
130132
self.assertEqual(alt_title["title"], expected_alt_title.title)
131133

dakara_server/library/tests/test_song.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ def test_get_song_long_lyrics(self):
5757
self.assertEqual(len(response.data["results"]), 2)
5858

5959
# check lyrics
60+
self.assertNotEqual(
61+
response.data["results"][1]["lyrics_preview"]["text"], self.song2.lyrics
62+
)
6063
self.assertDictEqual(
6164
response.data["results"][1]["lyrics_preview"],
6265
{
@@ -962,3 +965,34 @@ def test_put_song_embedded_work_subtitle(self):
962965
self.assertEqual(Work.objects.count(), 4)
963966
workNew = Work.objects.get(title="Work1", subtitle="", work_type=self.wt1)
964967
self.assertIsNotNone(workNew)
968+
969+
970+
class SongLyricsViewTestCase(LibraryAPITestCase):
971+
def setUp(self):
972+
# create a user without any rights
973+
self.user = self.create_user("TestUser")
974+
975+
# create test data
976+
self.create_test_data()
977+
978+
# add lyrics to one song
979+
self.song2.lyrics = """Mary had a little lamb
980+
Little lamb, little lamb
981+
Mary had a little lamb
982+
Its fleece was white as snow
983+
And everywhere that Mary went
984+
Mary went, Mary."""
985+
self.song2.save()
986+
987+
# Create urls to access these playlist entries
988+
self.url_song2 = reverse("library-song-lyrics", kwargs={"pk": self.song2.id})
989+
990+
def test_get_lyrics(self):
991+
"""Get a song lyrics."""
992+
self.authenticate(self.user)
993+
994+
response = self.client.get(self.url_song2)
995+
996+
self.assertEqual(response.status_code, status.HTTP_200_OK)
997+
self.assertEqual(response.data["id"], self.song2.id)
998+
self.assertEqual(response.data["lyrics"], self.song2.lyrics)

dakara_server/library/views.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from rest_framework.generics import (
77
ListAPIView,
88
ListCreateAPIView,
9+
RetrieveAPIView,
910
RetrieveUpdateDestroyAPIView,
1011
)
1112
from rest_framework.permissions import IsAuthenticated
@@ -54,6 +55,17 @@ class SongView(RetrieveUpdateDestroyAPIView):
5455
serializer_class = serializers.SongSerializer
5556

5657

58+
class SongLyricsView(RetrieveAPIView):
59+
"""List of songs."""
60+
61+
permission_classes = [
62+
IsAuthenticated,
63+
permissions.IsLibraryManager | internal_permissions.IsReadOnly,
64+
]
65+
queryset = models.Song.objects.all()
66+
serializer_class = serializers.SongLyricsSerializer
67+
68+
5769
class SongRetrieveListView(ListAPIView):
5870
"""List of all songs.
5971

requirements.txt

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
asgiref>=3.9.1,<3.10.0 # to remove after updating channels
2-
APScheduler>=3.11.0,<3.12.0
3-
channels>=4.2.0,<4.3.0
4-
daphne>=4.1.2,<4.2.0
5-
dj-database-url>=2.3.0,<2.4.0
1+
APScheduler>=3.11.2,<3.12.0
2+
channels>=4.3.2,<4.4.0
3+
daphne>=4.2.1,<4.3.0
4+
dj-database-url>=3.1.2,<3.2.0
65
django-cache-lock>=0.2.5,<0.3.0
7-
django-filter>=25.1,<25.2
6+
django-filter>=25.2,<25.3
87
django-ordered-model>=3.7.4,<3.8.0
98
django-rest-registration>=0.9.0,<0.10.0
10-
Django>=5.1.6,<5.2.0
11-
djangorestframework>=3.15.2,<3.16.0
12-
drf-spectacular==0.28.0
13-
packaging>=24.2,<24.3
9+
Django>=5.2.12,<5.3.0
10+
djangorestframework>=3.17.1,<3.18.0
11+
drf-spectacular>=0.29.0,<0.30.0
12+
packaging>=26.0,<27.0
1413
python-decouple>=3.8,<3.9
15-
setuptools>=75.8
14+
setuptools>=82.0.1

0 commit comments

Comments
 (0)