diff --git a/headphones/__init__.py b/headphones/__init__.py index a9a1e6bb..8d29811c 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -22,15 +22,13 @@ import subprocess import threading import webbrowser import sqlite3 -import itertools import cherrypy from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.interval import IntervalTrigger -from headphones import versioncheck, logger, version +from headphones import versioncheck, logger import headphones.config -from headphones.common import * # (append new extras to the end) POSSIBLE_EXTRAS = [ @@ -153,7 +151,7 @@ def initialize(config_file): logger.info('Checking to see if the database has all tables....') try: dbcheck() - except Exception, e: + except Exception as e: logger.error("Can't connect to the database: %s", e) # Get the currently installed version - returns None, 'win32' or the git hash @@ -539,7 +537,7 @@ def shutdown(restart=False, update=False): logger.info('Headphones is updating...') try: versioncheck.update() - except Exception, e: + except Exception as e: logger.warn('Headphones failed to update: %s. Restarting.', e) if CREATEPID: diff --git a/headphones/albumart.py b/headphones/albumart.py index e7f64bb0..8bbbd425 100644 --- a/headphones/albumart.py +++ b/headphones/albumart.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . -from headphones import request, db +from headphones import request, db, logger def getAlbumArt(albumid): diff --git a/headphones/albumswitcher.py b/headphones/albumswitcher.py index 1f52d0a6..1edf1937 100644 --- a/headphones/albumswitcher.py +++ b/headphones/albumswitcher.py @@ -18,10 +18,11 @@ from headphones import db, logger, cache def switch(AlbumID, ReleaseID): - ''' + """ Takes the contents from allalbums & alltracks (based on ReleaseID) and switches them into the albums & tracks table. - ''' + """ + logger.debug('Switching allalbums and alltracks') myDB = db.DBConnection() oldalbumdata = myDB.action( 'SELECT * from albums WHERE AlbumID=?', [AlbumID]).fetchone() diff --git a/headphones/api.py b/headphones/api.py index 0097b99f..cb429ea6 100644 --- a/headphones/api.py +++ b/headphones/api.py @@ -15,10 +15,7 @@ from headphones import db, mb, importer, searcher, cache, postprocessor, versioncheck, logger -from xml.dom.minidom import Document - import headphones -import copy import json cmd_list = ['getIndex', 'getArtist', 'getAlbum', 'getUpcoming', 'getWanted', 'getSimilar', 'getHistory', 'getLogs', @@ -206,7 +203,7 @@ class Api(object): try: importer.addArtisttoDB(self.id) - except Exception, e: + except Exception as e: self.data = e return @@ -256,7 +253,7 @@ class Api(object): try: importer.addArtisttoDB(self.id) - except Exception, e: + except Exception as e: self.data = e return @@ -270,7 +267,7 @@ class Api(object): try: importer.addReleaseById(self.id) - except Exception, e: + except Exception as e: self.data = e return diff --git a/headphones/cache.py b/headphones/cache.py index 73c7fc40..615b3e2c 100644 --- a/headphones/cache.py +++ b/headphones/cache.py @@ -14,8 +14,6 @@ # along with Headphones. If not, see . import os -import glob -import urllib import headphones from headphones import db, helpers, logger, lastfm, request @@ -269,7 +267,7 @@ class Cache(object): for thumb_file in self.thumb_files: try: os.remove(thumb_file) - except Exception as e: + except Exception: logger.warn('Error deleting file from the cache: %s', thumb_file) def _update_cache(self): @@ -376,7 +374,7 @@ class Cache(object): if not os.path.isdir(self.path_to_art_cache): try: os.makedirs(self.path_to_art_cache) - except Exception, e: + except Exception as e: logger.error('Unable to create artwork cache dir. Error: %s', e) self.artwork_errors = True self.artwork_url = image_url diff --git a/headphones/classes.py b/headphones/classes.py index d9665090..96315ba7 100644 --- a/headphones/classes.py +++ b/headphones/classes.py @@ -17,10 +17,8 @@ ## Stolen from Sick-Beard's classes.py ## ######################################### -import headphones import urllib -import datetime from common import USER_AGENT diff --git a/headphones/cuesplit.py b/headphones/cuesplit.py index 0712bdaa..89da78e5 100755 --- a/headphones/cuesplit.py +++ b/headphones/cuesplit.py @@ -18,10 +18,7 @@ import os import sys import re -import shutil -import commands import subprocess -import time import copy import glob @@ -69,6 +66,9 @@ WAVE_FILE_TYPE_BY_EXTENSION = { #SHNTOOL_COMPATIBLE = ('Waveform Audio', 'WavPack', 'Free Lossless Audio Codec') SHNTOOL_COMPATIBLE = ('Free Lossless Audio Codec') +# this module-level variable is bad. :( +META = None + def check_splitter(command): '''Check xld or shntools installed''' @@ -170,21 +170,6 @@ def int_to_str(value, length=2): return content -def split_file_list(ext=None): - file_list = [None for m in range(100)] - if ext and ext[0] != '.': - ext = '.' + ext - for f in os.listdir('.'): - if f[:11] == 'split-track': - if (ext and ext == os.path.splitext(f)[-1]) or not ext: - filename_parser = re.search('split-track(\d\d)', f) - track_nr = int(filename_parser.group(1)) - if cue.htoa() and not os.path.exists('split-track00' + ext): - track_nr -= 1 - file_list[track_nr] = WaveFile(f, track_nr=track_nr) - return check_list(file_list, ignore=1) - - class Directory: def __init__(self, path): self.path = path @@ -267,7 +252,7 @@ class Directory: self.content.append(File(self.path + os.sep + i)) -class File: +class File(object): def __init__(self, path): self.path = path self.name = os.path.split(self.path)[-1] @@ -373,7 +358,7 @@ class CueFile(File): return track_nr, track_meta, line_index - File.__init__(self, path) + super(CueFile, self).__init__(path) try: with open(self.name) as cue_file: @@ -445,7 +430,7 @@ class CueFile(File): class MetaFile(File): def __init__(self, path): - File.__init__(self, path) + super(MetaFile, self).__init__(path) with open(self.path) as meta_file: self.rawcontent = meta_file.read() @@ -481,8 +466,8 @@ class MetaFile(File): common_tags['tracktotal'] = str(len(self.content['tracks']) - 1) if 'date' in self.content: common_tags['date'] = self.content['date'] - if 'genre' in meta.content: - common_tags['genre'] = meta.content['genre'] + if 'genre' in META.content: + common_tags['genre'] = META.content['genre'] #freeform tags #freeform_tags['country'] = self.content['country'] @@ -510,13 +495,13 @@ class MetaFile(File): class WaveFile(File): def __init__(self, path, track_nr=None): - File.__init__(self, path) + super(WaveFile, self).__init__(path) self.track_nr = track_nr self.type = WAVE_FILE_TYPE_BY_EXTENSION[self.name_ext] def filename(self, ext=None, cmd=False): - title = meta.content['tracks'][self.track_nr]['title'] + title = META.content['tracks'][self.track_nr]['title'] if ext: if ext[0] != '.': @@ -538,7 +523,7 @@ class WaveFile(File): def tag(self): if self.type == 'Free Lossless Audio Codec': f = FLAC(self.name) - tags = meta.flac_tags(self.track_nr) + tags = META.flac_tags(self.track_nr) for t in tags[0]: f[t] = tags[0][t] f.save() @@ -547,11 +532,16 @@ class WaveFile(File): if self.type == 'Free Lossless Audio Codec': return FLAC(self.name) - def split(albumpath): - + global META os.chdir(albumpath) base_dir = Directory(os.getcwd()) + # check metafile for completeness + if not base_dir.filter('MetaFile'): + raise ValueError('Meta file {0} missing!'.format(ALBUM_META_FILE_NAME)) + else: + META = base_dir.filter('MetaFile')[0] + cue = None wave = None @@ -614,12 +604,6 @@ def split(albumpath): with open(ALBUM_META_FILE_NAME, mode='w') as meta_file: meta_file.write(cue.get_meta()) base_dir.content.append(MetaFile(os.path.abspath(ALBUM_META_FILE_NAME))) - # check metafile for completeness - if not base_dir.filter('MetaFile'): - raise ValueError('Meta file {0} missing!'.format(ALBUM_META_FILE_NAME)) - else: - global meta - meta = base_dir.filter('MetaFile')[0] # Split with xld if 'xld' in splitter: @@ -653,13 +637,13 @@ def split(albumpath): base_dir.update() # tag FLAC files - if split and meta.count_tracks() == len(base_dir.tracks(ext='.flac', split=True)): + if split and META.count_tracks() == len(base_dir.tracks(ext='.flac', split=True)): for t in base_dir.tracks(ext='.flac', split=True): logger.info('Tagging {0}...'.format(t.name)) t.tag() # rename FLAC files - if split and meta.count_tracks() == len(base_dir.tracks(ext='.flac', split=True)): + if split and META.count_tracks() == len(base_dir.tracks(ext='.flac', split=True)): for t in base_dir.tracks(ext='.flac', split=True): if t.name != t.filename(): logger.info('Renaming {0} to {1}...'.format(t.name, t.filename())) diff --git a/headphones/db.py b/headphones/db.py index b1eac471..cf4cdeae 100644 --- a/headphones/db.py +++ b/headphones/db.py @@ -21,8 +21,6 @@ from __future__ import with_statement import os import sqlite3 -import threading -import time import headphones diff --git a/headphones/getXldProfile.py b/headphones/getXldProfile.py index d52c5b2d..3e389914 100755 --- a/headphones/getXldProfile.py +++ b/headphones/getXldProfile.py @@ -2,7 +2,6 @@ import os.path import plistlib import sys import xml.parsers.expat as expat -import commands from headphones import logger diff --git a/headphones/helpers.py b/headphones/helpers.py index 36d2c7a4..29f1fe23 100644 --- a/headphones/helpers.py +++ b/headphones/helpers.py @@ -436,7 +436,7 @@ def extract_metadata(f): # (Lots of) different artists. Could be a featuring album, so test for this. if len(artists) > 1 and len(albums) == 1: - split_artists = [RE_FEATURING.split(artist) for artist in artists] + split_artists = [RE_FEATURING.split(x) for x in artists] featurings = [len(split_artist) - 1 for split_artist in split_artists] logger.info("Album seem to feature %d different artists", sum(featurings)) @@ -481,7 +481,7 @@ def preserve_torrent_direcory(albumpath): try: shutil.copytree(albumpath, new_folder) return new_folder - except Exception, e: + except Exception as e: logger.warn("Cannot copy/move files to temp folder: " + \ new_folder.decode(headphones.SYS_ENCODING, 'replace') + \ ". Not continuing. Error: " + str(e)) @@ -517,7 +517,7 @@ def cue_split(albumpath): for cue_dir in cue_dirs: try: cuesplit.split(cue_dir) - except Exception, e: + except Exception as e: os.chdir(cwd) logger.warn("Cue not split: " + str(e)) return False @@ -591,7 +591,7 @@ def smartMove(src, dest, delete=True): try: os.rename(src, os.path.join(source_dir, newfile)) filename = newfile - except Exception, e: + except Exception as e: logger.warn('Error renaming %s: %s', src.decode(headphones.SYS_ENCODING, 'replace'), e) break @@ -601,7 +601,7 @@ def smartMove(src, dest, delete=True): else: shutil.copy(os.path.join(source_dir, filename), os.path.join(dest, filename)) return True - except Exception, e: + except Exception as e: logger.warn('Error moving file %s: %s', filename.decode(headphones.SYS_ENCODING, 'replace'), e) ######################### diff --git a/headphones/importer.py b/headphones/importer.py index c5fdda0b..758470ad 100644 --- a/headphones/importer.py +++ b/headphones/importer.py @@ -17,9 +17,7 @@ from headphones import logger, helpers, db, mb, lastfm from beets.mediafile import MediaFile -import os import time -import threading import headphones blacklisted_special_artist_names = ['[anonymous]', '[data]', '[no artist]', @@ -700,7 +698,7 @@ def updateFormat(): for track in tracks: try: f = MediaFile(track['Location']) - except Exception, e: + except Exception as e: logger.info("Exception from MediaFile for: " + track['Location'] + " : " + str(e)) continue controlValueDict = {"TrackID": track['TrackID']} @@ -713,7 +711,7 @@ def updateFormat(): for track in havetracks: try: f = MediaFile(track['Location']) - except Exception, e: + except Exception as e: logger.info("Exception from MediaFile for: " + track['Location'] + " : " + str(e)) continue controlValueDict = {"TrackID": track['TrackID']} diff --git a/headphones/librarysync.py b/headphones/librarysync.py index c13fef17..0b49f563 100644 --- a/headphones/librarysync.py +++ b/headphones/librarysync.py @@ -14,7 +14,6 @@ # along with Headphones. If not, see . import os -import glob import headphones from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError @@ -110,7 +109,7 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None, cron=Fal except (FileTypeError, UnreadableFileError): logger.warning("Cannot read media file '%s', skipping. It may be corrupted or not a media file.", unicode_song_path) continue - except IOError as e: + except IOError: logger.warning("Cannnot read media file '%s', skipping. Does the file exists?", unicode_song_path) continue @@ -301,15 +300,30 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None, cron=Fal current_artists = myDB.select('SELECT ArtistName, ArtistID from artists') #There was a bug where artists with special characters (-,') would show up in new artists. - artist_list = [f for f in unique_artists if helpers.cleanName(f).lower() not in [helpers.cleanName(x[0]).lower() for x in current_artists]] - artists_checked = [f for f in unique_artists if helpers.cleanName(f).lower() in [helpers.cleanName(x[0]).lower() for x in current_artists]] + artist_list = [ + x for x in unique_artists + if helpers.cleanName(x).lower() not in [ + helpers.cleanName(y[0]).lower() + for y in current_artists + ] + ] + artists_checked = [ + x for x in unique_artists + if helpers.cleanName(x).lower() in [ + helpers.cleanName(y[0]).lower() + for y in current_artists + ] + ] # Update track counts for artist in artists_checked: # Have tracks are selected from tracks table and not all tracks because of duplicates # We update the track count upon an album switch to compliment this - havetracks = len(myDB.select('SELECT TrackTitle from tracks WHERE ArtistName like ? AND Location IS NOT NULL', [artist])) + len(myDB.select('SELECT TrackTitle from have WHERE ArtistName like ? AND Matched = "Failed"', [artist])) + havetracks = ( + len(myDB.select('SELECT TrackTitle from tracks WHERE ArtistName like ? AND Location IS NOT NULL', [artist])) + + len(myDB.select('SELECT TrackTitle from have WHERE ArtistName like ? AND Matched = "Failed"', [artist])) + ) #Note, some people complain about having "artist have tracks" > # of tracks total in artist official releases # (can fix by getting rid of second len statement) myDB.action('UPDATE artists SET HaveTracks=? WHERE ArtistName=?', [havetracks, artist]) diff --git a/headphones/mb.py b/headphones/mb.py index 19d9766c..a688624b 100644 --- a/headphones/mb.py +++ b/headphones/mb.py @@ -15,7 +15,6 @@ from headphones import logger, db, helpers -from headphones.helpers import multikeysort, replace_all import time import threading @@ -224,7 +223,7 @@ def getArtist(artistid, extrasonly=False): except musicbrainzngs.WebServiceError as e: logger.warn('Attempt to retrieve artist information from MusicBrainz failed for artistid: %s (%s)' % (artistid, str(e))) time.sleep(5) - except Exception, e: + except Exception as e: pass if not artist: @@ -332,8 +331,6 @@ def getReleaseGroup(rgid): """ with mb_lock: - releaselist = [] - releaseGroup = None try: @@ -463,8 +460,6 @@ def get_new_releases(rgid, includeExtras=False, forcefull=False): release = {} rel_id_check = releasedata['id'] - artistid = unicode(releasedata['artist-credit'][0]['artist']['id']) - album_checker = myDB.action('SELECT * from allalbums WHERE ReleaseID=?', [rel_id_check]).fetchone() if not album_checker or forcefull: #DELETE all references to this release since we're updating it anyway. diff --git a/headphones/music_encoder.py b/headphones/music_encoder.py index b5f606cb..27f596ae 100644 --- a/headphones/music_encoder.py +++ b/headphones/music_encoder.py @@ -24,18 +24,14 @@ from headphones import logger from beets.mediafile import MediaFile # xld -if headphones.CONFIG.ENCODER == 'xld': - import getXldProfile - XLD = True -else: - XLD = False +import getXldProfile def encode(albumPath): + use_xld = headphones.CONFIG.ENCODER == 'xld' # Return if xld details not found - if XLD: - global xldProfile + if use_xld: (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.CONFIG.XLDPROFILE) if not xldFormat: logger.error('Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) @@ -61,7 +57,7 @@ def encode(albumPath): for r, d, f in os.walk(albumPath): for music in f: if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS): - if not XLD: + if not use_xld: encoderFormat = headphones.CONFIG.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING) else: xldMusicFile = os.path.join(r, music) @@ -70,7 +66,7 @@ def encode(albumPath): if (headphones.CONFIG.ENCODERLOSSLESS): ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower() - if not XLD and ext == 'flac' or XLD and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)): + if not use_xld and ext == 'flac' or use_xld and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)): musicFiles.append(os.path.join(r, music)) musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat) musicTempFiles.append(os.path.join(tempDirEncode, musicTemp)) @@ -84,7 +80,7 @@ def encode(albumPath): if headphones.CONFIG.ENCODER_PATH: encoder = headphones.CONFIG.ENCODER_PATH.encode(headphones.SYS_ENCODING) else: - if XLD: + if use_xld: encoder = os.path.join('/Applications', 'xld') elif headphones.CONFIG.ENCODER == 'lame': if headphones.SYS_PLATFORM == "win32": @@ -111,7 +107,7 @@ def encode(albumPath): infoMusic = MediaFile(music) encode = False - if XLD: + if use_xld: if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate): logger.info('%s has bitrate <= %skb, will not be re-encoded', music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate) else: @@ -202,7 +198,7 @@ def encode(albumPath): os.remove(check_dest) try: shutil.move(dest, albumPath) - except Exception, e: + except Exception as e: logger.error('Could not move %s to %s: %s', dest, albumPath, e) encoder_failed = True break @@ -241,7 +237,7 @@ def command_map(args): # Start encoding try: return command(*args) - except Exception as e: + except Exception: logger.exception("Encoder raised an exception.") return False @@ -251,12 +247,17 @@ def command(encoder, musicSource, musicDest, albumPath): Encode a given music file with a certain encoder. Returns True on success, or False otherwise. """ + use_xld = headphones.CONFIG.ENCODER == 'xld' startMusicTime = time.time() cmd = [] - # XLD - if XLD: + # Return if xld details not found + if use_xld: + (xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.CONFIG.XLDPROFILE) + if not xldFormat: + logger.error('Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile) + return None xldDestDir = os.path.split(musicDest)[0] cmd = [encoder] cmd.extend([musicSource]) diff --git a/headphones/notifiers.py b/headphones/notifiers.py index f744e252..953b7d5f 100644 --- a/headphones/notifiers.py +++ b/headphones/notifiers.py @@ -28,7 +28,6 @@ import headphones import os.path import subprocess import gntp.notifier -import time import json import oauth2 as oauth @@ -286,7 +285,7 @@ class LMS(object): try: handle = urllib2.urlopen(req) - except Exception, e: + except Exception as e: logger.warn('Error opening LMS url: %s' % e) return @@ -337,7 +336,7 @@ class Plex(object): try: handle = urllib2.urlopen(req) - except Exception, e: + except Exception as e: logger.warn('Error opening Plex url: %s' % e) return @@ -371,7 +370,7 @@ class Plex(object): url = "%s/library/sections/%s/refresh" % (host, s.getAttribute('key')) try: urllib.urlopen(url) - except Exception, e: + except Exception as e: logger.warn("Error updating library section for Plex Media Server: %s" % e) return False @@ -649,7 +648,6 @@ class TwitterNotifier(object): def _get_authorization(self): - signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1() #@UnusedVariable oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret) oauth_client = oauth.Client(oauth_consumer) @@ -679,7 +677,6 @@ class TwitterNotifier(object): logger.info('Generating and signing request for an access token using key ' + key) - signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1() #@UnusedVariable oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret) logger.info('oauth_consumer: ' + str(oauth_consumer)) oauth_client = oauth.Client(oauth_consumer, token) @@ -714,7 +711,7 @@ class TwitterNotifier(object): try: api.PostUpdate(message) - except Exception, e: + except Exception as e: logger.info(u"Error Sending Tweet: %s" % e) return False @@ -778,7 +775,7 @@ class OSX_NOTIFY(object): del pool return True - except Exception, e: + except Exception as e: logger.warn('Error sending OS X Notification: %s' % e) return False diff --git a/headphones/nzbget.py b/headphones/nzbget.py index d14dade8..50240f35 100644 --- a/headphones/nzbget.py +++ b/headphones/nzbget.py @@ -20,15 +20,12 @@ import httplib -import datetime import headphones from base64 import standard_b64encode import xmlrpclib -#from headphones.providers.generic import GenericProvider - from headphones import logger @@ -87,13 +84,15 @@ def sendNZB(nzb): if nzbcontent64 is not None: nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, addToTop, nzbcontent64) else: - if nzb.resultType == "nzb": - genProvider = GenericProvider("") - data = genProvider.getURL(nzb.url) - if (data is None): - return False - nzbcontent64 = standard_b64encode(data) - nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, addToTop, nzbcontent64) + # from headphones.common.providers.generic import GenericProvider + # if nzb.resultType == "nzb": + # genProvider = GenericProvider("") + # data = genProvider.getURL(nzb.url) + # if (data is None): + # return False + # nzbcontent64 = standard_b64encode(data) + # nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, addToTop, nzbcontent64) + return False elif nzbget_version == 12: if nzbcontent64 is not None: nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, headphones.CONFIG.NZBGET_PRIORITY, False, diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 88f79d33..90de3587 100755 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -23,7 +23,6 @@ import headphones from beets import autotag from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError -from beets import plugins from beetsplug import lyrics as beetslyrics from headphones import notifiers, utorrent, transmission @@ -71,7 +70,7 @@ def verify(albumid, albumpath, Kind=None, forced=False): # Fetch album information from MusicBrainz try: release_list = mb.getReleaseGroup(albumid) - except Exception, e: + except Exception as e: logger.error('Unable to get release information for manual album with rgid: %s. Error: %s', albumid, e) return @@ -199,7 +198,7 @@ def verify(albumid, albumpath, Kind=None, forced=False): for downloaded_track in downloaded_track_list: try: f = MediaFile(downloaded_track) - except Exception, e: + except Exception as e: logger.info(u"Exception from MediaFile for: " + downloaded_track.decode(headphones.SYS_ENCODING, 'replace') + u" : " + unicode(e)) continue @@ -290,7 +289,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, shutil.copytree(albumpath, new_folder) # Update the album path with the new location albumpath = new_folder - except Exception, e: + except Exception as e: logger.warn("Cannot copy/move files to temp folder: " + new_folder.decode(headphones.SYS_ENCODING, 'replace') + ". Not continuing. Error: " + str(e)) return @@ -308,7 +307,10 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, # below are executed. This simplifies errors and prevents unfinished steps. for downloaded_track in downloaded_track_list: try: - media_file = MediaFile(downloaded_track) + f = MediaFile(downloaded_track) + if f is None: + # this test is just to keep pyflakes from complaining about an unused variable + return except (FileTypeError, UnreadableFileError): logger.error("Track file is not a valid media file: %s. Not " \ "continuing.", downloaded_track.decode( @@ -329,7 +331,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, try: with open(downloaded_track, "a+b"): pass - except IOError as e: + except IOError: logger.error("Track file is not writeable. This is required " \ "for some post processing steps: %s. Not continuing.", downloaded_track.decode(headphones.SYS_ENCODING, "replace")) @@ -519,7 +521,7 @@ def embedAlbumArt(artwork, downloaded_track_list): try: f.art = artwork f.save() - except Exception, e: + except Exception as e: logger.error(u'Error embedding album art to: %s. Error: %s' % (downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e))) continue @@ -685,7 +687,7 @@ def moveFiles(albumpath, release, tracks): if headphones.CONFIG.REPLACE_EXISTING_FOLDERS: try: shutil.rmtree(lossless_destination_path) - except Exception, e: + except Exception as e: logger.error("Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (lossless_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e)) create_duplicate_folder = True @@ -705,7 +707,7 @@ def moveFiles(albumpath, release, tracks): if not os.path.exists(lossless_destination_path): try: os.makedirs(lossless_destination_path) - except Exception, e: + except Exception as e: logger.error('Could not create lossless folder for %s. (Error: %s)' % (release['AlbumTitle'], e)) if not make_lossy_folder: return [albumpath] @@ -718,7 +720,7 @@ def moveFiles(albumpath, release, tracks): if headphones.CONFIG.REPLACE_EXISTING_FOLDERS: try: shutil.rmtree(lossy_destination_path) - except Exception, e: + except Exception as e: logger.error("Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (lossy_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e)) create_duplicate_folder = True @@ -738,7 +740,7 @@ def moveFiles(albumpath, release, tracks): if not os.path.exists(lossy_destination_path): try: os.makedirs(lossy_destination_path) - except Exception, e: + except Exception as e: logger.error('Could not create folder for %s. Not moving: %s' % (release['AlbumTitle'], e)) return [albumpath] @@ -766,7 +768,7 @@ def moveFiles(albumpath, release, tracks): if moved_to_lossy_folder or moved_to_lossless_folder: try: os.remove(file_to_move) - except Exception, e: + except Exception as e: logger.error("Error deleting file '" + file_to_move.decode(headphones.SYS_ENCODING, 'replace') + "' from source directory") else: logger.error("Error copying '" + file_to_move.decode(headphones.SYS_ENCODING, 'replace') + "'. Not deleting from download directory") @@ -799,13 +801,13 @@ def moveFiles(albumpath, release, tracks): try: os.chmod(os.path.normpath(temp_f).encode(headphones.SYS_ENCODING, 'replace'), int(headphones.CONFIG.FOLDER_PERMISSIONS, 8)) - except Exception, e: + except Exception as e: logger.error("Error trying to change permissions on folder: %s. %s", temp_f, e) # If we failed to move all the files out of the directory, this will fail too try: shutil.rmtree(albumpath) - except Exception, e: + except Exception as e: logger.error('Could not remove directory: %s. %s', albumpath, e) destination_paths = [] @@ -835,7 +837,7 @@ def correctMetadata(albumid, release, downloaded_track_list): lossy_items.append(beets.library.Item.from_path(downloaded_track)) else: logger.warn("Skipping: %s because it is not a mutagen friendly file format", downloaded_track.decode(headphones.SYS_ENCODING, 'replace')) - except Exception, e: + except Exception as e: logger.error("Beets couldn't create an Item from: %s - not a media file? %s", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e)) for items in [lossy_items, lossless_items]: @@ -845,7 +847,7 @@ def correctMetadata(albumid, release, downloaded_track_list): try: cur_artist, cur_album, candidates, rec = autotag.tag_album(items, search_artist=helpers.latinToAscii(release['ArtistName']), search_album=helpers.latinToAscii(release['AlbumTitle'])) - except Exception, e: + except Exception as e: logger.error('Error getting recommendation: %s. Not writing metadata', e) return if str(rec) == 'recommendation.none': @@ -868,7 +870,7 @@ def correctMetadata(albumid, release, downloaded_track_list): try: item.write() logger.info("Successfully applied metadata to: %s", item.path.decode(headphones.SYS_ENCODING, 'replace')) - except Exception, e: + except Exception as e: logger.warn("Error writing metadata to '%s': %s", item.path.decode(headphones.SYS_ENCODING, 'replace'), str(e)) @@ -891,7 +893,7 @@ def embedLyrics(downloaded_track_list): lossy_items.append(beets.library.Item.from_path(downloaded_track)) else: logger.warn("Skipping: %s because it is not a mutagen friendly file format", downloaded_track.decode(headphones.SYS_ENCODING, 'replace')) - except Exception, e: + except Exception as e: logger.error("Beets couldn't create an Item from: %s - not a media file? %s", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e)) for items in [lossy_items, lossless_items]: @@ -914,7 +916,7 @@ def embedLyrics(downloaded_track_list): item.lyrics = lyrics try: item.write() - except Exception, e: + except Exception as e: logger.error('Cannot save lyrics to: %s. Skipping', item.title) else: logger.debug('No lyrics found for track: %s', item.title) @@ -1003,7 +1005,7 @@ def renameFiles(albumpath, downloaded_track_list, release): logger.debug('Renaming %s ---> %s', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), new_file_name.decode(headphones.SYS_ENCODING, 'replace')) try: os.rename(downloaded_track, new_file) - except Exception, e: + except Exception as e: logger.error('Error renaming file: %s. Error: %s', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), e) continue @@ -1107,11 +1109,12 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): verify(snatched['AlbumID'], folder, snatched['Kind']) continue + year = None # Attempt 2a: parse the folder name into a valid format try: logger.debug('Attempting to extract name, album and year from folder name') name, album, year = helpers.extract_data(folder_basename) - except Exception as e: + except Exception: name = album = year = None if name and album: @@ -1138,15 +1141,15 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): try: logger.debug('Attempting to extract name, album and year from metadata') name, album, year = helpers.extract_metadata(folder) - except Exception as e: - name = album = year = None + except Exception: + name = album = None # Check if there's a cue to split if not name and not album and helpers.cue_split(folder): try: name, album, year = helpers.extract_metadata(folder) - except Exception as e: - name = album = year = None + except Exception: + name = album = None if name and album: release = myDB.action('SELECT AlbumID, ArtistName, AlbumTitle from albums WHERE ArtistName LIKE ? and AlbumTitle LIKE ?', [name, album]).fetchone() diff --git a/headphones/sab.py b/headphones/sab.py index 7f64041f..45565f77 100644 --- a/headphones/sab.py +++ b/headphones/sab.py @@ -19,7 +19,6 @@ import MultipartPostHandler import headphones -import datetime import cookielib import urllib2 import httplib @@ -28,7 +27,7 @@ import ast from headphones.common import USER_AGENT from headphones import logger -from headphones import notifiers, helpers +from headphones import helpers def sendNZB(nzb): @@ -88,15 +87,15 @@ def sendNZB(nzb): f = opener.open(req) - except (EOFError, IOError), e: + except (EOFError, IOError) as e: logger.error(u"Unable to connect to SAB with URL: %s" % url) return False - except httplib.InvalidURL, e: + except httplib.InvalidURL as e: logger.error(u"Invalid SAB host, check your config. Current host: %s" % headphones.CONFIG.SAB_HOST) return False - except Exception, e: + except Exception as e: logger.error(u"Error: " + str(e)) return False @@ -106,7 +105,7 @@ def sendNZB(nzb): try: result = f.readlines() - except Exception, e: + except Exception as e: logger.info(u"Error trying to get result from SAB, NZB not sent: ") return False @@ -152,7 +151,7 @@ def checkConfig(): try: f = urllib.urlopen(url).read() - except Exception, e: + except Exception: logger.warn("Unable to read SABnzbd config file - cannot determine renaming options (might affect auto & forced post processing)") return (0, 0) diff --git a/headphones/searcher.py b/headphones/searcher.py index f065ae6a..35ccd5a7 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -20,13 +20,11 @@ import urlparse from pygazelle import api as gazelleapi from pygazelle import encoding as gazelleencoding from pygazelle import format as gazelleformat -from pygazelle import media as gazellemedia from base64 import b16encode, b32decode from hashlib import sha1 import os import re -import time import string import shutil import random @@ -395,7 +393,7 @@ def sort_search_results(resultlist, album, new, albumlength): if not len(finallist) and len(flac_list) and headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS: logger.info("Since there were no appropriate lossy matches (and at least one lossless match, going to use lossless instead") finallist = sorted(flac_list, key=lambda title: (title[5], int(title[1])), reverse=True) - except Exception as e: + except Exception: logger.exception('Unhandled exception') logger.info('No track information for %s - %s. Defaulting to highest quality', (album['ArtistName'], album['AlbumTitle'])) @@ -423,8 +421,6 @@ def get_year_from_release_date(release_date): def searchNZB(album, new=False, losslessOnly=False, albumlength=None): - - albumid = album['AlbumID'] reldate = album['ReleaseDate'] year = get_year_from_release_date(reldate) @@ -1061,7 +1057,6 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None): logger.debug("Using search term: %s" % term) resultlist = [] - pre_sorted_results = False minimumseeders = int(headphones.CONFIG.NUMBEROFSEEDERS) - 1 def set_proxy(proxy_url): @@ -1087,15 +1082,12 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None): # Pick category for torrents if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly: - categories = "7" # Music format = "2" # FLAC maxsize = 10000000000 elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless: - categories = "7" # Music format = "10" # MP3 and FLAC maxsize = 10000000000 else: - categories = "7" # Music format = "8" # MP3 only maxsize = 300000000 @@ -1289,8 +1281,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None): # filter on format, size, and num seeders logger.info(u"Filtering torrents by format, maximum size, and minimum seeders...") - match_torrents = [torrent for torrent in all_torrents if torrent.size <= maxsize] - match_torrents = [torrent for torrent in match_torrents if torrent.seeders >= minimumseeders] + match_torrents = [t for t in all_torrents if t.size <= maxsize and t.seeders >= minimumseeders] logger.info(u"Remaining torrents: %s" % ", ".join(repr(torrent) for torrent in match_torrents)) @@ -1312,7 +1303,6 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None): # match_torrents.sort(key=lambda x: str(bitrate) in x.getTorrentFolderName(), reverse=True) logger.info(u"New order: %s" % ", ".join(repr(torrent) for torrent in match_torrents)) - pre_sorted_results = True for torrent in match_torrents: if not torrent.file_path: torrent.group.update_group_data() # will load the file_path for the individual torrents @@ -1398,15 +1388,15 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None): providerurl = fix_url("http://www.mininova.org/rss/" + term + "/5") if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly: - categories = "7" #music + # categories = "7" #music format = "2" #flac maxsize = 10000000000 elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless: - categories = "7" #music + # categories = "7" #music format = "10" #mp3+flac maxsize = 10000000000 else: - categories = "7" #music + # categories = "7" #music format = "8" #mp3 maxsize = 300000000 diff --git a/headphones/searcher_rutracker.py b/headphones/searcher_rutracker.py index ab7f10b1..0817cc50 100644 --- a/headphones/searcher_rutracker.py +++ b/headphones/searcher_rutracker.py @@ -4,8 +4,6 @@ # Headphones rutracker.org search # Functions called from searcher.py -from headphones import logger, db, utorrent - from bencode import bencode as bencode, bdecode from urlparse import urlparse from bs4 import BeautifulSoup @@ -20,6 +18,8 @@ import urllib import re import os +from headphones import db, logger + class Rutracker(): @@ -198,7 +198,7 @@ class Rutracker(): decoded = bdecode(torrent) metainfo = decoded['info'] page.close() - except Exception, e: + except Exception as e: logger.error('Error getting torrent: %s' % e) return False diff --git a/headphones/transmission.py b/headphones/transmission.py index decc026d..f6cbf582 100644 --- a/headphones/transmission.py +++ b/headphones/transmission.py @@ -13,9 +13,8 @@ # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . -from headphones import logger, notifiers, request +from headphones import logger, request -import re import time import json import base64 @@ -45,13 +44,10 @@ def addTorrent(link): if response['result'] == 'success': if 'torrent-added' in response['arguments']: - name = response['arguments']['torrent-added']['name'] retid = response['arguments']['torrent-added']['hashString'] elif 'torrent-duplicate' in response['arguments']: - name = response['arguments']['torrent-duplicate']['name'] retid = response['arguments']['torrent-duplicate']['hashString'] else: - name = link retid = False logger.info(u"Torrent sent to Transmission successfully") @@ -147,11 +143,13 @@ def torrentAction(method, arguments): i = host.rfind(':') if i >= 0: possible_port = host[i + 1:] + host = host + "/rpc" try: port = int(possible_port) - host = host + "/transmission/rpc" + if port: + host = host + "/transmission/rpc" except ValueError: - host = host + "/rpc" + logger.debug('No port, assuming not transmission') else: logger.error('Transmission port missing') return diff --git a/headphones/updater.py b/headphones/updater.py index 4b1e8910..b18db5bc 100644 --- a/headphones/updater.py +++ b/headphones/updater.py @@ -13,8 +13,6 @@ # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . -import headphones - from headphones import logger, db, importer diff --git a/headphones/webserve.py b/headphones/webserve.py index 0702ec08..b1c0d950 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -452,7 +452,6 @@ class WebInterface(object): myDB = db.DBConnection() have_album_dictionary = [] headphones_album_dictionary = [] - unmatched_albums = [] have_albums = myDB.select('SELECT ArtistName, AlbumTitle, TrackTitle, CleanName from have WHERE Matched = "Failed" GROUP BY AlbumTitle ORDER BY ArtistName') for albums in have_albums: #Have to skip over manually matched tracks @@ -685,7 +684,7 @@ class WebInterface(object): if scan: try: threading.Thread(target=librarysync.libraryScan).start() - except Exception, e: + except Exception as e: logger.error('Unable to complete the scan: %s' % e) if redirect: raise cherrypy.HTTPRedirect(redirect) @@ -923,7 +922,7 @@ class WebInterface(object): logger.info('Marking all unwanted albums as Skipped') try: threading.Thread(target=librarysync.libraryScan).start() - except Exception, e: + except Exception as e: logger.error('Unable to complete the scan: %s' % e) raise cherrypy.HTTPRedirect("home") forceScan.exposed = True