mirror of
https://github.com/bspeice/Melodia
synced 2024-12-26 00:28:13 -05:00
Various bugfixes, add test case for playlists
This commit is contained in:
parent
811fdc652d
commit
870efac03f
@ -81,12 +81,11 @@ class Archive (models.Model):
|
|||||||
#This method operates only on the songs that are in the database - if you need to make
|
#This method operates only on the songs that are in the database - if you need to make
|
||||||
#sure that new songs are added, use the _scan_filesystem() method in addition
|
#sure that new songs are added, use the _scan_filesystem() method in addition
|
||||||
total_songs = self.songs.count()
|
total_songs = self.songs.count()
|
||||||
current_song = 0
|
|
||||||
|
|
||||||
for song in self.songs.all():
|
for index, song in enumerate(self.songs.all()):
|
||||||
current_song += 1
|
|
||||||
song.populate_metadata(use_echonest = use_echonest)
|
song.populate_metadata(use_echonest = use_echonest)
|
||||||
progress_callback(current_song, total_songs)
|
song.save()
|
||||||
|
progress_callback(index + 1, total_songs)
|
||||||
|
|
||||||
def _needs_backup(self):
|
def _needs_backup(self):
|
||||||
"Check if the current archive is due for a backup"
|
"Check if the current archive is due for a backup"
|
||||||
@ -129,7 +128,7 @@ class Archive (models.Model):
|
|||||||
import subprocess
|
import subprocess
|
||||||
subprocess.call(['rsync', '-av', self.root_folder, self.backup_location])
|
subprocess.call(['rsync', '-av', self.root_folder, self.backup_location])
|
||||||
|
|
||||||
def reorganize(self, format_string, progress_function = lambda x, y: None, song_status_function = lambda x, y: None, dry_run = False):
|
def reorganize(self, format_string, progress_function = lambda w, x, y, z: None, dry_run = False):
|
||||||
"""Reorganize a music archive using a specified format string.
|
"""Reorganize a music archive using a specified format string.
|
||||||
Recognized escape characters:
|
Recognized escape characters:
|
||||||
%a - Artist Name %A - Album Name
|
%a - Artist Name %A - Album Name
|
||||||
@ -139,11 +138,14 @@ class Archive (models.Model):
|
|||||||
%y - Album year
|
%y - Album year
|
||||||
|
|
||||||
Note that all organization takes place relative to the archive's root folder.
|
Note that all organization takes place relative to the archive's root folder.
|
||||||
The progress_function is called with the current song number as its first argument, and total songs as its second.
|
The progress_function is called with the current song number as its first argument, total songs as its second,
|
||||||
The song_status_function is called with the current song url as its first argument, and new url as its second."""
|
current song URL as the third argument, and new URL as the fourth.
|
||||||
|
"""
|
||||||
import os, shutil, errno
|
import os, shutil, errno
|
||||||
|
|
||||||
for song in self.songs.all():
|
total_songs = self.songs.count()
|
||||||
|
|
||||||
|
for index, song in enumerate(self.songs.all()):
|
||||||
_current_filename = os.path.basename(song.url)
|
_current_filename = os.path.basename(song.url)
|
||||||
_current_filename_no_extension = os.path.splitext(_current_filename)[0]
|
_current_filename_no_extension = os.path.splitext(_current_filename)[0]
|
||||||
|
|
||||||
@ -161,7 +163,7 @@ class Archive (models.Model):
|
|||||||
|
|
||||||
new_url = os.path.join(self.root_folder, new_location)
|
new_url = os.path.join(self.root_folder, new_location)
|
||||||
|
|
||||||
song_status_function(song.url, new_url)
|
progress_function(index + 1, total_songs, song.url, new_url)
|
||||||
|
|
||||||
if not dry_run:
|
if not dry_run:
|
||||||
new_folder = os.path.dirname(new_url)
|
new_folder = os.path.dirname(new_url)
|
||||||
|
@ -68,7 +68,7 @@ class Playlist (models.Model):
|
|||||||
|
|
||||||
self.song_list.insert(position, new_song.id)
|
self.song_list.insert(position, new_song.id)
|
||||||
|
|
||||||
_populate_songs()
|
self._populate_songs()
|
||||||
|
|
||||||
def append(self, new_song):
|
def append(self, new_song):
|
||||||
"""
|
"""
|
||||||
@ -82,7 +82,7 @@ class Playlist (models.Model):
|
|||||||
|
|
||||||
self.song_list.append(new_song.id)
|
self.song_list.append(new_song.id)
|
||||||
|
|
||||||
_populate_songs()
|
self._populate_songs()
|
||||||
|
|
||||||
def move(self, original_position, new_position):
|
def move(self, original_position, new_position):
|
||||||
"""
|
"""
|
||||||
@ -103,7 +103,7 @@ class Playlist (models.Model):
|
|||||||
del self.song_list[original_position]
|
del self.song_list[original_position]
|
||||||
self.song_list.insert(new_position - 1, song_id) #Account for the list indices shifting down.
|
self.song_list.insert(new_position - 1, song_id) #Account for the list indices shifting down.
|
||||||
|
|
||||||
_populate_songs()
|
self._populate_songs()
|
||||||
|
|
||||||
def remove(self, position):
|
def remove(self, position):
|
||||||
if position > len(self.song_list):
|
if position > len(self.song_list):
|
||||||
@ -111,7 +111,7 @@ class Playlist (models.Model):
|
|||||||
|
|
||||||
del self.song_list[position]
|
del self.song_list[position]
|
||||||
|
|
||||||
_populate_songs()
|
self._populate_songs()
|
||||||
|
|
||||||
def export(self, playlist_type = "m3u"):
|
def export(self, playlist_type = "m3u"):
|
||||||
"""
|
"""
|
||||||
@ -135,7 +135,7 @@ class Playlist (models.Model):
|
|||||||
|
|
||||||
playlist_string += "File" + str(index + 1) + "=" + song.url + "\n"
|
playlist_string += "File" + str(index + 1) + "=" + song.url + "\n"
|
||||||
playlist_string += "Title" + str(index + 1) + "=" + song.title + "\n"
|
playlist_string += "Title" + str(index + 1) + "=" + song.title + "\n"
|
||||||
playlist_string += "Length" + str(index + 1) + "=" + song.duration + "\n"
|
playlist_string += "Length" + str(index + 1) + "=" + str(song.duration) + "\n"
|
||||||
|
|
||||||
#Playlist footer
|
#Playlist footer
|
||||||
playlist_string += "NumberOfEntries=" + str(len(self.song_list))
|
playlist_string += "NumberOfEntries=" + str(len(self.song_list))
|
||||||
@ -151,15 +151,19 @@ class Playlist (models.Model):
|
|||||||
for song_id in self.song_list:
|
for song_id in self.song_list:
|
||||||
song = self.songs.get(id = song_id)
|
song = self.songs.get(id = song_id)
|
||||||
|
|
||||||
playlist_string += "#EXTINF:" + song.duration + "," + song.artist + " - " + song.title + "\n"
|
playlist_string += "#EXTINF:" + str(song.duration) + "," + song.artist + " - " + song.title + "\n"
|
||||||
playlist_string += song.url + "\n"
|
playlist_string += song.url + "\n"
|
||||||
|
|
||||||
#Playlist footer
|
#Playlist footer
|
||||||
|
|
||||||
|
return playlist_string
|
||||||
|
|
||||||
def _import(self, playlist_string = None):
|
def _import(self, playlist_string = None):
|
||||||
"""
|
"""
|
||||||
Import and convert a playlist into native DB format.
|
Import and convert a playlist into native DB format.
|
||||||
As a side note - the _import() name is used since python doesn't let
|
As a side note - the _import() name is used since python doesn't let
|
||||||
you name a function import().
|
you name a function import().
|
||||||
"""
|
"""
|
||||||
pass
|
if not playlist_string:
|
||||||
|
#Make sure we have a string to operate on.
|
||||||
|
return False
|
||||||
|
@ -22,6 +22,8 @@ class FilesystemScanTest(TestCase):
|
|||||||
|
|
||||||
new_archive.quick_scan()
|
new_archive.quick_scan()
|
||||||
|
|
||||||
|
new_archive.save()
|
||||||
|
|
||||||
class ScanTest(TestCase):
|
class ScanTest(TestCase):
|
||||||
def test_archive_scan(self):
|
def test_archive_scan(self):
|
||||||
"Tests that we can scan an archive correctly."
|
"Tests that we can scan an archive correctly."
|
||||||
@ -34,12 +36,12 @@ class ScanTest(TestCase):
|
|||||||
|
|
||||||
#We must save the archive before we can start adding songs to it
|
#We must save the archive before we can start adding songs to it
|
||||||
new_archive.save()
|
new_archive.save()
|
||||||
|
|
||||||
new_archive.scan()
|
new_archive.scan()
|
||||||
|
new_archive.save()
|
||||||
|
|
||||||
class DeepScanTest(TestCase):
|
class DeepScanTest(TestCase):
|
||||||
def test_archive_deep_scan(self):
|
def test_archive_deep_scan(self):
|
||||||
"Tests that we can deep scan an archive correctly."
|
"Tests that we can deep scan an archive correctly. This is currently broken, as EchoNest support does not exist."
|
||||||
import os
|
import os
|
||||||
from archiver.archive import Archive
|
from archiver.archive import Archive
|
||||||
from Melodia.settings import PROJECT_FOLDER
|
from Melodia.settings import PROJECT_FOLDER
|
||||||
@ -49,5 +51,38 @@ class DeepScanTest(TestCase):
|
|||||||
|
|
||||||
#We must save the archive before we can start adding songs to it
|
#We must save the archive before we can start adding songs to it
|
||||||
new_archive.save()
|
new_archive.save()
|
||||||
|
|
||||||
new_archive.deep_scan()
|
new_archive.deep_scan()
|
||||||
|
new_archive.save()
|
||||||
|
|
||||||
|
class PlaylistExportTest(TestCase):
|
||||||
|
def test_playlist_export(self):
|
||||||
|
"Tests that we can export a playlist."
|
||||||
|
from archiver.archive import Archive
|
||||||
|
from archiver.playlist import Playlist
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
#- Re-using code from the scan to set up our archive.
|
||||||
|
import os
|
||||||
|
from archiver.archive import Archive
|
||||||
|
from Melodia.settings import PROJECT_FOLDER
|
||||||
|
|
||||||
|
TEST_DATA_FOLDER = os.path.join(PROJECT_FOLDER, "test_data")
|
||||||
|
new_archive = Archive(root_folder = TEST_DATA_FOLDER)
|
||||||
|
|
||||||
|
#We must save the archive before we can start adding songs to it
|
||||||
|
new_archive.save()
|
||||||
|
new_archive.scan()
|
||||||
|
new_archive.save()
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#Resume playlist testing code
|
||||||
|
a_playlist = Playlist()
|
||||||
|
a_playlist.name = "Testing..."
|
||||||
|
a_playlist.save()
|
||||||
|
|
||||||
|
for song in new_archive.songs.all():
|
||||||
|
a_playlist.append(song)
|
||||||
|
|
||||||
|
a_playlist.save()
|
||||||
|
|
||||||
|
playlist_string = a_playlist.export()
|
||||||
|
Loading…
Reference in New Issue
Block a user