From d0198b15ee022d3f0bf66d4ec09ef85408749216 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 8 Apr 2014 22:39:25 +0200 Subject: [PATCH 01/11] Restructured imports of post processor --- headphones/postprocessor.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 8e7dccb4..6b56d510 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -16,19 +16,19 @@ from __future__ import with_statement import os -import time -import threading -import music_encoder -import shutil, re +import re +import shutil import uuid -from headphones import notifiers import beets +import threading +import headphones + from beets import autotag from beets.mediafile import MediaFile -import headphones -from headphones import db, albumart, librarysync, lyrics, logger, helpers, request -from headphones.helpers import sab_replace_dots, sab_replace_spaces +from headphones import notifiers +from headphones import db, albumart, librarysync, lyrics +from headphones import logger, helpers, request, mb, music_encoder postprocessor_lock = threading.Lock() @@ -48,9 +48,9 @@ def checkFolder(): # iterations in just in case we can't read the config for some reason nzb_album_possibilities = [ album['FolderName'], - sab_replace_dots(album['FolderName']), - sab_replace_spaces(album['FolderName']), - sab_replace_spaces(sab_replace_dots(album['FolderName'])) + helpers.sab_replace_dots(album['FolderName']), + helpers.sab_replace_spaces(album['FolderName']), + helpers.sab_replace_spaces(sab_replace_dots(album['FolderName'])) ] for nzb_folder_name in nzb_album_possibilities: @@ -80,8 +80,6 @@ def verify(albumid, albumpath, Kind=None, forced=False): #from an RSS feed or etc #TODO: This should be a call to a class method.. copied it out of importer with only minor changes #TODO: odd things can happen when there are diacritic characters in the folder name, need to translate them? - import mb - release_list = None try: @@ -1044,7 +1042,6 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): continue else: logger.info('Querying MusicBrainz for the release group id for: %s - %s', name, album) - from headphones import mb try: rgid = mb.findAlbumID(helpers.latinToAscii(name), helpers.latinToAscii(album)) except: @@ -1072,7 +1069,6 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): continue else: logger.info('Querying MusicBrainz for the release group id for: %s - %s', name, album) - from headphones import mb try: rgid = mb.findAlbumID(helpers.latinToAscii(name), helpers.latinToAscii(album)) except: @@ -1116,7 +1112,6 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): continue else: logger.info('Querying MusicBrainz for the release group id for: %s', folder) - from headphones import mb try: rgid = mb.findAlbumID(album=helpers.latinToAscii(folder)) except: @@ -1129,3 +1124,4 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): else: logger.info('No match found on MusicBrainz for: %s - %s', name, album) + \ No newline at end of file From 0411bb6b446f8b9f34fc35a60552cf1f2cb498f3 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 8 Apr 2014 22:49:03 +0200 Subject: [PATCH 02/11] Importing with statement is for Python 2.5. Bases on libraries (e.g. beautifulsoup4), I guess the minimal version for Headphones is at least 2.6 --- headphones/__init__.py | 5 +---- headphones/mb.py | 2 -- headphones/postprocessor.py | 2 -- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/headphones/__init__.py b/headphones/__init__.py index 47588ec4..6e7fd194 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -15,20 +15,17 @@ # NZBGet support added by CurlyMo as a part of XBian - XBMC on the Raspberry Pi -from __future__ import with_statement - import os, sys, subprocess import threading import webbrowser import sqlite3 import itertools +import cherrypy from lib.apscheduler.scheduler import Scheduler from lib.configobj import ConfigObj -import cherrypy - from headphones import versioncheck, logger, version from headphones.common import * diff --git a/headphones/mb.py b/headphones/mb.py index 25061bf3..ff4ac42d 100644 --- a/headphones/mb.py +++ b/headphones/mb.py @@ -13,8 +13,6 @@ # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . -from __future__ import with_statement - import time import threading diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 6b56d510..cf64258f 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -13,8 +13,6 @@ # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . -from __future__ import with_statement - import os import re import shutil From 60ea86d4995d3d9a5de79053da22246e97db4cf4 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Wed, 9 Apr 2014 17:10:46 +0200 Subject: [PATCH 03/11] Correct indent. Use signum is not None instead of type(signum) != type(None) --- headphones/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headphones/__init__.py b/headphones/__init__.py index 6e7fd194..3c3f9a36 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -1090,7 +1090,7 @@ def start(): started = True def sig_handler(signum=None, frame=None): - if type(signum) != type(None): + if signum is not None: logger.info("Signal %i caught, saving and exiting...", signum) shutdown() From 65fa0e21fa761fc887cdd3f87b95d42885f3aaea Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Wed, 9 Apr 2014 17:11:35 +0200 Subject: [PATCH 04/11] Do not decode for logger. --- headphones/postprocessor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index cf64258f..3d8a315f 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -742,13 +742,13 @@ def moveFiles(albumpath, release, tracks): try: os.chmod(os.path.normpath(temp_f).encode(headphones.SYS_ENCODING, 'replace'), int(headphones.FOLDER_PERMISSIONS, 8)) except Exception, e: - logger.error("Error trying to change permissions on folder: %s" % temp_f.decode(headphones.SYS_ENCODING, 'replace')) + 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: - logger.error('Could not remove directory: %s. %s' % (albumpath.decode(headphones.SYS_ENCODING, 'replace'), e)) + logger.error('Could not remove directory: %s. %s', albumpath, e) destination_paths = [] From eb7a1d71179be67513285a63de252653fb655807 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Wed, 9 Apr 2014 17:21:25 +0200 Subject: [PATCH 05/11] Updated methods to log messages new style --- headphones/helpers.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/headphones/helpers.py b/headphones/helpers.py index 438dc7d7..a90018cf 100644 --- a/headphones/helpers.py +++ b/headphones/helpers.py @@ -274,7 +274,7 @@ def expand_subfolders(f): difference = max(path_depths) - min(path_depths) if difference > 0: - logger.info("Found %d media folders, but depth difference between lowest and deepest media folder is %d (expected zero). If this is a discography or a collection of albums, make sure albums are per folder" % (len(media_folders), difference)) + logger.info("Found %d media folders, but depth difference between lowest and deepest media folder is %d (expected zero). If this is a discography or a collection of albums, make sure albums are per folder.", len(media_folders), difference) # While already failed, advice the user what he could try. We assume the # directory may contain separate CD's and maybe some extra's. The @@ -283,7 +283,7 @@ def expand_subfolders(f): extra_media_folders = [ media_folder[:min(path_depths)] for media_folder in media_folders if len(media_folder) > min(path_depths) ] extra_media_folders = list(set([ os.path.join(*media_folder) for media_folder in extra_media_folders ])) - logger.info("Please look at the following folder(s), since they cause the depth difference: %s" % extra_media_folders) + logger.info("Please look at the following folder(s), since they cause the depth difference: %s", extra_media_folders) return # Convert back to paths and remove duplicates, which may be there after @@ -297,7 +297,7 @@ def expand_subfolders(f): logger.debug("Did not expand subfolder, as it resulted in one folder.") return - logger.debug("Expanded subfolders in folder: " % media_folders) + logger.debug("Expanded subfolders in folder: %s", media_folders) return media_folders def extract_data(s): @@ -374,14 +374,14 @@ def extract_metadata(f): # Verify results if len(results) == 0: - logger.info("No metadata in media files found, ignoring") + logger.info("No metadata in media files found, ignoring.") return (None, None, None) # Require that some percentage of files have tags count_ratio = 0.75 if count < (count_ratio * len(results)): - logger.info("Counted %d media files, but only %d have tags, ignoring" % (count, len(results))) + logger.info("Counted %d media files, but only %d have tags, ignoring.", count, len(results)) return (None, None, None) # Count distinct values @@ -399,7 +399,7 @@ def extract_metadata(f): old_album = new_albums[index] new_albums[index] = RE_CD_ALBUM.sub("", album).strip() - logger.debug("Stripped albumd number identifier: %s -> %s" % (old_album, new_albums[index])) + logger.debug("Stripped albumd number identifier: %s -> %s", old_album, new_albums[index]) # Remove duplicates new_albums = list(set(new_albums)) @@ -417,7 +417,7 @@ def extract_metadata(f): if len(artists) > 1 and len(albums) == 1: split_artists = [ RE_FEATURING.split(artist) for artist in artists ] featurings = [ len(split_artist) - 1 for split_artist in split_artists ] - logger.info("Album seem to feature %d different artists" % sum(featurings)) + logger.info("Album seem to feature %d different artists", sum(featurings) if sum(featurings) > 0: # Find the artist of which the least splits have been generated. @@ -429,8 +429,8 @@ def extract_metadata(f): return (artist, albums[0], years[0]) # Not sure what to do here. - logger.info("Found %d artists, %d albums and %d years in metadata, so ignoring" % (len(artists), len(albums), len(years))) - logger.debug("Artists: %s, Albums: %s, Years: %s" % (artists, albums, years)) + logger.info("Found %d artists, %d albums and %d years in metadata, so ignoring", len(artists), len(albums), len(years)) + logger.debug("Artists: %s, Albums: %s, Years: %s", artists, albums, years) return (None, None, None) @@ -486,7 +486,7 @@ def smartMove(src, dest, delete=True): filename = os.path.basename(src) if os.path.isfile(os.path.join(dest, filename)): - logger.info('Destination file exists: %s', os.path.join(dest, filename).decode(headphones.SYS_ENCODING, 'replace')) + logger.info('Destination file exists: %s', os.path.join(dest, filename)) title = os.path.splitext(filename)[0] ext = os.path.splitext(filename)[1] i = 1 From a0339d981415521b3e34506dd2d836ac469c3c49 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Thu, 10 Apr 2014 01:23:09 +0200 Subject: [PATCH 06/11] Forgot a parenthesis --- headphones/helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headphones/helpers.py b/headphones/helpers.py index a90018cf..7de2ad36 100644 --- a/headphones/helpers.py +++ b/headphones/helpers.py @@ -417,7 +417,7 @@ def extract_metadata(f): if len(artists) > 1 and len(albums) == 1: split_artists = [ RE_FEATURING.split(artist) for artist in artists ] featurings = [ len(split_artist) - 1 for split_artist in split_artists ] - logger.info("Album seem to feature %d different artists", sum(featurings) + logger.info("Album seem to feature %d different artists", sum(featurings)) if sum(featurings) > 0: # Find the artist of which the least splits have been generated. From f7ba0ff63421dbbc3670b6fd6aa1cae592e13bc2 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Sat, 12 Apr 2014 18:56:40 +0200 Subject: [PATCH 07/11] All loggers on the same level. In the issues, a lot of logs do not include DEBUG info, even if started with verbose turned on. By defaulting all loggers to INFO, but DEBUG if verbose is 2, I hope this will improve. This will disable DEBUG for log file, but I assume verbose is turned on in case of problems, so it will save disk writings. --- headphones/logger.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/headphones/logger.py b/headphones/logger.py index c10aac58..b2ea73db 100644 --- a/headphones/logger.py +++ b/headphones/logger.py @@ -55,7 +55,7 @@ def initLogger(verbose=1): # Configure the logger to accept all messages logger.propagate = False - logger.setLevel(logging.DEBUG) + logger.setLevel(logging.DEBUG if verbose == 2 else logging.INFO) # Setup file logger filename = os.path.join(headphones.LOG_DIR, FILENAME) @@ -69,7 +69,7 @@ def initLogger(verbose=1): # Add list logger loglist_handler = LogListHandler() - loglist_handler.setLevel(logging.INFO) + loglist_handler.setLevel(logging.DEBUG) logger.addHandler(loglist_handler) @@ -78,11 +78,7 @@ def initLogger(verbose=1): console_formatter = logging.Formatter('%(asctime)s - %(levelname)s :: %(threadName)s : %(message)s', '%d-%b-%Y %H:%M:%S') console_handler = logging.StreamHandler() console_handler.setFormatter(console_formatter) - - if verbose == 1: - console_handler.setLevel(logging.INFO) - elif verbose == 2: - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(logging.DEBUG) logger.addHandler(console_handler) From a96b793c9848cf40e3355dd7c7e6bec36fd2bf16 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Sat, 12 Apr 2014 18:59:08 +0200 Subject: [PATCH 08/11] Add color for warnings. Some distinction between the levels is handy. --- data/interfaces/default/css/data_table.css | 7 +++++++ data/interfaces/default/logs.html | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/data/interfaces/default/css/data_table.css b/data/interfaces/default/css/data_table.css index 08c6de4c..348179c3 100644 --- a/data/interfaces/default/css/data_table.css +++ b/data/interfaces/default/css/data_table.css @@ -254,6 +254,13 @@ table.display tr.even.gradeU { background-color: #eee; } +table.display tr.odd.gradeW { + background-color: #ffffaa; +} + +table.display tr.even.gradeW { + background-color: #ffffaa; +} table.display tr.odd.gradeZ { background-color: #FAFAFA; diff --git a/data/interfaces/default/logs.html b/data/interfaces/default/logs.html index e6ed4aeb..1978b54e 100644 --- a/data/interfaces/default/logs.html +++ b/data/interfaces/default/logs.html @@ -56,10 +56,14 @@ $(document).ready(function() { "sInfoEmpty":"Showing 0 to 0 of 0 lines", "sInfoFiltered":"(filtered from _MAX_ total lines)"}, "fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) { - if (aData[1] === "WARNING" || aData[1] === "ERROR") + if (aData[1] === "ERROR") { $('td', nRow).closest('tr').addClass("gradeX"); } + else if (aData[1] === "WARNING") + { + $('td', nRow).closest('tr').addClass("gradeW"); + } else { $('td', nRow).closest('tr').addClass("gradeZ"); From e2e1ef9bc6ab3d1c0864086319c1712a40c79f0e Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Sat, 12 Apr 2014 20:27:38 +0200 Subject: [PATCH 09/11] Add clear log option. Improved styling. --- data/interfaces/default/logs.html | 19 ++++++++++++++----- headphones/webserve.py | 5 +++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/data/interfaces/default/logs.html b/data/interfaces/default/logs.html index 1978b54e..35f09f88 100644 --- a/data/interfaces/default/logs.html +++ b/data/interfaces/default/logs.html @@ -1,10 +1,18 @@ -lossless<%inherit file="base.html"/> +<%inherit file="base.html"/> <%! from headphones import helpers %> +<%def name="headerIncludes()"> +
+ +
+ + <%def name="body()"> -
+

Logs

@@ -40,6 +48,8 @@ lossless<%inherit file="base.html"/>