Verified Commit 20eaa5e6 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Merge branch 'release/0.2.5'

parents 142a8050 5ac9d261
......@@ -44,7 +44,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(primary_key=True, auto_created=True, serialize=False, verbose_name='ID')),
('creation_date', models.DateTimeField(default=django.utils.timezone.now)),
('submitted_by', models.ForeignKey(related_name='imports', to=settings.AUTH_USER_MODEL)),
('submitted_by', models.ForeignKey(related_name='imports', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
),
migrations.CreateModel(
......@@ -54,7 +54,7 @@ class Migration(migrations.Migration):
('source', models.URLField()),
('mbid', models.UUIDField(editable=False)),
('status', models.CharField(default='pending', choices=[('pending', 'Pending'), ('finished', 'finished')], max_length=30)),
('batch', models.ForeignKey(related_name='jobs', to='music.ImportBatch')),
('batch', models.ForeignKey(related_name='jobs', to='music.ImportBatch', on_delete=models.CASCADE)),
],
),
migrations.CreateModel(
......@@ -64,8 +64,8 @@ class Migration(migrations.Migration):
('mbid', models.UUIDField(editable=False, blank=True, null=True)),
('creation_date', models.DateTimeField(default=django.utils.timezone.now)),
('title', models.CharField(max_length=255)),
('album', models.ForeignKey(related_name='tracks', blank=True, null=True, to='music.Album')),
('artist', models.ForeignKey(related_name='tracks', to='music.Artist')),
('album', models.ForeignKey(related_name='tracks', blank=True, null=True, to='music.Album', on_delete=models.CASCADE)),
('artist', models.ForeignKey(related_name='tracks', to='music.Artist', on_delete=models.CASCADE)),
],
options={
'abstract': False,
......@@ -78,12 +78,12 @@ class Migration(migrations.Migration):
('audio_file', models.FileField(upload_to='tracks')),
('source', models.URLField(blank=True, null=True)),
('duration', models.IntegerField(blank=True, null=True)),
('track', models.ForeignKey(related_name='files', to='music.Track')),
('track', models.ForeignKey(related_name='files', to='music.Track', on_delete=models.CASCADE)),
],
),
migrations.AddField(
model_name='album',
name='artist',
field=models.ForeignKey(related_name='albums', to='music.Artist'),
field=models.ForeignKey(related_name='albums', to='music.Artist', on_delete=models.CASCADE),
),
]
......@@ -39,11 +39,11 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='lyrics',
name='work',
field=models.ForeignKey(related_name='lyrics', to='music.Work', blank=True, null=True),
field=models.ForeignKey(related_name='lyrics', to='music.Work', blank=True, null=True, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='track',
name='work',
field=models.ForeignKey(related_name='tracks', to='music.Work', blank=True, null=True),
field=models.ForeignKey(related_name='tracks', to='music.Work', blank=True, null=True, on_delete=models.CASCADE),
),
]
......@@ -10,7 +10,7 @@ from django.conf import settings
from django.db import models
from django.core.files.base import ContentFile
from django.core.files import File
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.utils import timezone
from taggit.managers import TaggableManager
from versatileimagefield.fields import VersatileImageField
......@@ -108,7 +108,8 @@ def import_tracks(instance, cleaned_data, raw_data):
class Album(APIModelMixin):
title = models.CharField(max_length=255)
artist = models.ForeignKey(Artist, related_name='albums')
artist = models.ForeignKey(
Artist, related_name='albums', on_delete=models.CASCADE)
release_date = models.DateField(null=True)
release_group_id = models.UUIDField(null=True, blank=True)
cover = VersatileImageField(upload_to='albums/covers/%Y/%m/%d', null=True, blank=True)
......@@ -245,7 +246,12 @@ class Work(APIModelMixin):
class Lyrics(models.Model):
work = models.ForeignKey(Work, related_name='lyrics', null=True, blank=True)
work = models.ForeignKey(
Work,
related_name='lyrics',
null=True,
blank=True,
on_delete=models.CASCADE)
url = models.URLField(unique=True)
content = models.TextField(null=True, blank=True)
......@@ -268,10 +274,21 @@ class Lyrics(models.Model):
class Track(APIModelMixin):
title = models.CharField(max_length=255)
artist = models.ForeignKey(Artist, related_name='tracks')
artist = models.ForeignKey(
Artist, related_name='tracks', on_delete=models.CASCADE)
position = models.PositiveIntegerField(null=True, blank=True)
album = models.ForeignKey(Album, related_name='tracks', null=True, blank=True)
work = models.ForeignKey(Work, related_name='tracks', null=True, blank=True)
album = models.ForeignKey(
Album,
related_name='tracks',
null=True,
blank=True,
on_delete=models.CASCADE)
work = models.ForeignKey(
Work,
related_name='tracks',
null=True,
blank=True,
on_delete=models.CASCADE)
musicbrainz_model = 'recording'
api = musicbrainz.api.recordings
......@@ -340,7 +357,8 @@ class Track(APIModelMixin):
class TrackFile(models.Model):
track = models.ForeignKey(Track, related_name='files')
track = models.ForeignKey(
Track, related_name='files', on_delete=models.CASCADE)
audio_file = models.FileField(upload_to='tracks/%Y/%m/%d', max_length=255)
source = models.URLField(null=True, blank=True)
duration = models.IntegerField(null=True, blank=True)
......@@ -376,7 +394,8 @@ class TrackFile(models.Model):
class ImportBatch(models.Model):
creation_date = models.DateTimeField(default=timezone.now)
submitted_by = models.ForeignKey('users.User', related_name='imports')
submitted_by = models.ForeignKey(
'users.User', related_name='imports', on_delete=models.CASCADE)
class Meta:
ordering = ['-creation_date']
......@@ -392,9 +411,14 @@ class ImportBatch(models.Model):
return 'finished'
class ImportJob(models.Model):
batch = models.ForeignKey(ImportBatch, related_name='jobs')
batch = models.ForeignKey(
ImportBatch, related_name='jobs', on_delete=models.CASCADE)
track_file = models.ForeignKey(
TrackFile, related_name='jobs', null=True, blank=True)
TrackFile,
related_name='jobs',
null=True,
blank=True,
on_delete=models.CASCADE)
source = models.URLField()
mbid = models.UUIDField(editable=False)
STATUS_CHOICES = (
......
......@@ -59,3 +59,30 @@ class ImportJobFactory(factory.django.DjangoModelFactory):
class Meta:
model = 'music.ImportJob'
class WorkFactory(factory.django.DjangoModelFactory):
mbid = factory.Faker('uuid4')
language = 'eng'
nature = 'song'
title = factory.Faker('sentence', nb_words=3)
class Meta:
model = 'music.Work'
class LyricsFactory(factory.django.DjangoModelFactory):
work = factory.SubFactory(WorkFactory)
url = factory.Faker('url')
content = factory.Faker('paragraphs', nb=4)
class Meta:
model = 'music.Lyrics'
class TagFactory(factory.django.DjangoModelFactory):
name = factory.SelfAttribute('slug')
slug = factory.Faker('slug')
class Meta:
model = 'taggit.Tag'
import json
import unittest
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from django.urls import reverse
from funkwhale_api.music import models
from funkwhale_api.utils.tests import TMPDirTestCaseMixin
......
import json
import unittest
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from model_mommy import mommy
from django.urls import reverse
from funkwhale_api.music import models
from funkwhale_api.musicbrainz import api
from funkwhale_api.music import serializers
from funkwhale_api.users.models import User
from funkwhale_api.music import lyrics as lyrics_utils
from .mocking import lyricswiki
from . import factories
from . import data as api_data
from funkwhale_api.music import lyrics as lyrics_utils
class TestLyrics(TestCase):
@unittest.mock.patch('funkwhale_api.music.lyrics._get_html',
return_value=lyricswiki.content)
def test_works_import_lyrics_if_any(self, *mocks):
lyrics = mommy.make(
models.Lyrics,
lyrics = factories.LyricsFactory(
url='http://lyrics.wikia.com/System_Of_A_Down:Chop_Suey!')
lyrics.fetch_content()
......@@ -42,7 +43,7 @@ Is it me you're looking for?
content = """Hello
Is it me you're looking for?"""
l = mommy.make(models.Lyrics, content=content)
l = factories.LyricsFactory(content=content)
expected = "<p>Hello<br />Is it me you're looking for?</p>"
self.assertHTMLEqual(expected, l.content_rendered)
......@@ -54,8 +55,7 @@ Is it me you're looking for?"""
@unittest.mock.patch('funkwhale_api.music.lyrics._get_html',
return_value=lyricswiki.content)
def test_works_import_lyrics_if_any(self, *mocks):
track = mommy.make(
models.Track,
track = factories.TrackFactory(
work=None,
mbid='07ca77cf-f513-4e9c-b190-d7e24bbad448')
......
......@@ -2,13 +2,11 @@ from test_plus.test import TestCase
import unittest.mock
from funkwhale_api.music import models
import datetime
from model_mommy import mommy
from . import factories
from . import data as api_data
from .cover import binary_data
def prettyprint(d):
import json
print(json.dumps(d, sort_keys=True, indent=4))
class TestMusic(TestCase):
......@@ -79,9 +77,9 @@ class TestMusic(TestCase):
self.assertEqual(track, track2)
def test_album_tags_deduced_from_tracks_tags(self):
tag = mommy.make('taggit.Tag')
album = mommy.make('music.Album')
tracks = mommy.make('music.Track', album=album, _quantity=5)
tag = factories.TagFactory()
album = factories.AlbumFactory()
tracks = factories.TrackFactory.create_batch(album=album, size=5)
for track in tracks:
track.tags.add(tag)
......@@ -92,10 +90,10 @@ class TestMusic(TestCase):
self.assertIn(tag, album.tags)
def test_artist_tags_deduced_from_album_tags(self):
tag = mommy.make('taggit.Tag')
artist = mommy.make('music.Artist')
album = mommy.make('music.Album', artist=artist)
tracks = mommy.make('music.Track', album=album, _quantity=5)
tag = factories.TagFactory()
artist = factories.ArtistFactory()
album = factories.AlbumFactory(artist=artist)
tracks = factories.TrackFactory.create_batch(album=album, size=5)
for track in tracks:
track.tags.add(tag)
......@@ -108,7 +106,7 @@ class TestMusic(TestCase):
@unittest.mock.patch('funkwhale_api.musicbrainz.api.images.get_front', return_value=binary_data)
def test_can_download_image_file_for_album(self, *mocks):
# client._api.get_image_front('55ea4f82-b42b-423e-a0e5-290ccdf443ed')
album = mommy.make('music.Album', mbid='55ea4f82-b42b-423e-a0e5-290ccdf443ed')
album = factories.AlbumFactory(mbid='55ea4f82-b42b-423e-a0e5-290ccdf443ed')
album.get_image()
album.save()
......
import json
import unittest
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from model_mommy import mommy
from django.urls import reverse
from funkwhale_api.music import models
from funkwhale_api.musicbrainz import api
from funkwhale_api.music import serializers
from funkwhale_api.music.tests import factories
from funkwhale_api.users.models import User
from . import data as api_data
class TestWorks(TestCase):
@unittest.mock.patch('funkwhale_api.musicbrainz.api.works.get',
return_value=api_data.works['get']['chop_suey'])
def test_can_import_work(self, *mocks):
recording = mommy.make(
models.Track, mbid='07ca77cf-f513-4e9c-b190-d7e24bbad448')
recording = factories.TrackFactory(
mbid='07ca77cf-f513-4e9c-b190-d7e24bbad448')
mbid = 'e2ecabc4-1b9d-30b2-8f30-3596ec423dc5'
work = models.Work.create_from_api(id=mbid)
......@@ -36,8 +37,7 @@ class TestWorks(TestCase):
@unittest.mock.patch('funkwhale_api.musicbrainz.api.recordings.get',
return_value=api_data.tracks['get']['chop_suey'])
def test_can_get_work_from_recording(self, *mocks):
recording = mommy.make(
models.Track,
recording = factories.TrackFactory(
work=None,
mbid='07ca77cf-f513-4e9c-b190-d7e24bbad448')
mbid = 'e2ecabc4-1b9d-30b2-8f30-3596ec423dc5'
......
......@@ -2,7 +2,7 @@ import os
import json
import unicodedata
import urllib
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db import models, transaction
from django.db.models.functions import Length
from django.conf import settings
......@@ -102,7 +102,7 @@ class TrackViewSet(TagViewSetMixin, SearchMixin, viewsets.ReadOnlyModelViewSet):
queryset = super().get_queryset()
filter_favorites = self.request.GET.get('favorites', None)
user = self.request.user
if user.is_authenticated() and filter_favorites == 'true':
if user.is_authenticated and filter_favorites == 'true':
queryset = queryset.filter(track_favorites__user=user)
return queryset
......
import json
import unittest
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from django.urls import reverse
from funkwhale_api.musicbrainz import api
from . import data as api_data
......
......@@ -22,7 +22,7 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=50)),
('is_public', models.BooleanField(default=False)),
('creation_date', models.DateTimeField(default=django.utils.timezone.now)),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='playlists')),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='playlists', on_delete=models.CASCADE)),
],
),
migrations.CreateModel(
......@@ -33,9 +33,9 @@ class Migration(migrations.Migration):
('rght', models.PositiveIntegerField(db_index=True, editable=False)),
('tree_id', models.PositiveIntegerField(db_index=True, editable=False)),
('position', models.PositiveIntegerField(db_index=True, editable=False)),
('playlist', models.ForeignKey(to='playlists.Playlist', related_name='playlist_tracks')),
('previous', mptt.fields.TreeOneToOneField(null=True, to='playlists.PlaylistTrack', related_name='next', blank=True)),
('track', models.ForeignKey(to='music.Track', related_name='playlist_tracks')),
('playlist', models.ForeignKey(to='playlists.Playlist', related_name='playlist_tracks', on_delete=models.CASCADE)),
('previous', mptt.fields.TreeOneToOneField(null=True, to='playlists.PlaylistTrack', related_name='next', blank=True, on_delete=models.CASCADE)),
('track', models.ForeignKey(to='music.Track', related_name='playlist_tracks', on_delete=models.CASCADE)),
],
options={
'ordering': ('-playlist', 'position'),
......
......@@ -7,7 +7,8 @@ from mptt.models import MPTTModel, TreeOneToOneField
class Playlist(models.Model):
name = models.CharField(max_length=50)
is_public = models.BooleanField(default=False)
user = models.ForeignKey('users.User', related_name="playlists")
user = models.ForeignKey(
'users.User', related_name="playlists", on_delete=models.CASCADE)
creation_date = models.DateTimeField(default=timezone.now)
def __str__(self):
......@@ -21,9 +22,18 @@ class Playlist(models.Model):
class PlaylistTrack(MPTTModel):
track = models.ForeignKey('music.Track', related_name='playlist_tracks')
previous = TreeOneToOneField('self', blank=True, null=True, related_name='next')
playlist = models.ForeignKey(Playlist, related_name='playlist_tracks')
track = models.ForeignKey(
'music.Track',
related_name='playlist_tracks',
on_delete=models.CASCADE)
previous = TreeOneToOneField(
'self',
blank=True,
null=True,
related_name='next',
on_delete=models.CASCADE)
playlist = models.ForeignKey(
Playlist, related_name='playlist_tracks', on_delete=models.CASCADE)
class MPTTMeta:
level_attr = 'position'
......
import json
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.core.exceptions import ValidationError
from django.utils import timezone
from model_mommy import mommy
from funkwhale_api.music.tests import factories
from funkwhale_api.users.models import User
from funkwhale_api.playlists import models
from funkwhale_api.playlists.serializers import PlaylistSerializer
......@@ -18,7 +17,7 @@ class TestPlayLists(TestCase):
self.user = User.objects.create_user(username='test', email='test@test.com', password='test')
def test_can_create_playlist(self):
tracks = list(mommy.make('music.Track', _quantity=5))
tracks = factories.TrackFactory.create_batch(size=5)
playlist = models.Playlist.objects.create(user=self.user, name="test")
previous = None
......@@ -49,7 +48,7 @@ class TestPlayLists(TestCase):
self.assertEqual(playlist.name, 'test')
def test_can_add_playlist_track_via_api(self):
tracks = list(mommy.make('music.Track', _quantity=5))
tracks = factories.TrackFactory.create_batch(size=5)
playlist = models.Playlist.objects.create(user=self.user, name="test")
self.client.login(username=self.user.username, password='test')
......
from django.conf.urls import include, url
from funkwhale_api.music import views
urlpatterns = [
url(r'^youtube/', include('funkwhale_api.providers.youtube.urls', namespace='youtube')),
url(r'^musicbrainz/', include('funkwhale_api.musicbrainz.urls', namespace='musicbrainz')),
url(r'^youtube/', include(
('funkwhale_api.providers.youtube.urls', 'youtube'),
namespace='youtube')),
url(r'^musicbrainz/', include(
('funkwhale_api.musicbrainz.urls', 'musicbrainz'),
namespace='musicbrainz')),
]
......@@ -2,7 +2,7 @@ import json
from collections import OrderedDict
import unittest
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from django.urls import reverse
from funkwhale_api.providers.youtube.client import client
from . import data as api_data
......
......@@ -20,7 +20,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
('radio_type', models.CharField(max_length=50)),
('creation_date', models.DateTimeField(default=django.utils.timezone.now)),
('user', models.ForeignKey(related_name='radio_sessions', blank=True, to=settings.AUTH_USER_MODEL, null=True)),
('user', models.ForeignKey(related_name='radio_sessions', blank=True, to=settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)),
],
),
migrations.CreateModel(
......@@ -28,8 +28,8 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
('position', models.IntegerField(default=1)),
('session', models.ForeignKey(to='radios.RadioSession', related_name='session_tracks')),
('track', models.ForeignKey(to='music.Track', related_name='radio_session_tracks')),
('session', models.ForeignKey(to='radios.RadioSession', related_name='session_tracks', on_delete=models.CASCADE)),
('track', models.ForeignKey(to='music.Track', related_name='radio_session_tracks', on_delete=models.CASCADE)),
],
options={
'ordering': ('session', 'position'),
......
......@@ -15,7 +15,7 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='radiosession',
name='related_object_content_type',
field=models.ForeignKey(null=True, to='contenttypes.ContentType', blank=True),
field=models.ForeignKey(null=True, to='contenttypes.ContentType', blank=True, on_delete=models.CASCADE),
),
migrations.AddField(
model_name='radiosession',
......
......@@ -7,11 +7,20 @@ from django.contrib.contenttypes.models import ContentType
from funkwhale_api.music.models import Track
class RadioSession(models.Model):
user = models.ForeignKey('users.User', related_name='radio_sessions', null=True, blank=True)
user = models.ForeignKey(
'users.User',
related_name='radio_sessions',
null=True,
blank=True,
on_delete=models.CASCADE)
session_key = models.CharField(max_length=100, null=True, blank=True)
radio_type = models.CharField(max_length=50)
creation_date = models.DateTimeField(default=timezone.now)
related_object_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True)
related_object_content_type = models.ForeignKey(
ContentType,
blank=True,
null=True,
on_delete=models.CASCADE)
related_object_id = models.PositiveIntegerField(blank=True, null=True)
related_object = GenericForeignKey('related_object_content_type', 'related_object_id')
......@@ -43,9 +52,11 @@ class RadioSession(models.Model):
return registry[self.radio_type](session=self)
class RadioSessionTrack(models.Model):
session = models.ForeignKey(RadioSession, related_name='session_tracks')
session = models.ForeignKey(
RadioSession, related_name='session_tracks', on_delete=models.CASCADE)
position = models.IntegerField(default=1)
track = models.ForeignKey(Track, related_name='radio_session_tracks')
track = models.ForeignKey(
Track, related_name='radio_session_tracks', on_delete=models.CASCADE)
class Meta:
ordering = ('session', 'position')
......
import random
import json
from test_plus.test import TestCase
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.core.exceptions import ValidationError
from model_mommy import mommy
from funkwhale_api.radios import radios
from funkwhale_api.radios import models
from funkwhale_api.favorites.models import TrackFavorite
from funkwhale_api.users.models import User
from funkwhale_api.music.models import Artist
from funkwhale_api.music.tests import factories
from funkwhale_api.history.tests.factories import ListeningFactory
class TestRadios(TestCase):
......@@ -55,7 +57,7 @@ class TestRadios(TestCase):
self.assertTrue(picks[2] > picks[1])
def test_can_get_choices_for_favorites_radio(self):
tracks = mommy.make('music.Track', _quantity=100)
tracks = factories.TrackFactory.create_batch(size=100)
for i in range(20):
TrackFavorite.add(track=random.choice(tracks), user=self.user)
......@@ -73,7 +75,7 @@ class TestRadios(TestCase):
self.assertIn(pick, choices)
def test_can_use_radio_session_to_filter_choices(self):
tracks = mommy.make('music.Track', _quantity=30)
tracks = factories.TrackFactory.create_batch(size=30)