Source code for mdbapi.lycra

# MusicDB,  a music manager with web-bases UI that focus on music.
# Copyright (C) 2017  Ralf Stemmer <ralf.stemmer@gmx.net>
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import logging
import imp
from lib.cfg.musicdb    import MusicDBConfig
from lib.db.lycradb     import LycraDatabase
from lib.filesystem     import Filesystem

import os, sys
CRAWLERPATH = os.path.join(os.path.dirname(sys.argv[0]), "lib/crawler")

[docs]class Lycra(object): """ This class does the main lyrics management. Args: config: MusicDB Configuration object. Raises: TypeError: when *config* is not of type :class:`~lib.cfg.musicdb.MusicDBConfig` """ def __init__(self, config): if type(config) != MusicDBConfig: logging.error("Config-class of unknown type!") raise TypeError("config argument not of type MusicDBConfig") logging.debug("Crawler path is %s", CRAWLERPATH) self.config = config self.lycradb = LycraDatabase(self.config.lycra.dbpath) self.fs = Filesystem(CRAWLERPATH) self.crawlers = None
[docs] def LoadCrawlers(self): """ This method loads all crawlers inside the crawler directory. .. warning:: Changes at crawler may not be recognized until the whole application gets restarted. Only new added crawler gets loaded. Already loaded crawler are stuck at Pythons module cache. Returns: ``None`` """ # Get a list of all modules crawlerfiles = self.fs.GetFiles(".") modulenames = [self.fs.GetFileName(x) for x in crawlerfiles if self.fs.GetFileExtension(x) == "py"] if len(modulenames) == 0: logging.warning("No modules found in \"%s\"! \033[1;30m(… but crawler cache is still usable.)", self.fs.AbsolutePath(CRAWLERPATH)) self.crawlers = None return None # load all modules self.crawlers = [] for modulename in modulenames: modfp, modpath, moddesc = imp.find_module(modulename, [CRAWLERPATH]) try: logging.debug("Loading %s …", str(modpath)) module = imp.load_module(modulename, modfp, modpath, moddesc) except Exception as e: logging.error("Loading Crawler %s failed with error: %s! \033[1;30m(Ignoring this specific Crawler)", str(e), str(modpath)) finally: # Since we may exit via an exception, close fp explicitly. if modfp: modfp.close() crawler = {} crawler["module"] = module crawler["modulename"] = modulename self.crawlers.append(crawler) if len(self.crawlers) == 0: logging.warning("No crawler loaded from \"%s\"! \033[1;30m(… but crawler cache is still usable.)", self.fs.AbsolutePath(CRAWLERPATH)) self.crawlers = None return None
[docs] def RunCrawler(self, crawler, artistname, albumname, songname, songid): """ This method runs a specific crawler. This crawler gets all information available to search for a specific songs lyric. This method is for class internal use. When using this class, call :meth:`~mdbapi.lycra.Lycra.CrawlForLyrics` instead of calling this method directly. Before calling this method, :meth:`~mdbapi.lycra.Lycra.LoadCrawlers` must be called. The crawler base class :class:`lib.crawlerapi.LycraCrawler` catches all exceptions so that they do not net to be executed in an try-except environment. Args: crawler (str): Name of the crawler. If it addresses the file ``lib/crawler/example.py`` the name is ``example`` artistname (str): The name of the artist as stored in the MusicDatabase albumname (str): The name of the album as stored in the MusicDatabase songname (str): The name of the song as stored in the MusicDatabase songid (int): The ID of the song to associate the lyrics with the song Returns: ``None`` """ crawlerclass = getattr(crawler["module"], crawler["modulename"]) crawlerentity = crawlerclass(self.lycradb) crawlerentity.Crawl(artistname, albumname, songname, songid) return None
[docs] def CrawlForLyrics(self, artistname, albumname, songname, songid): """ Loads all crawler from the crawler directory via :meth:`~mdbapi.lycra.Lycra.LoadCrawlers` and runs them via :meth:`~mdbapi.lycra.Lycra.RunCrawler`. Args: artistname (str): The name of the artist as stored in the music database albumname (str): The name of the album as stored in the music database songname (str): The name of the song as stored in the music database songid (int): The ID of the song to associate the lyrics with the song Returns: ``False`` if something went wrong. Otherwise ``True``. (This is *no* indication that there were lyrics found!) """ # Load / Reload crawlers try: self.LoadCrawlers() except Exception as e: logging.error("Loading Crawlers failed with error \"%s\"! \033[1;30m(… but crawler cache is still usable.)", str(e)) return False if not self.crawlers: return False for crawler in self.crawlers: self.RunCrawler(crawler, artistname, albumname, songname, songid) return True
[docs] def GetLyrics(self, songid): """ This method returns the lyrics of a song. See :meth:`lib.db.lycradb.LycraDatabase.GetLyricsFromCache` """ return self.lycradb.GetLyricsFromCache(songid)
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4