Commit 9e053cc4 authored by Gerion Entrup's avatar Gerion Entrup
Browse files

brainzfs: add basic logging and fix exception handling

parent fd0e783c
......@@ -3,6 +3,7 @@
import argparse
import sys
import os.path
import logging
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
......@@ -27,7 +28,6 @@ class Main:
Session = scoped_session(session_factory)
self.session = Session
def main(self, args):
version="0.1-alpha"
parser = argparse.ArgumentParser(description="Create a directory structure of music with symlinks based on musicbrainz data", add_help=True)
......@@ -36,10 +36,12 @@ class Main:
parser.add_argument('mountpoint', help="where it should be mounted")
parser.add_argument('--verbose', '-v', action="store_true", default=False, help="lookup files with musicbrainz (better results, but takes a long time")
parser.add_argument('--database', '-d', default="music.db", help="path of the database")
parser.add_argument('--logfile', '-l', help="log into a logfile")
arg = parser.parse_args(args[1:])
self.init_database(arg.database)
logger.info("database initialized")
collector = Collector(self.session)
collector.start()
......@@ -57,4 +59,6 @@ class Main:
translator.join()
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('main')
Main().main(sys.argv)
......@@ -4,9 +4,11 @@ import musicbrainzngs
import itertools
import threading
import queue
import logging
from sqlalchemy import and_
from sqlalchemy.orm import Session
from musicbrainzngs import WebServiceError
from mbdata.models import Recording, ArtistCredit, ArtistCreditName, Artist, Release, ReleaseGroup, Medium, Track, MediumFormat
from utils import pairwise
......@@ -23,6 +25,7 @@ class Collector(threading.Thread):
super().__init__(target=self)
self._session = session_fac()
self.fetcher = Fetcher()
self.logger = logging.getLogger('collector')
def run(self):
while True:
......@@ -99,32 +102,37 @@ class Collector(threading.Thread):
def fetch_recording(self, mbid, path):
recording = self._session.query(Recording).filter_by(gid=mbid).first()
if recording is None:
result = self.fetcher.get_table_by_id(mbid, 'recording')
#minimal mapping
recording = Recording()
recording.gid = result['id']
recording.name = result['title']
recording.path = path
recording.ftype = path.split('.')[-1]
recording.artist_credit = self.create_artist_credit(result['artist-credit'], result['artist-credit-phrase'])
if 'length' in result:
recording.length = result['length']
self._session.add(recording)
#extended mapping
for releasedata in result['release-list']:
release = self.fetch_release(releasedata['id'])
# find track in release,
# this is clearly a workaround and only works efficient because of caching.
# correct way would be to fetch all tracks directly, but the musicbrainz api
# offer no way to do this.
mediumlist = self.fetcher.get_table_by_id(releasedata['id'], 'release')['medium-list']
for medium in mediumlist:
for track in medium['track-list']:
if track['recording']['id'] == mbid:
self.create_track(track, release, recording, medium)
self._session.commit()
try:
result = self.fetcher.get_table_by_id(mbid, 'recording')
#minimal mapping
recording = Recording()
recording.gid = result['id']
recording.name = result['title']
recording.path = path
recording.ftype = path.split('.')[-1]
recording.artist_credit = self.create_artist_credit(result['artist-credit'], result['artist-credit-phrase'])
if 'length' in result:
recording.length = result['length']
self._session.add(recording)
#extended mapping
for releasedata in result['release-list']:
release = self.fetch_release(releasedata['id'])
# find track in release,
# this is clearly a workaround and only works efficient because of caching.
# correct way would be to fetch all tracks directly, but the musicbrainz api
# offer no way to do this.
mediumlist = self.fetcher.get_table_by_id(releasedata['id'], 'release')['medium-list']
for medium in mediumlist:
for track in medium['track-list']:
if track['recording']['id'] == mbid:
self.create_track(track, release, recording, medium)
self._session.commit()
except musicbrainzngs.WebServiceError as exc:
self._session.rollback()
self.logger.error("Could not connect to Musicbrainz. Path: {} Request: {}".format(path, exc))
recording = None
return recording
......
......@@ -3,6 +3,7 @@ import mutagen
import musicbrainzngs
import itertools
import time
import logging
class Fetcher:
"""
......@@ -10,6 +11,7 @@ class Fetcher:
"""
def __init__(self):
self.logger = logging.getLogger('collector.fetcher')
musicbrainzngs.set_useragent("brainzfs", "0.1-alpha", "https://git.finf.uni-hannover.de/Chrysops/brainzfs")
self.cache = {'recording': {},
'release-group': {},
......@@ -28,6 +30,9 @@ class Fetcher:
self.time = timems()
def get_table_by_id(self, mbid, tablename):
"""fetch the data from musicbrainz. Asked the cache in transparent way, if data already available and handles the musicbrainz timing rules.
Throws an musicbrainzngs.WebServiceError if anything goes wrong."""
methods = {
'recording' : lambda mbid : musicbrainzngs.get_recording_by_id(mbid, includes=['releases', 'artists'])['recording'],
'release-group': lambda mbid : musicbrainzngs.get_release_group_by_id(mbid, includes=['artist-credits'])['release-group'],
......@@ -39,18 +44,15 @@ class Fetcher:
}
if mbid not in self.cache[tablename]:
try:
#delay to follow musicbrainz rules
self._delay()
#request actual data
result = methods[tablename](mbid)
except musicbrainzngs.WebServiceError as exc:
print("Could not connect to Musicbrainz. Request: {}".format(exc))
#delay to follow musicbrainz rules
self._delay()
#request actual data
result = methods[tablename](mbid)
self.cache[tablename][mbid] = result
print("asked web for {}".format(tablename))
self.logger.debug("asked web for {}".format(tablename))
else:
result = self.cache[tablename][mbid]
print("asked fetcher")
self.logger.debug("asked fetcher for {}".format(tablename))
#pp = pprint.PrettyPrinter(indent=4)
#pp.pprint(result)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment