From d06f96388d754ed41876f7fccb63f84241d44963 Mon Sep 17 00:00:00 2001 From: Michaƫl Ball Date: Sun, 26 Mar 2017 10:19:59 +0100 Subject: Works on python 2/pypy --- library.py | 192 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 129 insertions(+), 63 deletions(-) (limited to 'library.py') diff --git a/library.py b/library.py index 01924a2..272e9e5 100755 --- a/library.py +++ b/library.py @@ -1,99 +1,165 @@ #!/usr/bin/env python -import configparser -import gevent -from gevent import monkey, queue +"""This module implements a library for storing information on audio tracks.""" import logging -import mutagen import os +from gevent import joinall, monkey, queue, sleep, spawn +import mutagen +import six +from six.moves import configparser + from db.db_manager import DbManager from models.track import Track -file_store = queue.Queue() - logging.basicConfig(format="%(asctime)s %(message)s", level=logging.DEBUG) +_LOGGER = logging.getLogger(__name__) + +if six.PY2: + def _u(string): + return unicode(string, encoding="utf_8") +else: + def _u(string): + return string + + +class MediaLibrary(object): + """Implements methods for storing and managing media in a library.""" + + def __init__(self, media_dir, database): + """Create a media library object. + + Args: + media_dir (str): The path of the media directory + database (DatabaseManager): The media database + + """ + self.__media_dir = media_dir + self.__database = database + + def store_track_task(self, file_queue): + """Store a track from the supplied queue. + Args: + file_queue (Queue[str]): A queue containing file paths. -def store_track_task(): - while not file_store.empty(): - path = file_store.get() - m = mutagen.File(path, easy=True) - Track.store(path, m) + """ + while not file_queue.empty(): + path = file_queue.get() + metadata = mutagen.File(path, easy=True) + Track.store(_u(path), metadata, self.__database) - gevent.sleep(0) + sleep(0) + def run(self, path=None): + """Store all tracks located in the supplied path. -def run(path=None): - db = DbManager() - if path is not None: - if os.path.isdir(path): - store_dir(path) + Args: + path (str): The path to an audio file or directory containing audio + files. + + """ + if path is not None: + if os.path.isdir(path): + self.store_dir(path) + else: + self.store_file(path) else: - store_file(path) - else: - store_dir("/media/Music") - db.export() + self.store_dir(self.__media_dir) + + self.__database.export() + + def store_file(self, path): + """Store an audio file. + + Args: + path (str): The path to an audio file. + + """ + metadata = mutagen.File(path, easy=True) + if metadata: + if not Track.store(_u(path), metadata, self.__database): + _LOGGER.error("Problem saving %s", path) + + def store_dir(self, path): + """Store all audio files in a directory. + Args: + path (str): The path to a directory. -def store_file(path): - logger = logging.getLogger("store_file") - m = mutagen.File(path, easy=True) - if m: - if not Track.store(path, m): - logger.error("Problem saving %s" % (path,)) + """ + _LOGGER.info("Scanning files") + file_queue = queue.Queue() -def store_dir(path): - logger = logging.getLogger("store_dir") - logger.info("Scanning files") + allowed_extensions = [".mp3", ".ogg", ".flac", ".wav", ".aac", ".ape"] + for root, dummy, files in os.walk(path): + for name in files: + file_path = "".join([root, "/", name]) + dummy, ext = os.path.splitext(file_path) - allowed_extensions = [".mp3", ".ogg", ".flac", ".wav", ".aac", ".ape"] - for root, dirs, files in os.walk(path): - for name in files: - file_path = "".join([root, "/", name]) - file, ext = os.path.splitext(file_path) + if ext.lower() in allowed_extensions: + file_queue.put(file_path) - if ext.lower() in allowed_extensions: - file_store.put(file_path) + _LOGGER.info("Storing tracks") + joinall([spawn(self.store_track_task, file_queue)] * 18) + _LOGGER.info("Done") - logger.info("Storing tracks") - gevent.joinall([gevent.spawn(store_track_task)] * 6) - logger.info("Done") + def delete_file(self, path): + """Delete a file from the library. + Args: + path (str): The path for the file. -def delete_file(path): - track = Track.find_by_path(path) + """ + track = Track.find_by_path(_u(path), self.__database) - if track: - track_album = track.album - track_artists = track.artists + if track: + track_album = track.album + track_artists = track.artists - track.delete() + track.delete() - if track_album and len(track_album.tracks) == 0: - track_album.delete() + if track_album and len(track_album.tracks) == 0: + track_album.delete() - for artist in track_artists: - if len(artist.tracks) == 0: - artist.delete() + for artist in track_artists: + if len(artist.tracks) == 0: + artist.delete() + def update_file(self, path): + """Update a file in the library. -def update_file(path): - m = mutagen.File(path, easy=True) - if m: - track = Track.find_by_path(path) - track.update(m) + Args: + path (str): The path for the file. + """ + metadata = mutagen.File(path, easy=True) + if metadata: + track = Track.find_by_path(_u(path), self.__database) + track.update(metadata) + + def update_track_filename(self, oldpath, newpath): + """Update a track's filename. + + Args: + oldpath (str): The old path of the file. + newpath (str): The new path of the file. + + """ + track = Track.find_by_path(_u(oldpath), self.__database) + track.filename = _u(newpath) + track.save() -def update_track_filename(oldpath, newpath): - track = Track.find_by_path(oldpath) - track.filename = newpath - track.save() if __name__ == "__main__": monkey.patch_all(thread=False) - config = configparser.ConfigParser() - config.read("mach2.ini") + __CONFIG = configparser.ConfigParser() + __CONFIG.read("mach2.ini") + + db = DbManager(__CONFIG.get("DEFAULT", "library")) + media_path = __CONFIG.get("DEFAULT", "media_dir") + + media_library = MediaLibrary(media_path, db) - run(config["DEFAULT"]["media_dir"]) + media_library.run() -- cgit v1.2.3