mirror of
				https://github.com/bspeice/Melodia
				synced 2025-11-04 02:10:42 -05:00 
			
		
		
		
	Various bugfixes, add test case for playlists
This commit is contained in:
		@ -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()
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user