def get_library_contents(self): # Sequence of dicts contanining the metadata for all the songs. library = [] # Dict mapping keys to the original filenames. self.file_list = {} next_index = 0 try: for line in open(self.pls_file): # Ignore lines in the pls file starting with '#'. if line.startswith('#'): continue # only read lines starting with 'File' if line.startswith('File'): try: # Parse the filename from the line. filename = line.rstrip('\r\n')[line.index("=") + 1:] except ValueError: print "Warning: malformed line in playlist file: " + \ line.strip() continue try: metadata = extract_metadata(os.path.abspath(filename)) except ValueError: continue metadata['key'] = next_index self.file_list[next_index] = filename library.append(metadata) next_index = next_index + 1 return library except IOError: print "Error: could not read the specified playlist (%r)" \ % (self.pls_file,) sys.exit(1)
def test_with_metadata(self): tagpy = FakeTagpy(TagData(artist="Beatles", title="Ticket to Ride", album="Help!")) metadata = backends.extract_metadata("/dev/null", tagpy) self.assertEqual("Ticket to Ride", metadata[backends.TITLE]) self.assertEqual("Beatles", metadata[backends.ARTIST]) self.assertEqual("Help!", metadata[backends.ALBUM])
def test_with_metadata(self): tagpy = FakeTagpy(TagData(artist="Beatles", title="Ticket to Ride", album="Help!")) metadata = backends.extract_metadata("/dev/null", tagpy) self.assertEqual("Ticket to Ride", metadata[backends.TITLE]) self.assertEqual("Beatles", metadata[backends.ARTIST]) self.assertEqual("Help!", metadata[backends.ALBUM])
def get_library_contents(self): # Sequence of dicts contanining the metadata for all the songs. library = [] # Dict mapping keys to the original filenames. self.file_list = {} next_index = 0 try: for line in open(self.m3u_file): # Ignore lines in the m3u file starting with '#'. if line.startswith('#'): continue filename = line.rstrip('\r\n') try: metadata = extract_metadata(os.path.abspath(filename)) except ValueError: continue metadata['key'] = next_index self.file_list[next_index] = filename library.append(metadata) next_index = next_index + 1 return library except IOError: print "Error: could not read the specified playlist (%r)" \ % (self.m3u_file,) sys.exit(1)
def get_library_contents(self): # Sequence of dicts contanining the metadata for all the songs. library = [] # Dict mapping keys to the original filenames. self.file_list = {} next_index = 0 try: for line in open(self.m3u_file): # Ignore lines in the m3u file starting with '#'. if line.startswith('#'): continue filename = line.rstrip('\r\n') try: metadata = extract_metadata(os.path.abspath(filename)) except ValueError: continue metadata['key'] = next_index self.file_list[next_index] = filename library.append(metadata) next_index = next_index + 1 return library except IOError: print "Error: could not read the specified playlist (%r)" \ % (self.m3u_file,) sys.exit(1)
def fill_db(self, previous_db): """ Populate the database, given the output of load_previous_db. """ # By default, os.walk will happily accept a non-existent directory and # return an empty sequence. Detect the case of a non-existent path and # bail out early. if not os.path.exists(self._media_path): raise IOError("Error: directory %r doesn't exist." % (self._media_path, )) print "Scanning for music in %r..." % (os.path.abspath( self._media_path), ) # Iterate over all the files. for path, dirs, files in os.walk(self._media_path, followlinks=True): # Sort dirs so that subdirectories will subsequently be visited # alphabetically (see os.walk). dirs.sort(key=tokenize_filename) for filename in sorted(files, key=tokenize_filename): filename = os.path.abspath(os.path.join(path, filename)) # For each file that we encounter, see if we have cached data # for it, and if we do, use it instead of calling out to tagpy. # previous_db acts as a cache of mtime and metadata, keyed by # filename. rec_mtime, old_metadata = previous_db.get( filename, (None, None)) try: file_mtime = os.stat(filename).st_mtime except OSError: continue # Set the artist, title, and album in this block, and the key # below. if rec_mtime is not None and rec_mtime >= file_mtime: # Use cached data. However, we potentially renumber the # keys every time, so the old KEY is no good. We'll update # the KEY field later. metadata = old_metadata else: # In this branch, we actually need to read the file and # extract its metadata. try: metadata = extract_metadata(filename) except ValueError: # If there was any exception, then ignore the file and # continue. continue # Number the keys consecutively starting from 0. next_key = len(self.key_filename) metadata[KEY] = next_key self.db.append(metadata) self.key_filename[next_key] = filename self.mtimes[filename] = file_mtime
def fill_db(self, previous_db): """ Populate the database, given the output of load_previous_db. """ # By default, os.walk will happily accept a non-existent directory and # return an empty sequence. Detect the case of a non-existent path and # bail out early. if not os.path.exists(self._media_path): raise IOError("Error: directory %r doesn't exist." % (self._media_path,)) print "Scanning for music in %r..." % (os.path.abspath(self._media_path),) # Iterate over all the files. for path, dirs, files in os.walk(self._media_path, followlinks=True): # Sort dirs so that subdirectories will subsequently be visited # alphabetically (see os.walk). dirs.sort(key=tokenize_filename) for filename in sorted(files, key=tokenize_filename): filename = os.path.abspath(os.path.join(path, filename)) # For each file that we encounter, see if we have cached data # for it, and if we do, use it instead of calling out to tagpy. # previous_db acts as a cache of mtime and metadata, keyed by # filename. rec_mtime, old_metadata = previous_db.get(filename, (None, None)) try: file_mtime = os.stat(filename).st_mtime except OSError: continue # Set the artist, title, and album in this block, and the key # below. if rec_mtime is not None and rec_mtime >= file_mtime: # Use cached data. However, we potentially renumber the # keys every time, so the old KEY is no good. We'll update # the KEY field later. metadata = old_metadata else: # In this branch, we actually need to read the file and # extract its metadata. try: metadata = extract_metadata(filename) except ValueError: # If there was any exception, then ignore the file and # continue. continue # Number the keys consecutively starting from 0. next_key = len(self.key_filename) metadata[KEY] = next_key self.db.append(metadata) self.key_filename[next_key] = filename self.mtimes[filename] = file_mtime
def write_metadata(self, filename, previous_db): """ Obtains and writes the metadata for the specified FILENAME to the database. The metadata may be found by looking in the cache (PREVIOUS_DB), and failing that, by pulling the metadata from the file itself. Returns the key associated with the filename. """ if filename in self.filename_key: # First, if the filename is already in our database, we don't have # to do anything. We can encounter the same filename twice if a # playlist contains a reference to a file we've already scanned. key = self.filename_key[filename] else: # The filename is not in the database. We have to obtain a metadata # entry, either by reading it out of our cache, or by calling out # to tagpy. # # previous_db acts as a cache of mtime and metadata, keyed by # filename. rec_mtime, old_metadata = previous_db.get(filename, (None, None)) if u'\0' in filename: # This can happen when the playlist files are malformed; # detect this condition here because stat below gives an # unenlightening error message. raise ValueError('Encountered invalid filename: %r' % (filename,)) file_mtime = os.stat(filename).st_mtime if rec_mtime is not None and rec_mtime >= file_mtime: # Use cached data. However, we potentially renumber the keys # every time the program runs, so the old KEY is no good. We'll # fix up the KEY field below. metadata = old_metadata else: # In this branch, we actually need to read the file and # extract its metadata. metadata = extract_metadata(filename) # Assign a key for this song. These are just integers assigned # sequentially. key = len(self.key_filename) metadata[KEY] = key self.db.append(metadata) self.key_filename[key] = filename self.filename_key[filename] = key self.mtimes[filename] = file_mtime return key
def write_metadata(self, filename, previous_db): """ Obtains and writes the metadata for the specified FILENAME to the database. The metadata may be found by looking in the cache (PREVIOUS_DB), and failing that, by pulling the metadata from the file itself. Returns the key associated with the filename. """ if filename in self.filename_key: # First, if the filename is already in our database, we don't have # to do anything. We can encounter the same filename twice if a # playlist contains a reference to a file we've already scanned. key = self.filename_key[filename] else: # The filename is not in the database. We have to obtain a metadata # entry, either by reading it out of our cache, or by calling out # to tagpy. # # previous_db acts as a cache of mtime and metadata, keyed by # filename. rec_mtime, old_metadata = previous_db.get(filename, (None, None)) file_mtime = os.stat(filename).st_mtime if rec_mtime is not None and rec_mtime >= file_mtime: # Use cached data. However, we potentially renumber the keys # every time the program runs, so the old KEY is no good. We'll # fix up the KEY field below. metadata = old_metadata else: # In this branch, we actually need to read the file and # extract its metadata. metadata = extract_metadata(filename) # Assign a key for this song. These are just integers assigned # sequentially. key = len(self.key_filename) metadata[KEY] = key self.db.append(metadata) self.key_filename[key] = filename self.filename_key[filename] = key self.mtimes[filename] = file_mtime return key
def get_library_contents(self): # Sequence of dicts containing the metadata for all the songs. library = [] # Dict mapping keys to the original filenames. self.file_list = {} next_index = 0 try: playlist = M3uPlaylist(self.m3u_file, open(self.m3u_file)) for filename in playlist.get_filenames(): try: metadata = extract_metadata(os.path.abspath(filename)) except ValueError: continue metadata['key'] = next_index self.file_list[next_index] = filename library.append(metadata) next_index = next_index + 1 return library except IOError: print "Error: could not read the specified playlist (%r)" \ % (self.m3u_file,) sys.exit(1)
def get_library_contents(self): # Sequence of dicts containing the metadata for all the songs. library = [] # Dict mapping keys to the original filenames. self.file_list = {} next_index = 0 try: playlist = PlsPlaylist(self.pls_file, open(self.pls_file)) for filename in playlist.get_filenames(): try: metadata = extract_metadata(os.path.abspath(filename)) except ValueError: continue metadata['key'] = next_index self.file_list[next_index] = filename library.append(metadata) next_index = next_index + 1 return library except IOError: print "Error: could not read the specified playlist (%r)" \ % (self.pls_file,) sys.exit(1)
def test_without_metadata(self): tagpy = FakeTagpy(None) metadata = backends.extract_metadata("/the/path/to/Song.flac", tagpy) self.assertEqual("Song.flac", metadata[backends.TITLE]) self.assertEqual("", metadata[backends.ARTIST]) self.assertEqual("path/to", metadata[backends.ALBUM])
def test_noalbum_path(self): tagpy = FakeTagpy(TagData(artist="Beatles", title=None, album=None)) metadata = backends.extract_metadata("/music/Song.flac", tagpy) self.assertEqual("", metadata[backends.ALBUM])
def test_short_path(self): tagpy = FakeTagpy(None) metadata = backends.extract_metadata("/music/Song.flac", tagpy) self.assertEqual("music", metadata[backends.ALBUM])
def test_without_metadata(self): tagpy = FakeTagpy(None) metadata = backends.extract_metadata("/the/path/to/Song.flac", tagpy) self.assertEqual("Song.flac", metadata[backends.TITLE]) self.assertEqual("", metadata[backends.ARTIST]) self.assertEqual("path/to", metadata[backends.ALBUM])
def test_short_path(self): tagpy = FakeTagpy(None) metadata = backends.extract_metadata("/music/Song.flac", tagpy) self.assertEqual("music", metadata[backends.ALBUM])
def test_noalbum_path(self): tagpy = FakeTagpy(TagData(artist="Beatles", title=None, album=None)) metadata = backends.extract_metadata("/music/Song.flac", tagpy) self.assertEqual("", metadata[backends.ALBUM])
def test_decode_filename(self): tagpy = FakeTagpy(None) metadata = backends.extract_metadata("/path/to/\xe4\xb8\xad.flac", tagpy) self.assertEqual(u"\u4e2d.flac", metadata[backends.TITLE])
def test_decode_filename(self): tagpy = FakeTagpy(None) metadata = backends.extract_metadata("/path/to/\xe4\xb8\xad.flac", tagpy) self.assertEqual(u"\u4e2d.flac", metadata[backends.TITLE])