diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 5ac2380db..3fa98758c 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -14,8 +14,8 @@ """Facilities for automatically determining files' correct metadata. """ -import logging +from beets import logging from beets import config # Parts of external interface. diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index beb3bd91b..5118212b4 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -13,10 +13,10 @@ # included in all copies or substantial portions of the Software. """Glue between metadata sources and the matching logic.""" -import logging from collections import namedtuple import re +from beets import logging from beets import plugins from beets import config from beets.autotag import mb diff --git a/beets/autotag/match.py b/beets/autotag/match.py index 2d1f20074..d51cd4fb1 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -18,10 +18,10 @@ releases and tracks. from __future__ import division import datetime -import logging import re from munkres import Munkres +from beets import logging from beets import plugins from beets import config from beets.util import plurality @@ -267,7 +267,7 @@ def match_by_id(items): # If all album IDs are equal, look up the album. if bool(reduce(lambda x, y: x if x == y else (), albumids)): albumid = albumids[0] - log.debug(u'Searching for discovered album ID: {0}'.format(albumid)) + log.debug(u'Searching for discovered album ID: {0}', albumid) return hooks.album_for_mbid(albumid) else: log.debug(u'No album ID consensus.') @@ -330,7 +330,7 @@ def _add_candidate(items, results, info): checking the track count, ordering the items, checking for duplicates, and calculating the distance. """ - log.debug(u'Candidate: {0} - {1}'.format(info.artist, info.album)) + log.debug(u'Candidate: {0} - {1}', info.artist, info.album) # Discard albums with zero tracks. if not info.tracks: @@ -345,7 +345,7 @@ def _add_candidate(items, results, info): # Discard matches without required tags. for req_tag in config['match']['required'].as_str_seq(): if getattr(info, req_tag) is None: - log.debug(u'Ignored. Missing required tag: {0}'.format(req_tag)) + log.debug(u'Ignored. Missing required tag: {0}', req_tag) return # Find mapping between the items and the track info. @@ -358,10 +358,10 @@ def _add_candidate(items, results, info): penalties = [key for _, key in dist] for penalty in config['match']['ignored'].as_str_seq(): if penalty in penalties: - log.debug(u'Ignored. Penalty: {0}'.format(penalty)) + log.debug(u'Ignored. Penalty: {0}', penalty) return - log.debug(u'Success. Distance: {0}'.format(dist)) + log.debug(u'Success. Distance: {0}', dist) results[info.album_id] = hooks.AlbumMatch(dist, info, mapping, extra_items, extra_tracks) @@ -387,7 +387,7 @@ def tag_album(items, search_artist=None, search_album=None, likelies, consensus = current_metadata(items) cur_artist = likelies['artist'] cur_album = likelies['album'] - log.debug(u'Tagging {0} - {1}'.format(cur_artist, cur_album)) + log.debug(u'Tagging {0} - {1}', cur_artist, cur_album) # The output result (distance, AlbumInfo) tuples (keyed by MB album # ID). @@ -395,7 +395,7 @@ def tag_album(items, search_artist=None, search_album=None, # Search by explicit ID. if search_id is not None: - log.debug(u'Searching for album ID: {0}'.format(search_id)) + log.debug(u'Searching for album ID: {0}', search_id) search_cands = hooks.albums_for_id(search_id) # Use existing metadata or text search. @@ -405,7 +405,7 @@ def tag_album(items, search_artist=None, search_album=None, if id_info: _add_candidate(items, candidates, id_info) rec = _recommendation(candidates.values()) - log.debug(u'Album ID match recommendation is {0}'.format(str(rec))) + log.debug(u'Album ID match recommendation is {0}', str(rec)) if candidates and not config['import']['timid']: # If we have a very good MBID match, return immediately. # Otherwise, this match will compete against metadata-based @@ -418,20 +418,19 @@ def tag_album(items, search_artist=None, search_album=None, if not (search_artist and search_album): # No explicit search terms -- use current metadata. search_artist, search_album = cur_artist, cur_album - log.debug(u'Search terms: {0} - {1}'.format(search_artist, - search_album)) + log.debug(u'Search terms: {0} - {1}', search_artist, search_album) # Is this album likely to be a "various artist" release? va_likely = ((not consensus['artist']) or (search_artist.lower() in VA_ARTISTS) or any(item.comp for item in items)) - log.debug(u'Album might be VA: {0}'.format(str(va_likely))) + log.debug(u'Album might be VA: {0}', str(va_likely)) # Get the results from the data sources. search_cands = hooks.album_candidates(items, search_artist, search_album, va_likely) - log.debug(u'Evaluating {0} candidates.'.format(len(search_cands))) + log.debug(u'Evaluating {0} candidates.', len(search_cands)) for info in search_cands: _add_candidate(items, candidates, info) @@ -456,7 +455,7 @@ def tag_item(item, search_artist=None, search_title=None, # First, try matching by MusicBrainz ID. trackid = search_id or item.mb_trackid if trackid: - log.debug(u'Searching for track ID: {0}'.format(trackid)) + log.debug(u'Searching for track ID: {0}', trackid) for track_info in hooks.tracks_for_id(trackid): dist = track_distance(item, track_info, incl_artist=True) candidates[track_info.track_id] = \ @@ -477,8 +476,7 @@ def tag_item(item, search_artist=None, search_title=None, # Search terms. if not (search_artist and search_title): search_artist, search_title = item.artist, item.title - log.debug(u'Item search terms: {0} - {1}'.format(search_artist, - search_title)) + log.debug(u'Item search terms: {0} - {1}', search_artist, search_title) # Get and evaluate candidate metadata. for track_info in hooks.item_candidates(item, search_artist, search_title): @@ -486,7 +484,7 @@ def tag_item(item, search_artist=None, search_title=None, candidates[track_info.track_id] = hooks.TrackMatch(dist, track_info) # Sort by distance and return with recommendation. - log.debug(u'Found {0} candidates.'.format(len(candidates))) + log.debug(u'Found {0} candidates.', len(candidates)) candidates = sorted(candidates.itervalues()) rec = _recommendation(candidates) return candidates, rec diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py index d063f6278..7c598a17f 100644 --- a/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -14,12 +14,12 @@ """Searches for albums in the MusicBrainz database. """ -import logging import musicbrainzngs import re import traceback from urlparse import urljoin +from beets import logging import beets.autotag.hooks import beets from beets import util @@ -374,7 +374,7 @@ def album_for_id(releaseid): """ albumid = _parse_id(releaseid) if not albumid: - log.debug(u'Invalid MBID ({0}).'.format(releaseid)) + log.debug(u'Invalid MBID ({0}).', releaseid) return try: res = musicbrainzngs.get_release_by_id(albumid, @@ -394,7 +394,7 @@ def track_for_id(releaseid): """ trackid = _parse_id(releaseid) if not trackid: - log.debug(u'Invalid MBID ({0}).'.format(releaseid)) + log.debug(u'Invalid MBID ({0}).', releaseid) return try: res = musicbrainzngs.get_recording_by_id(trackid, TRACK_INCLUDES) diff --git a/beets/importer.py b/beets/importer.py index 4a7bd997f..a0f100749 100644 --- a/beets/importer.py +++ b/beets/importer.py @@ -19,7 +19,6 @@ from __future__ import print_function import os import re -import logging import pickle import itertools from collections import defaultdict @@ -28,6 +27,7 @@ from bisect import insort, bisect_left from contextlib import contextmanager import shutil +from beets import logging from beets import autotag from beets import library from beets import dbcore @@ -71,7 +71,7 @@ def _open_state(): # unpickling, including ImportError. We use a catch-all # exception to avoid enumerating them all (the docs don't even have a # full list!). - log.debug(u'state file could not be read: {0}'.format(exc)) + log.debug(u'state file could not be read: {0}', exc) return {} @@ -81,7 +81,7 @@ def _save_state(state): with open(config['statefile'].as_filename(), 'w') as f: pickle.dump(state, f) except IOError as exc: - log.error(u'state file could not be written: {0}'.format(exc)) + log.error(u'state file could not be written: {0}', exc) # Utilities for reading and writing the beets progress file, which @@ -347,8 +347,8 @@ class ImportSession(object): # Either accept immediately or prompt for input to decide. if self.want_resume is True or \ self.should_resume(toppath): - log.warn(u'Resuming interrupted import of {0}'.format( - util.displayable_path(toppath))) + log.warn(u'Resuming interrupted import of {0}', + util.displayable_path(toppath)) self._is_resuming[toppath] = True else: # Clear progress; we're starting from the top. @@ -481,13 +481,12 @@ class ImportTask(object): def remove_duplicates(self, lib): duplicate_items = self.duplicate_items(lib) - log.debug(u'removing {0} old duplicated items' - .format(len(duplicate_items))) + log.debug(u'removing {0} old duplicated items', len(duplicate_items)) for item in duplicate_items: item.remove() if lib.directory in util.ancestry(item.path): - log.debug(u'deleting duplicate {0}' - .format(util.displayable_path(item.path))) + log.debug(u'deleting duplicate {0}', + util.displayable_path(item.path)) util.remove(item.path) util.prune_dirs(os.path.dirname(item.path), lib.directory) @@ -686,12 +685,11 @@ class ImportTask(object): self.album.store() log.debug( u'Reimported album: added {0}, flexible ' - u'attributes {1} from album {2} for {3}'.format( - self.album.added, - replaced_album._values_flex.keys(), - replaced_album.id, - displayable_path(self.album.path), - ) + u'attributes {1} from album {2} for {3}', + self.album.added, + replaced_album._values_flex.keys(), + replaced_album.id, + displayable_path(self.album.path) ) for item in self.imported_items(): @@ -701,20 +699,18 @@ class ImportTask(object): item.added = dup_item.added log.debug( u'Reimported item added {0} ' - u'from item {1} for {2}'.format( - item.added, - dup_item.id, - displayable_path(item.path), - ) + u'from item {1} for {2}', + item.added, + dup_item.id, + displayable_path(item.path) ) item.update(dup_item._values_flex) log.debug( u'Reimported item flexible attributes {0} ' - u'from item {1} for {2}'.format( - dup_item._values_flex.keys(), - dup_item.id, - displayable_path(item.path), - ) + u'from item {1} for {2}', + dup_item._values_flex.keys(), + dup_item.id, + displayable_path(item.path) ) item.store() @@ -724,13 +720,12 @@ class ImportTask(object): """ for item in self.imported_items(): for dup_item in self.replaced_items[item]: - log.debug(u'Replacing item {0}: {1}' - .format(dup_item.id, - displayable_path(item.path))) + log.debug(u'Replacing item {0}: {1}', + dup_item.id, displayable_path(item.path)) dup_item.remove() - log.debug(u'{0} of {1} items replaced' - .format(sum(bool(l) for l in self.replaced_items.values()), - len(self.imported_items()))) + log.debug(u'{0} of {1} items replaced', + sum(bool(l) for l in self.replaced_items.values()), + len(self.imported_items())) def choose_match(self, session): """Ask the session which match should apply and apply it. @@ -1002,8 +997,8 @@ class ImportTaskFactory(object): def singleton(self, path): if self.session.already_imported(self.toppath, [path]): - log.debug(u'Skipping previously-imported path: {0}' - .format(displayable_path(path))) + log.debug(u'Skipping previously-imported path: {0}', + displayable_path(path)) self.skipped += 1 return None @@ -1026,8 +1021,8 @@ class ImportTaskFactory(object): dirs = list(set(os.path.dirname(p) for p in paths)) if self.session.already_imported(self.toppath, dirs): - log.debug(u'Skipping previously-imported path: {0}' - .format(displayable_path(dirs))) + log.debug(u'Skipping previously-imported path: {0}', + displayable_path(dirs)) self.skipped += 1 return None @@ -1055,14 +1050,10 @@ class ImportTaskFactory(object): # Silently ignore non-music files. pass elif isinstance(exc.reason, mediafile.UnreadableFileError): - log.warn(u'unreadable file: {0}'.format( - displayable_path(path)) - ) + log.warn(u'unreadable file: {0}', displayable_path(path)) else: - log.error(u'error reading {0}: {1}'.format( - displayable_path(path), - exc, - )) + log.error(u'error reading {0}: {1}', + displayable_path(path), exc) # Full-album pipeline stages. @@ -1086,13 +1077,13 @@ def read_tasks(session): "'copy' or 'move' to be enabled.") continue - log.debug(u'extracting archive {0}' - .format(displayable_path(toppath))) + log.debug(u'extracting archive {0}', + displayable_path(toppath)) archive_task = ArchiveImportTask(toppath) try: archive_task.extract() except Exception as exc: - log.error(u'extraction failed: {0}'.format(exc)) + log.error(u'extraction failed: {0}', exc) continue # Continue reading albums from the extracted directory. @@ -1112,12 +1103,12 @@ def read_tasks(session): yield archive_task if not imported: - log.warn(u'No files imported from {0}' - .format(displayable_path(user_toppath))) + log.warn(u'No files imported from {0}', + displayable_path(user_toppath)) # Show skipped directories. if skipped: - log.info(u'Skipped {0} directories.'.format(skipped)) + log.info(u'Skipped {0} directories.', skipped) def query_tasks(session): @@ -1133,8 +1124,8 @@ def query_tasks(session): else: # Search for albums. for album in session.lib.albums(session.query): - log.debug(u'yielding album {0}: {1} - {2}' - .format(album.id, album.albumartist, album.album)) + log.debug(u'yielding album {0}: {1} - {2}', + album.id, album.albumartist, album.album) items = list(album.items()) # Clear IDs from re-tagged items so they appear "fresh" when @@ -1159,7 +1150,7 @@ def lookup_candidates(session, task): return plugins.send('import_task_start', session=session, task=task) - log.debug(u'Looking up: {0}'.format(displayable_path(task.paths))) + log.debug(u'Looking up: {0}', displayable_path(task.paths)) task.lookup_candidates() @@ -1300,12 +1291,11 @@ def log_files(session, task): """A coroutine (pipeline stage) to log each file which will be imported """ if isinstance(task, SingletonImportTask): - log.info( - 'Singleton: {0}'.format(displayable_path(task.item['path']))) + log.info('Singleton: {0}', displayable_path(task.item['path'])) elif task.items: - log.info('Album {0}'.format(displayable_path(task.paths[0]))) + log.info('Album {0}', displayable_path(task.paths[0])) for item in task.items: - log.info(' {0}'.format(displayable_path(item['path']))) + log.info(' {0}', displayable_path(item['path'])) def group_albums(session): diff --git a/beets/library.py b/beets/library.py index 1de1bba56..180f029cb 100644 --- a/beets/library.py +++ b/beets/library.py @@ -16,12 +16,13 @@ """ import os import sys -import logging import shlex import unicodedata import time import re from unidecode import unidecode + +from beets import logging from beets.mediafile import MediaFile, MutagenError, UnreadableFileError from beets import plugins from beets import util @@ -509,7 +510,7 @@ class Item(LibModel): self.write(path) return True except FileOperationError as exc: - log.error(exc) + log.error(str(exc)) return False def try_sync(self, write=None): @@ -837,9 +838,9 @@ class Album(LibModel): return new_art = util.unique_path(new_art) - log.debug(u'moving album art {0} to {1}' - .format(util.displayable_path(old_art), - util.displayable_path(new_art))) + log.debug(u'moving album art {0} to {1}', + util.displayable_path(old_art), + util.displayable_path(new_art)) if copy: util.copy(old_art, new_art) elif link: diff --git a/beets/logging.py b/beets/logging.py new file mode 100644 index 000000000..48c9d4625 --- /dev/null +++ b/beets/logging.py @@ -0,0 +1,72 @@ +"""Allow {}-style logging on python 2 and 3 + +Provide everything the "logging" module does, the only difference is that when +getLogger(name) instantiates a logger that logger uses {}-style formatting. + +It requires special hacks for python 2.6 due to logging.Logger being an old- +style class and having no loggerClass attribute. +""" + +from __future__ import absolute_import +from copy import copy +from logging import * # noqa +import sys + + +# create a str.format-based logger +class StrFormatLogger(Logger): + class _LogMessage(object): + def __init__(self, msg, args, kwargs): + self.msg = msg + self.args = args + self.kwargs = kwargs + + def __str__(self): + return self.msg.format(*self.args, **self.kwargs) + + def _log(self, level, msg, args, exc_info=None, extra=None, **kwargs): + """Log msg.format(*args, **kwargs)""" + m = self._LogMessage(msg, args, kwargs) + return Logger._log(self, level, m, (), exc_info, extra) + # we cannot call super(StrFormatLogger, self) because it is not + # allowed on old-style classes (py2) which Logger is in python 2.6 + # moreover we cannot make StrFormatLogger a new-style class (by + # declaring 'class StrFormatLogger(Logger, object)' because the class- + # patching stmt 'logger.__class__ = StrFormatLogger' would not work: + # both prev & new __class__ values must be either old- or new- style, + # no mixing allowed. + + if sys.version_info[:2] == (2, 6): + def getChild(self, suffix): + """Shameless copy from cpython's Lib/logging/__init__.py""" + if self.root is not self: + suffix = '.'.join((self.name, suffix)) + return self.manager.getLogger(suffix) + +my_manager = copy(Logger.manager) +my_manager.loggerClass = StrFormatLogger + + +def getLogger(name=None): + if name: + return my_manager.getLogger(name) + else: + return Logger.root + + +if sys.version_info[:2] == (2, 6): + # no Manager.loggerClass so we dynamically change the logger class + # we must be careful to do that on new loggers only to avoid side-effects. + # Wrap Manager.getLogger + old_getLogger = my_manager.getLogger + + def new_getLogger(name): + change_its_type = not isinstance(my_manager.loggerDict.get(name), + Logger) + # it either does not exist or is a placeholder + logger = old_getLogger(name) + if change_its_type: + logger.__class__ = StrFormatLogger + return logger + + my_manager.getLogger = new_getLogger diff --git a/beets/mediafile.py b/beets/mediafile.py index 49ef10378..3e3d2aa23 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -48,10 +48,10 @@ import math import struct import imghdr import os -import logging import traceback import enum +from beets import logging from beets.util import displayable_path @@ -1313,7 +1313,7 @@ class MediaFile(object): try: self.mgfile = mutagen.File(path) except unreadable_exc as exc: - log.debug(u'header parsing failed: {0}'.format(unicode(exc))) + log.debug(u'header parsing failed: {0}', unicode(exc)) raise UnreadableFileError(path) except IOError as exc: if type(exc) == IOError: @@ -1326,7 +1326,7 @@ class MediaFile(object): except Exception as exc: # Isolate bugs in Mutagen. log.debug(traceback.format_exc()) - log.error(u'uncaught Mutagen exception in open: {0}'.format(exc)) + log.error(u'uncaught Mutagen exception in open: {0}', exc) raise MutagenError(path, exc) if self.mgfile is None: @@ -1399,7 +1399,7 @@ class MediaFile(object): raise except Exception as exc: log.debug(traceback.format_exc()) - log.error(u'uncaught Mutagen exception in save: {0}'.format(exc)) + log.error(u'uncaught Mutagen exception in save: {0}', exc) raise MutagenError(self.path, exc) def delete(self): diff --git a/beets/plugins.py b/beets/plugins.py index 8611b92a6..a975145db 100755 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -14,7 +14,6 @@ """Support for beets plugins.""" -import logging import traceback import inspect import re @@ -22,6 +21,7 @@ from collections import defaultdict import beets +from beets import logging from beets import mediafile PLUGIN_NAMESPACE = 'beetsplug' @@ -204,7 +204,7 @@ def load_plugins(names=()): except ImportError as exc: # Again, this is hacky: if exc.args[0].endswith(' ' + name): - log.warn(u'** plugin {0} not found'.format(name)) + log.warn(u'** plugin {0} not found', name) else: raise else: @@ -214,7 +214,7 @@ def load_plugins(names=()): _classes.add(obj) except: - log.warn(u'** error loading plugin {0}'.format(name)) + log.warn(u'** error loading plugin {0}', name) log.warn(traceback.format_exc()) @@ -398,7 +398,7 @@ def send(event, **arguments): Returns a list of return values from the handlers. """ - log.debug(u'Sending event: {0}'.format(event)) + log.debug(u'Sending event: {0}', event) for handler in event_handlers()[event]: # Don't break legacy plugins if we want to pass more arguments argspec = inspect.getargspec(handler).args diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index 8978ff547..a69b98ac2 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -23,7 +23,6 @@ import optparse import textwrap import sys from difflib import SequenceMatcher -import logging import sqlite3 import errno import re @@ -31,6 +30,7 @@ import struct import traceback import os.path +from beets import logging from beets import library from beets import plugins from beets import util @@ -866,14 +866,14 @@ def _configure(options): config_path = config.user_config_path() if os.path.isfile(config_path): - log.debug(u'user configuration: {0}'.format( - util.displayable_path(config_path))) + log.debug(u'user configuration: {0}', + util.displayable_path(config_path)) else: - log.debug(u'no user configuration found at {0}'.format( - util.displayable_path(config_path))) + log.debug(u'no user configuration found at {0}', + util.displayable_path(config_path)) - log.debug(u'data directory: {0}' - .format(util.displayable_path(config.config_dir()))) + log.debug(u'data directory: {0}', + util.displayable_path(config.config_dir())) return config @@ -895,9 +895,9 @@ def _open_library(config): util.displayable_path(dbpath) )) log.debug(u'library database: {0}\n' - u'library directory: {1}' - .format(util.displayable_path(lib.path), - util.displayable_path(lib.directory))) + u'library directory: {1}', + util.displayable_path(lib.path), + util.displayable_path(lib.directory)) return lib @@ -945,7 +945,7 @@ def main(args=None): _raw_main(args) except UserError as exc: message = exc.args[0] if exc.args else None - log.error(u'error: {0}'.format(message)) + log.error(u'error: {0}', message) sys.exit(1) except util.HumanReadableException as exc: exc.log(log) @@ -957,7 +957,7 @@ def main(args=None): log.error(exc) sys.exit(1) except confit.ConfigError as exc: - log.error(u'configuration error: {0}'.format(exc)) + log.error(u'configuration error: {0}', exc) sys.exit(1) except IOError as exc: if exc.errno == errno.EPIPE: diff --git a/beets/ui/commands.py b/beets/ui/commands.py index 4dfac11c8..f68a5e7c2 100644 --- a/beets/ui/commands.py +++ b/beets/ui/commands.py @@ -17,7 +17,6 @@ interface. """ from __future__ import print_function -import logging import os import time import codecs @@ -38,6 +37,7 @@ from beets.util import syspath, normpath, ancestry, displayable_path from beets.util.functemplate import Template from beets import library from beets import config +from beets import logging from beets.util.confit import _package_path VARIOUS_ARTISTS = u'Various Artists' @@ -765,8 +765,8 @@ class TerminalImportSession(importer.ImportSession): """Decide what to do when a new album or item seems similar to one that's already in the library. """ - log.warn(u"This {0} is already in the library!" - .format("album" if task.is_album else "item")) + log.warn(u"This {0} is already in the library!", + ("album" if task.is_album else "item")) if config['import']['quiet']: # In quiet mode, don't prompt -- just skip. @@ -1015,16 +1015,16 @@ def update_items(lib, query, album, move, pretend): # Did the item change since last checked? if item.current_mtime() <= item.mtime: - log.debug(u'skipping {0} because mtime is up to date ({1})' - .format(displayable_path(item.path), item.mtime)) + log.debug(u'skipping {0} because mtime is up to date ({1})', + displayable_path(item.path), item.mtime) continue # Read new data. try: item.read() except library.ReadError as exc: - log.error(u'error reading {0}: {1}'.format( - displayable_path(item.path), exc)) + log.error(u'error reading {0}: {1}', + displayable_path(item.path), exc) continue # Special-case album artist when it matches track artist. (Hacky @@ -1066,7 +1066,7 @@ def update_items(lib, query, album, move, pretend): continue album = lib.get_album(album_id) if not album: # Empty albums have already been removed. - log.debug(u'emptied album {0}'.format(album_id)) + log.debug(u'emptied album {0}', album_id) continue first_item = album.items().get() @@ -1077,7 +1077,7 @@ def update_items(lib, query, album, move, pretend): # Move album art (and any inconsistent items). if move and lib.directory in ancestry(first_item.path): - log.debug(u'moving album {0}'.format(album_id)) + log.debug(u'moving album {0}', album_id) album.move() @@ -1299,8 +1299,7 @@ def modify_items(lib, mods, dels, query, write, move, album, confirm): if move: cur_path = obj.path if lib.directory in ancestry(cur_path): # In library? - log.debug(u'moving object {0}' - .format(displayable_path(cur_path))) + log.debug(u'moving object {0}', displayable_path(cur_path)) obj.move() obj.try_sync(write) @@ -1378,9 +1377,9 @@ def move_items(lib, dest, query, copy, album): action = 'Copying' if copy else 'Moving' entity = 'album' if album else 'item' - log.info(u'{0} {1} {2}s.'.format(action, len(objs), entity)) + log.info(u'{0} {1} {2}s.', action, len(objs), entity) for obj in objs: - log.debug(u'moving: {0}'.format(util.displayable_path(obj.path))) + log.debug(u'moving: {0}', util.displayable_path(obj.path)) obj.move(copy, basedir=dest) obj.store() @@ -1426,18 +1425,15 @@ def write_items(lib, query, pretend, force): for item in items: # Item deleted? if not os.path.exists(syspath(item.path)): - log.info(u'missing file: {0}'.format( - util.displayable_path(item.path) - )) + log.info(u'missing file: {0}', util.displayable_path(item.path)) continue # Get an Item object reflecting the "clean" (on-disk) state. try: clean_item = library.Item.from_path(item.path) except library.ReadError as exc: - log.error(u'error reading {0}: {1}'.format( - displayable_path(item.path), exc - )) + log.error(u'error reading {0}: {1}', + displayable_path(item.path), exc) continue # Check for and display changes. diff --git a/beets/util/artresizer.py b/beets/util/artresizer.py index f17fdc5b9..5b51392bd 100644 --- a/beets/util/artresizer.py +++ b/beets/util/artresizer.py @@ -20,7 +20,8 @@ import subprocess import os import re from tempfile import NamedTemporaryFile -import logging + +from beets import logging from beets import util # Resizing methods @@ -58,9 +59,8 @@ def pil_resize(maxwidth, path_in, path_out=None): """ path_out = path_out or temp_file_for(path_in) from PIL import Image - log.debug(u'artresizer: PIL resizing {0} to {1}'.format( - util.displayable_path(path_in), util.displayable_path(path_out) - )) + log.debug(u'artresizer: PIL resizing {0} to {1}', + util.displayable_path(path_in), util.displayable_path(path_out)) try: im = Image.open(util.syspath(path_in)) @@ -69,9 +69,8 @@ def pil_resize(maxwidth, path_in, path_out=None): im.save(path_out) return path_out except IOError: - log.error(u"PIL cannot create thumbnail for '{0}'".format( - util.displayable_path(path_in) - )) + log.error(u"PIL cannot create thumbnail for '{0}'", + util.displayable_path(path_in)) return path_in @@ -80,9 +79,8 @@ def im_resize(maxwidth, path_in, path_out=None): Return the output path of resized image. """ path_out = path_out or temp_file_for(path_in) - log.debug(u'artresizer: ImageMagick resizing {0} to {1}'.format( - util.displayable_path(path_in), util.displayable_path(path_out) - )) + log.debug(u'artresizer: ImageMagick resizing {0} to {1}', + util.displayable_path(path_in), util.displayable_path(path_out)) # "-resize widthxheight>" shrinks images with dimension(s) larger # than the corresponding width and/or height dimension(s). The > @@ -94,9 +92,8 @@ def im_resize(maxwidth, path_in, path_out=None): '-resize', '{0}x^>'.format(maxwidth), path_out ]) except subprocess.CalledProcessError: - log.warn(u'artresizer: IM convert failed for {0}'.format( - util.displayable_path(path_in) - )) + log.warn(u'artresizer: IM convert failed for {0}', + util.displayable_path(path_in)) return path_in return path_out @@ -134,7 +131,7 @@ class ArtResizer(object): specified, with an inferred method. """ self.method = self._check_method(method) - log.debug(u"artresizer: method is {0}".format(self.method)) + log.debug(u"artresizer: method is {0}", self.method) self.can_compare = self._can_compare() def resize(self, maxwidth, path_in, path_out=None): diff --git a/beetsplug/beatport.py b/beetsplug/beatport.py index b83aef2f7..39054aab1 100644 --- a/beetsplug/beatport.py +++ b/beetsplug/beatport.py @@ -14,12 +14,12 @@ """Adds Beatport release and track search support to the autotagger """ -import logging import re from datetime import datetime, timedelta import requests +from beets import logging from beets.autotag.hooks import AlbumInfo, TrackInfo, Distance from beets.plugins import BeetsPlugin @@ -194,7 +194,7 @@ class BeatportPlugin(BeetsPlugin): try: return self._get_releases(query) except BeatportAPIError as e: - log.debug(u'Beatport API Error: {0} (query: {1})'.format(e, query)) + log.debug(u'Beatport API Error: {0} (query: {1})', e, query) return [] def item_candidates(self, item, artist, title): @@ -205,14 +205,14 @@ class BeatportPlugin(BeetsPlugin): try: return self._get_tracks(query) except BeatportAPIError as e: - log.debug(u'Beatport API Error: {0} (query: {1})'.format(e, query)) + log.debug(u'Beatport API Error: {0} (query: {1})', e, query) return [] def album_for_id(self, release_id): """Fetches a release by its Beatport ID and returns an AlbumInfo object or None if the release is not found. """ - log.debug(u'Searching Beatport for release {0}'.format(release_id)) + log.debug(u'Searching Beatport for release {0}', release_id) match = re.search(r'(^|beatport\.com/release/.+/)(\d+)$', release_id) if not match: return None @@ -224,7 +224,7 @@ class BeatportPlugin(BeetsPlugin): """Fetches a track by its Beatport ID and returns a TrackInfo object or None if the track is not found. """ - log.debug(u'Searching Beatport for track {0}'.format(str(track_id))) + log.debug(u'Searching Beatport for track {0}', track_id) match = re.search(r'(^|beatport\.com/track/.+/)(\d+)$', track_id) if not match: return None diff --git a/beetsplug/bpd/__init__.py b/beetsplug/bpd/__init__.py index 7b550487c..b0b8ce6c2 100644 --- a/beetsplug/bpd/__init__.py +++ b/beetsplug/bpd/__init__.py @@ -21,13 +21,13 @@ from __future__ import print_function import re from string import Template import traceback -import logging import random import time import beets from beets.plugins import BeetsPlugin import beets.ui +from beets import logging from beets import vfs from beets.util import bluelet from beets.library import Item diff --git a/beetsplug/bpm.py b/beetsplug/bpm.py index d895ec5be..028af7eae 100644 --- a/beetsplug/bpm.py +++ b/beetsplug/bpm.py @@ -15,9 +15,8 @@ """Determine BPM by pressing a key to the rhythm.""" import time -import logging -from beets import ui +from beets import ui, logging from beets.plugins import BeetsPlugin log = logging.getLogger('beets') @@ -73,15 +72,15 @@ class BPMPlugin(BeetsPlugin): item = items[0] if item['bpm']: - log.info(u'Found bpm {0}'.format(item['bpm'])) + log.info(u'Found bpm {0}', item['bpm']) if not overwrite: return log.info(u'Press Enter {0} times to the rhythm or Ctrl-D ' - u'to exit'.format(self.config['max_strokes'].get(int))) + u'to exit', self.config['max_strokes'].get(int)) new_bpm = bpm(self.config['max_strokes'].get(int)) item['bpm'] = int(new_bpm) if write: item.try_write() item.store() - log.info(u'Added new bpm {0}'.format(item['bpm'])) + log.info(u'Added new bpm {0}', item['bpm']) diff --git a/beetsplug/bucket.py b/beetsplug/bucket.py index 64dcdf6ee..68d520395 100644 --- a/beetsplug/bucket.py +++ b/beetsplug/bucket.py @@ -16,10 +16,11 @@ """ from datetime import datetime -import logging import re import string from itertools import tee, izip + +from beets import logging from beets import plugins, ui log = logging.getLogger('beets') diff --git a/beetsplug/chroma.py b/beetsplug/chroma.py index 106d6df76..485bfba61 100644 --- a/beetsplug/chroma.py +++ b/beetsplug/chroma.py @@ -19,10 +19,10 @@ from beets import plugins from beets import ui from beets import util from beets import config +from beets import logging from beets.util import confit from beets.autotag import hooks import acoustid -import logging from collections import defaultdict API_KEY = '1vOwZtEn' @@ -64,19 +64,19 @@ def acoustid_match(path): try: duration, fp = acoustid.fingerprint_file(util.syspath(path)) except acoustid.FingerprintGenerationError as exc: - log.error(u'fingerprinting of {0} failed: {1}' - .format(util.displayable_path(repr(path)), str(exc))) + log.error(u'fingerprinting of {0} failed: {1}', + util.displayable_path(repr(path)), str(exc)) return None _fingerprints[path] = fp try: res = acoustid.lookup(API_KEY, fp, duration, meta='recordings releases') except acoustid.AcoustidError as exc: - log.debug(u'fingerprint matching {0} failed: {1}' - .format(util.displayable_path(repr(path)), str(exc))) + log.debug(u'fingerprint matching {0} failed: {1}', + util.displayable_path(repr(path)), exc) return None - log.debug(u'chroma: fingerprinted {0}' - .format(util.displayable_path(repr(path)))) + log.debug(u'chroma: fingerprinted {0}', + util.displayable_path(repr(path))) # Ensure the response is usable and parse it. if res['status'] != 'ok' or not res.get('results'): @@ -99,9 +99,8 @@ def acoustid_match(path): if 'releases' in recording: release_ids += [rel['id'] for rel in recording['releases']] - log.debug(u'chroma: matched recordings {0} on releases {1}'.format( - recording_ids, release_ids, - )) + log.debug(u'chroma: matched recordings {0} on releases {1}', + recording_ids, release_ids) _matches[path] = recording_ids, release_ids @@ -155,7 +154,7 @@ class AcoustidPlugin(plugins.BeetsPlugin): if album: albums.append(album) - log.debug(u'acoustid album candidates: {0}'.format(len(albums))) + log.debug(u'acoustid album candidates: {0}', len(albums)) return albums def item_candidates(self, item, artist, title): @@ -168,7 +167,7 @@ class AcoustidPlugin(plugins.BeetsPlugin): track = hooks.track_for_mbid(recording_id) if track: tracks.append(track) - log.debug(u'acoustid item candidates: {0}'.format(len(tracks))) + log.debug(u'acoustid item candidates: {0}', len(tracks)) return tracks def commands(self): @@ -230,11 +229,11 @@ def submit_items(userkey, items, chunksize=64): def submit_chunk(): """Submit the current accumulated fingerprint data.""" - log.info(u'submitting {0} fingerprints'.format(len(data))) + log.info(u'submitting {0} fingerprints', len(data)) try: acoustid.submit(API_KEY, userkey, data) except acoustid.AcoustidError as exc: - log.warn(u'acoustid submission error: {0}'.format(exc)) + log.warn(u'acoustid submission error: {0}', exc) del data[:] for item in items: @@ -279,34 +278,28 @@ def fingerprint_item(item, write=False): """ # Get a fingerprint and length for this track. if not item.length: - log.info(u'{0}: no duration available'.format( - util.displayable_path(item.path) - )) + log.info(u'{0}: no duration available', + util.displayable_path(item.path)) elif item.acoustid_fingerprint: if write: - log.info(u'{0}: fingerprint exists, skipping'.format( - util.displayable_path(item.path) - )) + log.info(u'{0}: fingerprint exists, skipping', + util.displayable_path(item.path)) else: - log.info(u'{0}: using existing fingerprint'.format( - util.displayable_path(item.path) - )) + log.info(u'{0}: using existing fingerprint', + util.displayable_path(item.path)) return item.acoustid_fingerprint else: - log.info(u'{0}: fingerprinting'.format( - util.displayable_path(item.path) - )) + log.info(u'{0}: fingerprinting', + util.displayable_path(item.path)) try: _, fp = acoustid.fingerprint_file(item.path) item.acoustid_fingerprint = fp if write: - log.info(u'{0}: writing fingerprint'.format( - util.displayable_path(item.path) - )) + log.info(u'{0}: writing fingerprint', + util.displayable_path(item.path)) item.try_write() if item._db: item.store() return item.acoustid_fingerprint except acoustid.FingerprintGenerationError as exc: - log.info(u'fingerprint generation failed: {0}' - .format(exc)) + log.info(u'fingerprint generation failed: {0}', exc) diff --git a/beetsplug/convert.py b/beetsplug/convert.py index 0b87fb71b..c9b83c03f 100644 --- a/beetsplug/convert.py +++ b/beetsplug/convert.py @@ -14,7 +14,6 @@ """Converts tracks or albums to external directory """ -import logging import os import threading import subprocess @@ -22,7 +21,7 @@ import tempfile import shlex from string import Template -from beets import ui, util, plugins, config +from beets import logging, ui, util, plugins, config from beets.plugins import BeetsPlugin from beetsplug.embedart import embed_item from beets.util.confit import ConfigTypeError @@ -92,7 +91,7 @@ def encode(command, source, dest, pretend=False): quiet = config['convert']['quiet'].get() if not quiet and not pretend: - log.info(u'Encoding {0}'.format(util.displayable_path(source))) + log.info(u'Encoding {0}', util.displayable_path(source)) # Substitute $source and $dest in the argument list. args = shlex.split(command) @@ -110,12 +109,11 @@ def encode(command, source, dest, pretend=False): util.command_output(args) except subprocess.CalledProcessError as exc: # Something went wrong (probably Ctrl+C), remove temporary files - log.info(u'Encoding {0} failed. Cleaning up...' - .format(util.displayable_path(source))) - log.debug(u'Command {0} exited with status {1}'.format( - exc.cmd.decode('utf8', 'ignore'), - exc.returncode, - )) + log.info(u'Encoding {0} failed. Cleaning up...', + util.displayable_path(source)) + log.debug(u'Command {0} exited with status {1}', + exc.cmd.decode('utf8', 'ignore'), + exc.returncode) util.remove(dest) util.prune_dirs(os.path.dirname(dest)) raise @@ -127,9 +125,8 @@ def encode(command, source, dest, pretend=False): ) if not quiet and not pretend: - log.info(u'Finished encoding {0}'.format( - util.displayable_path(source)) - ) + log.info(u'Finished encoding {0}', + util.displayable_path(source)) def should_transcode(item, format): @@ -173,21 +170,17 @@ def convert_item(dest_dir, keep_new, path_formats, format, pretend=False): util.mkdirall(dest) if os.path.exists(util.syspath(dest)): - log.info(u'Skipping {0} (target file exists)'.format( - util.displayable_path(item.path) - )) + log.info(u'Skipping {0} (target file exists)', + util.displayable_path(item.path)) continue if keep_new: if pretend: - log.info(u'mv {0} {1}'.format( - util.displayable_path(item.path), - util.displayable_path(original), - )) + log.info(u'mv {0} {1}', + util.displayable_path(item.path), + util.displayable_path(original)) else: - log.info(u'Moving to {0}'.format( - util.displayable_path(original)) - ) + log.info(u'Moving to {0}', util.displayable_path(original)) util.move(item.path, original) if should_transcode(item, format): @@ -197,15 +190,12 @@ def convert_item(dest_dir, keep_new, path_formats, format, pretend=False): continue else: if pretend: - log.info(u'cp {0} {1}'.format( - util.displayable_path(original), - util.displayable_path(converted), - )) + log.info(u'cp {0} {1}', + util.displayable_path(original), + util.displayable_path(converted)) else: # No transcoding necessary. - log.info(u'Copying {0}'.format( - util.displayable_path(item.path)) - ) + log.info(u'Copying {0}', util.displayable_path(item.path)) util.copy(original, converted) if pretend: @@ -281,19 +271,17 @@ def copy_album_art(album, dest_dir, path_formats, pretend=False): util.mkdirall(dest) if os.path.exists(util.syspath(dest)): - log.info(u'Skipping {0} (target file exists)'.format( - util.displayable_path(album.artpath) - )) + log.info(u'Skipping {0} (target file exists)', + util.displayable_path(album.artpath)) return if pretend: - log.info(u'cp {0} {1}'.format( - util.displayable_path(album.artpath), - util.displayable_path(dest), - )) + log.info(u'cp {0} {1}', + util.displayable_path(album.artpath), + util.displayable_path(dest)) else: - log.info(u'Copying cover art to {0}'.format( - util.displayable_path(dest))) + log.info(u'Copying cover art to {0}', + util.displayable_path(dest)) util.copy(album.artpath, dest) diff --git a/beetsplug/discogs.py b/beetsplug/discogs.py index 234d9b6cd..e3a55fbdd 100644 --- a/beetsplug/discogs.py +++ b/beetsplug/discogs.py @@ -15,6 +15,7 @@ """Adds Discogs album search support to the autotagger. Requires the discogs-client library. """ +from beets import logging from beets.autotag.hooks import AlbumInfo, TrackInfo, Distance from beets.plugins import BeetsPlugin from beets.util import confit @@ -22,7 +23,6 @@ from discogs_client import Release, Client from discogs_client.exceptions import DiscogsAPIError from requests.exceptions import ConnectionError import beets -import logging import re import time import json @@ -89,7 +89,7 @@ class DiscogsPlugin(BeetsPlugin): raise beets.ui.UserError('Discogs authorization failed') # Save the token for later use. - log.debug('Discogs token {0}, secret {1}'.format(token, secret)) + log.debug('Discogs token {0}, secret {1}', token, secret) with open(self._tokenfile(), 'w') as f: json.dump({'token': token, 'secret': secret}, f) @@ -117,10 +117,10 @@ class DiscogsPlugin(BeetsPlugin): try: return self.get_albums(query) except DiscogsAPIError as e: - log.debug(u'Discogs API Error: {0} (query: {1})'.format(e, query)) + log.debug(u'Discogs API Error: {0} (query: {1})', e, query) return [] except ConnectionError as e: - log.debug(u'HTTP Connection Error: {0}'.format(e)) + log.debug(u'HTTP Connection Error: {0}', e) return [] def album_for_id(self, album_id): @@ -130,7 +130,7 @@ class DiscogsPlugin(BeetsPlugin): if not self.discogs_client: return - log.debug(u'Searching Discogs for release {0}'.format(str(album_id))) + log.debug(u'Searching Discogs for release {0}', album_id) # Discogs-IDs are simple integers. We only look for those at the end # of an input string as to avoid confusion with other metadata plugins. # An optional bracket can follow the integer, as this is how discogs @@ -145,11 +145,11 @@ class DiscogsPlugin(BeetsPlugin): getattr(result, 'title') except DiscogsAPIError as e: if e.message != '404 Not Found': - log.debug(u'Discogs API Error: {0} (query: {1})' - .format(e, result._uri)) + log.debug(u'Discogs API Error: {0} (query: {1})', + e, result._uri) return None except ConnectionError as e: - log.debug(u'HTTP Connection Error: {0}'.format(e)) + log.debug(u'HTTP Connection Error: {0}', e) return None return self.get_album_info(result) @@ -294,7 +294,7 @@ class DiscogsPlugin(BeetsPlugin): if match: medium, index = match.groups() else: - log.debug(u'Invalid Discogs position: {0}'.format(position)) + log.debug(u'Invalid Discogs position: {0}', position) medium = index = None return medium or None, index or None diff --git a/beetsplug/duplicates.py b/beetsplug/duplicates.py index 8e0af4ab7..1d7b6f9f1 100644 --- a/beetsplug/duplicates.py +++ b/beetsplug/duplicates.py @@ -15,8 +15,8 @@ """List duplicate tracks or albums. """ import shlex -import logging +from beets import logging from beets.plugins import BeetsPlugin from beets.ui import decargs, print_obj, vararg_callback, Subcommand, UserError from beets.util import command_output, displayable_path, subprocess @@ -56,20 +56,20 @@ def _checksum(item, prog): key = args[0] checksum = getattr(item, key, False) if not checksum: - log.debug(u'{0}: key {1} on item {2} not cached: computing checksum' - .format(PLUGIN, key, displayable_path(item.path))) + log.debug(u'{0}: key {1} on item {2} not cached: computing checksum', + PLUGIN, key, displayable_path(item.path)) try: checksum = command_output(args) setattr(item, key, checksum) item.store() - log.debug(u'{)}: computed checksum for {1} using {2}' - .format(PLUGIN, item.title, key)) + log.debug(u'{0}: computed checksum for {1} using {2}', + PLUGIN, item.title, key) except subprocess.CalledProcessError as e: - log.debug(u'{0}: failed to checksum {1}: {2}' - .format(PLUGIN, displayable_path(item.path), e)) + log.debug(u'{0}: failed to checksum {1}: {2}', + PLUGIN, displayable_path(item.path), e) else: - log.debug(u'{0}: key {1} on item {2} cached: not computing checksum' - .format(PLUGIN, key, displayable_path(item.path))) + log.debug(u'{0}: key {1} on item {2} cached: not computing checksum', + PLUGIN, key, displayable_path(item.path)) return key, checksum @@ -86,8 +86,8 @@ def _group_by(objs, keys): key = '\001'.join(values) counts[key].append(obj) else: - log.debug(u'{0}: all keys {1} on item {2} are null: skipping' - .format(PLUGIN, str(keys), displayable_path(obj.path))) + log.debug(u'{0}: all keys {1} on item {2} are null: skipping', + PLUGIN, str(keys), displayable_path(obj.path)) return counts diff --git a/beetsplug/echonest.py b/beetsplug/echonest.py index db440a44a..e38814437 100644 --- a/beetsplug/echonest.py +++ b/beetsplug/echonest.py @@ -15,14 +15,13 @@ """Fetch a variety of acoustic metrics from The Echo Nest. """ import time -import logging import socket import os import tempfile from string import Template import subprocess -from beets import util, config, plugins, ui +from beets import util, config, plugins, ui, logging from beets.dbcore import types import pyechonest import pyechonest.song @@ -154,23 +153,23 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): if e.code == 3: # reached access limit per minute log.debug(u'echonest: rate-limited on try {0}; ' - u'waiting {1} seconds' - .format(i + 1, RETRY_INTERVAL)) + u'waiting {1} seconds', + i + 1, RETRY_INTERVAL) time.sleep(RETRY_INTERVAL) elif e.code == 5: # specified identifier does not exist # no use in trying again. - log.debug(u'echonest: {0}'.format(e)) + log.debug(u'echonest: {0}', e) return None else: - log.error(u'echonest: {0}'.format(e.args[0][0])) + log.error(u'echonest: {0}', e.args[0][0]) return None except (pyechonest.util.EchoNestIOError, socket.error) as e: - log.warn(u'echonest: IO error: {0}'.format(e)) + log.warn(u'echonest: IO error: {0}', e) time.sleep(RETRY_INTERVAL) except Exception as e: # there was an error analyzing the track, status: error - log.debug(u'echonest: {0}'.format(e)) + log.debug(u'echonest: {0}', e) return None else: break @@ -292,10 +291,9 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): fd, dest = tempfile.mkstemp(u'.ogg') os.close(fd) - log.info(u'echonest: encoding {0} to {1}'.format( - util.displayable_path(source), - util.displayable_path(dest), - )) + log.info(u'echonest: encoding {0} to {1}', + util.displayable_path(source), + util.displayable_path(dest)) opts = [] for arg in CONVERT_COMMAND.split(): @@ -306,13 +304,12 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): try: util.command_output(opts) except (OSError, subprocess.CalledProcessError) as exc: - log.debug(u'echonest: encode failed: {0}'.format(exc)) + log.debug(u'echonest: encode failed: {0}', exc) util.remove(dest) return - log.info(u'echonest: finished encoding {0}'.format( - util.displayable_path(source)) - ) + log.info(u'echonest: finished encoding {0}', + util.displayable_path(source)) return dest def truncate(self, source): @@ -320,10 +317,9 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): fd, dest = tempfile.mkstemp(u'.ogg') os.close(fd) - log.info(u'echonest: truncating {0} to {1}'.format( - util.displayable_path(source), - util.displayable_path(dest), - )) + log.info(u'echonest: truncating {0} to {1}', + util.displayable_path(source), + util.displayable_path(dest)) opts = [] for arg in TRUNCATE_COMMAND.split(): @@ -334,13 +330,12 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): try: util.command_output(opts) except (OSError, subprocess.CalledProcessError) as exc: - log.debug(u'echonest: truncate failed: {0}'.format(exc)) + log.debug(u'echonest: truncate failed: {0}', exc) util.remove(dest) return - log.info(u'echonest: truncate encoding {0}'.format( - util.displayable_path(source)) - ) + log.info(u'echonest: truncate encoding {0}', + util.displayable_path(source)) return dest def analyze(self, item): @@ -411,14 +406,12 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): for method in methods: song = method(item) if song: - log.debug( - u'echonest: got song through {0}: {1} - {2} [{3}]'.format( - method.__name__, - item.artist, - item.title, - song.get('duration'), - ) - ) + log.debug(u'echonest: got song through {0}: {1} - {2} [{3}]', + method.__name__, + item.artist, + item.title, + song.get('duration'), + ) return song def apply_metadata(self, item, values, write=False): @@ -429,7 +422,7 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): for k, v in values.iteritems(): if k in ATTRIBUTES: field = ATTRIBUTES[k] - log.debug(u'echonest: metadata: {0} = {1}'.format(field, v)) + log.debug(u'echonest: metadata: {0} = {1}', field, v) if field == 'bpm': item[field] = int(v) else: @@ -441,7 +434,7 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): item['initial_key'] = key if 'id' in values: enid = values['id'] - log.debug(u'echonest: metadata: {0} = {1}'.format(ID_KEY, enid)) + log.debug(u'echonest: metadata: {0} = {1}', ID_KEY, enid) item[ID_KEY] = enid # Write and save. @@ -483,8 +476,7 @@ class EchonestMetadataPlugin(plugins.BeetsPlugin): self.config.set_args(opts) write = config['import']['write'].get(bool) for item in lib.items(ui.decargs(args)): - log.info(u'echonest: {0} - {1}'.format(item.artist, - item.title)) + log.info(u'echonest: {0} - {1}', item.artist, item.title) if self.config['force'] or self.requires_update(item): song = self.fetch_song(item) if song: diff --git a/beetsplug/embedart.py b/beetsplug/embedart.py index 49ed47928..7f04cd1fb 100644 --- a/beetsplug/embedart.py +++ b/beetsplug/embedart.py @@ -14,12 +14,12 @@ """Allows beets to embed album art into file metadata.""" import os.path -import logging import imghdr import subprocess import platform from tempfile import NamedTemporaryFile +from beets import logging from beets.plugins import BeetsPlugin from beets import mediafile from beets import ui @@ -122,20 +122,17 @@ def embed_item(item, imagepath, maxwidth=None, itempath=None, if not art: pass else: - log.debug(u'embedart: media file contained art already {0}'.format( - displayable_path(imagepath) - )) + log.debug(u'embedart: media file contained art already {0}', + displayable_path(imagepath)) return if maxwidth and not as_album: imagepath = resize_image(imagepath, maxwidth) try: - log.debug(u'embedart: embedding {0}'.format( - displayable_path(imagepath) - )) + log.debug(u'embedart: embedding {0}', displayable_path(imagepath)) item['images'] = [_mediafile_image(imagepath, maxwidth)] except IOError as exc: - log.error(u'embedart: could not read image file: {0}'.format(exc)) + log.error(u'embedart: could not read image file: {0}', exc) else: # We don't want to store the image in the database. item.try_write(itempath) @@ -147,19 +144,18 @@ def embed_album(album, maxwidth=None, quiet=False): """ imagepath = album.artpath if not imagepath: - log.info(u'No album art present: {0} - {1}'. - format(album.albumartist, album.album)) + log.info(u'No album art present: {0} - {1}', + album.albumartist, album.album) return if not os.path.isfile(syspath(imagepath)): - log.error(u'Album art not found at {0}' - .format(displayable_path(imagepath))) + log.error(u'Album art not found at {0}', displayable_path(imagepath)) return if maxwidth: imagepath = resize_image(imagepath, maxwidth) log.log( logging.DEBUG if quiet else logging.INFO, - u'Embedding album art into {0.albumartist} - {0.album}.'.format(album), + u'Embedding album art into {0.albumartist} - {0.album}.', album ) for item in album.items(): @@ -171,8 +167,7 @@ def embed_album(album, maxwidth=None, quiet=False): def resize_image(imagepath, maxwidth): """Returns path to an image resized to maxwidth. """ - log.info(u'Resizing album art to {0} pixels wide' - .format(maxwidth)) + log.info(u'Resizing album art to {0} pixels wide', maxwidth) imagepath = ArtResizer.shared.resize(maxwidth, syspath(imagepath)) return imagepath @@ -197,15 +192,15 @@ def check_art_similarity(item, imagepath, compare_threshold): stdout, stderr = proc.communicate() if proc.returncode: if proc.returncode != 1: - log.warn(u'embedart: IM phashes compare failed for {0}, \ - {1}'.format(displayable_path(imagepath), - displayable_path(art))) + log.warn(u'embedart: IM phashes compare failed for ' + u'{0}, {1}', displayable_path(imagepath), + displayable_path(art)) return phashDiff = float(stderr) else: phashDiff = float(stdout) - log.info(u'embedart: compare PHASH score is {0}'.format(phashDiff)) + log.info(u'embedart: compare PHASH score is {0}', phashDiff) if phashDiff > compare_threshold: return False @@ -226,9 +221,8 @@ def get_art(item): try: mf = mediafile.MediaFile(syspath(item.path)) except mediafile.UnreadableFileError as exc: - log.error(u'Could not extract art from {0}: {1}'.format( - displayable_path(item.path), exc - )) + log.error(u'Could not extract art from {0}: {1}', + displayable_path(item.path), exc) return return mf.art @@ -244,8 +238,8 @@ def extract(outpath, item): art = get_art(item) if not art: - log.error(u'No album art present in {0} - {1}.' - .format(item.artist, item.title)) + log.error(u'No album art present in {0} - {1}.', + item.artist, item.title) return # Add an extension to the filename. @@ -255,8 +249,8 @@ def extract(outpath, item): return outpath += '.' + ext - log.info(u'Extracting album art from: {0.artist} - {0.title} ' - u'to: {1}'.format(item, displayable_path(outpath))) + log.info(u'Extracting album art from: {0.artist} - {0.title} to: {1}', + item, displayable_path(outpath)) with open(syspath(outpath), 'wb') as f: f.write(art) return outpath @@ -267,14 +261,13 @@ def extract(outpath, item): def clear(lib, query): log.info(u'Clearing album art from items:') for item in lib.items(query): - log.info(u'{0} - {1}'.format(item.artist, item.title)) + log.info(u'{0} - {1}', item.artist, item.title) try: mf = mediafile.MediaFile(syspath(item.path), config['id3v23'].get(bool)) except mediafile.UnreadableFileError as exc: - log.error(u'Could not clear art from {0}: {1}'.format( - displayable_path(item.path), exc - )) + log.error(u'Could not clear art from {0}: {1}', + displayable_path(item.path), exc) continue del mf.art mf.save() diff --git a/beetsplug/fetchart.py b/beetsplug/fetchart.py index b2a4620b1..3b0059817 100644 --- a/beetsplug/fetchart.py +++ b/beetsplug/fetchart.py @@ -15,13 +15,13 @@ """Fetches album art. """ from contextlib import closing -import logging import os import re from tempfile import NamedTemporaryFile import requests +from beets import logging from beets import plugins from beets import importer from beets import ui @@ -50,7 +50,7 @@ def _fetch_image(url): actually be an image. If so, returns a path to the downloaded image. Otherwise, returns None. """ - log.debug(u'fetchart: downloading art: {0}'.format(url)) + log.debug(u'fetchart: downloading art: {0}', url) try: with closing(requests_session.get(url, stream=True)) as resp: if 'Content-Type' not in resp.headers \ @@ -63,9 +63,8 @@ def _fetch_image(url): as fh: for chunk in resp.iter_content(): fh.write(chunk) - log.debug(u'fetchart: downloaded art to: {0}'.format( - util.displayable_path(fh.name) - )) + log.debug(u'fetchart: downloaded art to: {0}', + util.displayable_path(fh.name)) return fh.name except (IOError, requests.RequestException): log.debug(u'fetchart: error fetching art') @@ -117,7 +116,7 @@ def aao_art(album): # Get the page from albumart.org. try: resp = requests_session.get(AAO_URL, params={'asin': album.asin}) - log.debug(u'fetchart: scraped art URL: {0}'.format(resp.url)) + log.debug(u'fetchart: scraped art URL: {0}', resp.url) except requests.RequestException: log.debug(u'fetchart: error scraping art page') return @@ -172,7 +171,7 @@ def itunes_art(album): try: itunes_album = itunes.search_album(search_string)[0] except Exception as exc: - log.debug('fetchart: iTunes search failed: {0}'.format(exc)) + log.debug('fetchart: iTunes search failed: {0}', exc) return if itunes_album.get_artwork()['100']: @@ -216,16 +215,14 @@ def art_in_path(path, cover_names, cautious): cover_pat = r"(\b|_)({0})(\b|_)".format('|'.join(cover_names)) for fn in images: if re.search(cover_pat, os.path.splitext(fn)[0], re.I): - log.debug(u'fetchart: using well-named art file {0}'.format( - util.displayable_path(fn) - )) + log.debug(u'fetchart: using well-named art file {0}', + util.displayable_path(fn)) return os.path.join(path, fn) # Fall back to any image in the folder. if images and not cautious: - log.debug(u'fetchart: using fallback art file {0}'.format( - util.displayable_path(images[0]) - )) + log.debug(u'fetchart: using fallback art file {0}', + util.displayable_path(images[0])) return os.path.join(path, images[0]) @@ -315,8 +312,7 @@ def batch_fetch_art(lib, albums, force, maxwidth=None): else: message = ui.colorize('red', 'no art found') - log.info(u'{0} - {1}: {2}'.format(album.albumartist, album.album, - message)) + log.info(u'{0} - {1}: {2}', album.albumartist, album.album, message) class FetchArtPlugin(plugins.BeetsPlugin): diff --git a/beetsplug/freedesktop.py b/beetsplug/freedesktop.py index 0aea97c38..3f3307c82 100644 --- a/beetsplug/freedesktop.py +++ b/beetsplug/freedesktop.py @@ -15,12 +15,12 @@ """Creates freedesktop.org-compliant .directory files on an album level. """ +from beets import logging from beets.plugins import BeetsPlugin from beets.ui import Subcommand from beets.ui import decargs import os -import logging log = logging.getLogger('beets.freedesktop') diff --git a/beetsplug/ftintitle.py b/beetsplug/ftintitle.py index f28a1661c..f36cfb348 100644 --- a/beetsplug/ftintitle.py +++ b/beetsplug/ftintitle.py @@ -14,12 +14,13 @@ """Moves "featured" artists to the title from the artist field. """ +import re + from beets import plugins from beets import ui from beets.util import displayable_path from beets import config -import logging -import re +from beets import logging log = logging.getLogger('beets') @@ -52,8 +53,7 @@ def update_metadata(item, feat_part, drop_feat, loglevel=logging.DEBUG): remove it from the artist field. """ # In all cases, update the artist fields. - log.log(loglevel, u'artist: {0} -> {1}'.format( - item.artist, item.albumartist)) + log.log(loglevel, u'artist: {0} -> {1}', item.artist, item.albumartist) item.artist = item.albumartist if item.artist_sort: # Just strip the featured artist from the sort name. @@ -63,7 +63,7 @@ def update_metadata(item, feat_part, drop_feat, loglevel=logging.DEBUG): # artist and if we do not drop featuring information. if not drop_feat and not contains_feat(item.title): new_title = u"{0} feat. {1}".format(item.title, feat_part) - log.log(loglevel, u'title: {0} -> {1}'.format(item.title, new_title)) + log.log(loglevel, u'title: {0} -> {1}', item.title, new_title) item.title = new_title diff --git a/beetsplug/ihate.py b/beetsplug/ihate.py index b55554d8a..ed7cbd954 100644 --- a/beetsplug/ihate.py +++ b/beetsplug/ihate.py @@ -14,7 +14,7 @@ """Warns you about things you hate (or even blocks import).""" -import logging +from beets import logging from beets.plugins import BeetsPlugin from beets.importer import action from beets.library import parse_query_string @@ -72,12 +72,11 @@ class IHatePlugin(BeetsPlugin): self._log.debug(u'[ihate] processing your hate') if self.do_i_hate_this(task, skip_queries): task.choice_flag = action.SKIP - self._log.info(u'[ihate] skipped: {0}' - .format(summary(task))) + self._log.info(u'[ihate] skipped: {0}', summary(task)) return if self.do_i_hate_this(task, warn_queries): - self._log.info(u'[ihate] you maybe hate this: {0}' - .format(summary(task))) + self._log.info(u'[ihate] you maybe hate this: {0}', + summary(task)) else: self._log.debug(u'[ihate] nothing to do') else: diff --git a/beetsplug/importadded.py b/beetsplug/importadded.py index bf2de1300..8cb590111 100644 --- a/beetsplug/importadded.py +++ b/beetsplug/importadded.py @@ -6,9 +6,9 @@ Reimported albums and items are skipped. from __future__ import unicode_literals, absolute_import, print_function -import logging import os +from beets import logging from beets import config from beets import util from beets.plugins import BeetsPlugin @@ -75,8 +75,8 @@ def write_item_mtime(item, mtime): item's file. """ if mtime is None: - log.warn(u"No mtime to be preserved for item '{0}'" - .format(util.displayable_path(item.path))) + log.warn(u"No mtime to be preserved for item '{0}'", + util.displayable_path(item.path)) return # The file's mtime on disk must be in sync with the item's mtime @@ -97,17 +97,17 @@ def record_import_mtime(item, source, destination): """ mtime = os.stat(util.syspath(source)).st_mtime item_mtime[destination] = mtime - log.debug(u"Recorded mtime {0} for item '{1}' imported from '{2}'".format( - mtime, util.displayable_path(destination), - util.displayable_path(source))) + log.debug(u"Recorded mtime {0} for item '{1}' imported from '{2}'", + mtime, util.displayable_path(destination), + util.displayable_path(source)) @ImportAddedPlugin.listen('album_imported') def update_album_times(lib, album): if reimported_album(album): log.debug(u"Album '{0}' is reimported, skipping import of added dates" - u" for the album and its items." - .format(util.displayable_path(album.path))) + u" for the album and its items.", + util.displayable_path(album.path)) return album_mtimes = [] @@ -120,7 +120,7 @@ def update_album_times(lib, album): item.store() album.added = min(album_mtimes) log.debug(u"Import of album '{0}', selected album.added={1} from item" - u" file mtimes.".format(album.album, album.added)) + u" file mtimes.", album.album, album.added) album.store() @@ -128,13 +128,13 @@ def update_album_times(lib, album): def update_item_times(lib, item): if reimported_item(item): log.debug(u"Item '{0}' is reimported, skipping import of added " - u"date.".format(util.displayable_path(item.path))) + u"date.", util.displayable_path(item.path)) return mtime = item_mtime.pop(item.path, None) if mtime: item.added = mtime if config['importadded']['preserve_mtimes'].get(bool): write_item_mtime(item, mtime) - log.debug(u"Import of item '{0}', selected item.added={1}" - .format(util.displayable_path(item.path), item.added)) + log.debug(u"Import of item '{0}', selected item.added={1}", + util.displayable_path(item.path), item.added) item.store() diff --git a/beetsplug/importfeeds.py b/beetsplug/importfeeds.py index 0f1cd11c8..4ac1dda2b 100644 --- a/beetsplug/importfeeds.py +++ b/beetsplug/importfeeds.py @@ -19,11 +19,10 @@ one wants to manually add music to a player by its path. import datetime import os import re -import logging from beets.plugins import BeetsPlugin from beets.util import normpath, syspath, bytestring_path -from beets import config +from beets import config, logging M3U_DEFAULT_NAME = 'imported.m3u' log = logging.getLogger('beets') @@ -132,7 +131,7 @@ def _record_items(lib, basename, items): if 'echo' in formats: log.info("Location of imported music:") for path in paths: - log.info(" " + path) + log.info(" {0}", path) @ImportFeedsPlugin.listen('library_opened') diff --git a/beetsplug/info.py b/beetsplug/info.py index 180f35747..30cccb1b2 100644 --- a/beetsplug/info.py +++ b/beetsplug/info.py @@ -16,8 +16,8 @@ """ import os -import logging +from beets import logging from beets.plugins import BeetsPlugin from beets import ui from beets import mediafile @@ -52,7 +52,7 @@ def run(lib, opts, args): try: data = data_emitter() except mediafile.UnreadableFileError as ex: - log.error(u'cannot read file: {0}'.format(ex.message)) + log.error(u'cannot read file: {0}', ex.message) continue if opts.summarize: diff --git a/beetsplug/inline.py b/beetsplug/inline.py index 1ce4eb788..e7e7e0f41 100644 --- a/beetsplug/inline.py +++ b/beetsplug/inline.py @@ -14,12 +14,11 @@ """Allows inline path template customization code in the config file. """ -import logging import traceback import itertools from beets.plugins import BeetsPlugin -from beets import config +from beets import config, logging log = logging.getLogger('beets') @@ -64,9 +63,8 @@ def compile_inline(python_code, album): try: func = _compile_func(python_code) except SyntaxError: - log.error(u'syntax error in inline field definition:\n{0}'.format( - traceback.format_exc() - )) + log.error(u'syntax error in inline field definition:\n{0}', + traceback.format_exc()) return else: is_expr = False @@ -113,14 +111,14 @@ class InlinePlugin(BeetsPlugin): # Item fields. for key, view in itertools.chain(config['item_fields'].items(), config['pathfields'].items()): - log.debug(u'inline: adding item field {0}'.format(key)) + log.debug(u'inline: adding item field {0}', key) func = compile_inline(view.get(unicode), False) if func is not None: self.template_fields[key] = func # Album fields. for key, view in config['album_fields'].items(): - log.debug(u'inline: adding album field {0}'.format(key)) + log.debug(u'inline: adding album field {0}', key) func = compile_inline(view.get(unicode), True) if func is not None: self.album_template_fields[key] = func diff --git a/beetsplug/keyfinder.py b/beetsplug/keyfinder.py index 2abae381d..49830edef 100644 --- a/beetsplug/keyfinder.py +++ b/beetsplug/keyfinder.py @@ -15,9 +15,9 @@ """Uses the `KeyFinder` program to add the `initial_key` field. """ -import logging import subprocess +from beets import logging from beets import ui from beets import util from beets.plugins import BeetsPlugin @@ -62,11 +62,11 @@ class KeyFinderPlugin(BeetsPlugin): try: key = util.command_output([bin, '-f', item.path]) except (subprocess.CalledProcessError, OSError) as exc: - log.error(u'KeyFinder execution failed: {0}'.format(exc)) + log.error(u'KeyFinder execution failed: {0}', exc) continue item['initial_key'] = key - log.debug(u'added computed initial key {0} for {1}' - .format(key, util.displayable_path(item.path))) + log.debug(u'added computed initial key {0} for {1}', + key, util.displayable_path(item.path)) item.try_write() item.store() diff --git a/beetsplug/lastgenre/__init__.py b/beetsplug/lastgenre/__init__.py index 109aaae3c..2b4acb590 100644 --- a/beetsplug/lastgenre/__init__.py +++ b/beetsplug/lastgenre/__init__.py @@ -20,11 +20,11 @@ and has been edited to remove some questionable entries. The scraper script used is available here: https://gist.github.com/1241307 """ -import logging import pylast import os import yaml +from beets import logging from beets import plugins from beets import ui from beets.util import normpath, plurality @@ -71,7 +71,7 @@ def _tags_for(obj, min_weight=None): else: res = obj.get_top_tags() except PYLAST_EXCEPTIONS as exc: - log.debug(u'last.fm error: {0}'.format(exc)) + log.debug(u'last.fm error: {0}', exc) return [] # Filter by weight (optionally). @@ -371,9 +371,8 @@ class LastGenrePlugin(plugins.BeetsPlugin): for album in lib.albums(ui.decargs(args)): album.genre, src = self._get_genre(album) - log.info(u'genre for album {0} - {1} ({2}): {3}'.format( - album.albumartist, album.album, src, album.genre - )) + log.info(u'genre for album {0} - {1} ({2}): {3}', + album.albumartist, album.album, src, album.genre) album.store() for item in album.items(): @@ -382,9 +381,8 @@ class LastGenrePlugin(plugins.BeetsPlugin): if 'track' in self.sources: item.genre, src = self._get_genre(item) item.store() - log.info(u'genre for track {0} - {1} ({2}): {3}' - .format(item.artist, item.title, src, - item.genre)) + log.info(u'genre for track {0} - {1} ({2}): {3}', + item.artist, item.title, src, item.genre) if write: item.try_write() @@ -397,20 +395,20 @@ class LastGenrePlugin(plugins.BeetsPlugin): if task.is_album: album = task.album album.genre, src = self._get_genre(album) - log.debug(u'added last.fm album genre ({0}): {1}'.format( - src, album.genre)) + log.debug(u'added last.fm album genre ({0}): {1}', + src, album.genre) album.store() if 'track' in self.sources: for item in album.items(): item.genre, src = self._get_genre(item) - log.debug(u'added last.fm item genre ({0}): {1}'.format( - src, item.genre)) + log.debug(u'added last.fm item genre ({0}): {1}', + src, item.genre) item.store() else: item = task.item item.genre, src = self._get_genre(item) - log.debug(u'added last.fm item genre ({0}): {1}'.format( - src, item.genre)) + log.debug(u'added last.fm item genre ({0}): {1}', + src, item.genre) item.store() diff --git a/beetsplug/lastimport.py b/beetsplug/lastimport.py index 240aa90ca..087213031 100644 --- a/beetsplug/lastimport.py +++ b/beetsplug/lastimport.py @@ -12,12 +12,12 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -import logging import requests from beets import ui from beets import dbcore from beets import config from beets import plugins +from beets import logging from beets.dbcore import types log = logging.getLogger('beets') @@ -56,7 +56,7 @@ def import_lastfm(lib): if not user: raise ui.UserError('You must specify a user name for lastimport') - log.info('Fetching last.fm library for @{0}'.format(user)) + log.info('Fetching last.fm library for @{0}', user) page_total = 1 page_current = 0 @@ -65,10 +65,9 @@ def import_lastfm(lib): retry_limit = config['lastimport']['retry_limit'].get(int) # Iterate through a yet to be known page total count while page_current < page_total: - log.info('lastimport: Querying page #{0}{1}...'.format( - page_current + 1, - '/' + str(page_total) if page_total > 1 else '' - )) + log.info('lastimport: Querying page #{0}{1}...', + page_current + 1, + '/{}'.format(page_total) if page_total > 1 else '') for retry in range(0, retry_limit): page = fetch_tracks(user, page_current + 1, per_page) @@ -84,27 +83,22 @@ def import_lastfm(lib): unknown_total += unknown break else: - log.error('lastimport: ERROR: unable to read page #{0}'.format( - page_current + 1 - )) + log.error('lastimport: ERROR: unable to read page #{0}', + page_current + 1) if retry < retry_limit: log.info( - 'lastimport: Retrying page #{0}... ({1}/{2} retry)' - .format(page_current + 1, retry + 1, retry_limit) + 'lastimport: Retrying page #{0}... ({1}/{2} retry)', + page_current + 1, retry + 1, retry_limit ) else: - log.error( - 'lastimport: FAIL: unable to fetch page #{0}, ' - 'tried {1} times'.format(page_current, retry + 1) - ) + log.error('lastimport: FAIL: unable to fetch page #{0}, ', + 'tried {1} times', page_current, retry + 1) page_current += 1 log.info('lastimport: ... done!') - log.info('lastimport: finished processing {0} song pages'.format( - page_total - )) - log.info('lastimport: {0} unknown play-counts'.format(unknown_total)) - log.info('lastimport: {0} play-counts imported'.format(found_total)) + log.info('lastimport: finished processing {0} song pages', page_total) + log.info('lastimport: {0} unknown play-counts', unknown_total) + log.info('lastimport: {0} play-counts imported', found_total) def fetch_tracks(user, page, limit): @@ -122,10 +116,8 @@ def process_tracks(lib, tracks): total = len(tracks) total_found = 0 total_fails = 0 - log.info( - 'lastimport: Received {0} tracks in this page, processing...' - .format(total) - ) + log.info('lastimport: Received {0} tracks in this page, processing...', + total) for num in xrange(0, total): song = '' @@ -136,8 +128,7 @@ def process_tracks(lib, tracks): if 'album' in tracks[num]: album = tracks[num]['album'].get('name', '').strip() - log.debug(u'lastimport: query: {0} - {1} ({2})' - .format(artist, title, album)) + log.debug(u'lastimport: query: {0} - {1} ({2})', artist, title, album) # First try to query by musicbrainz's trackid if trackid: @@ -148,7 +139,7 @@ def process_tracks(lib, tracks): # Otherwise try artist/title/album if not song: log.debug(u'lastimport: no match for mb_trackid {0}, trying by ' - u'artist/title/album'.format(trackid)) + u'artist/title/album', trackid) query = dbcore.AndQuery([ dbcore.query.SubstringQuery('artist', artist), dbcore.query.SubstringQuery('title', title), @@ -178,26 +169,19 @@ def process_tracks(lib, tracks): if song: count = int(song.get('play_count', 0)) new_count = int(tracks[num]['playcount']) - log.debug( - u'lastimport: match: {0} - {1} ({2}) ' - u'updating: play_count {3} => {4}'.format( - song.artist, song.title, song.album, count, new_count - ) - ) + log.debug(u'lastimport: match: {0} - {1} ({2}) ' + u'updating: play_count {3} => {4}', + song.artist, song.title, song.album, count, new_count) song['play_count'] = new_count song.store() total_found += 1 else: total_fails += 1 - log.info( - u'lastimport: - No match: {0} - {1} ({2})' - .format(artist, title, album) - ) + log.info(u'lastimport: - No match: {0} - {1} ({2})', + artist, title, album) if total_fails > 0: - log.info( - 'lastimport: Acquired {0}/{1} play-counts ({2} unknown)' - .format(total_found, total, total_fails) - ) + log.info('lastimport: Acquired {0}/{1} play-counts ({2} unknown)', + total_found, total, total_fails) return total_found, total_fails diff --git a/beetsplug/lyrics.py b/beetsplug/lyrics.py index a2ebe7c36..a87715fe3 100644 --- a/beetsplug/lyrics.py +++ b/beetsplug/lyrics.py @@ -17,7 +17,6 @@ from __future__ import print_function import re -import logging import requests import json import unicodedata @@ -26,6 +25,7 @@ import difflib import itertools from HTMLParser import HTMLParseError +from beets import logging from beets import plugins from beets import config, ui @@ -63,12 +63,12 @@ def fetch_url(url): try: r = requests.get(url, verify=False) except requests.RequestException as exc: - log.debug(u'lyrics request failed: {0}'.format(exc)) + log.debug(u'lyrics request failed: {0}', exc) return if r.status_code == requests.codes.ok: return r.text else: - log.debug(u'failed to fetch: {0} ({1})'.format(url, r.status_code)) + log.debug(u'failed to fetch: {0} ({1})', url, r.status_code) def unescape(text): @@ -272,7 +272,7 @@ def slugify(text): text = unicodedata.normalize('NFKD', text).encode('ascii', 'ignore') text = unicode(re.sub('[-\s]+', ' ', text)) except UnicodeDecodeError: - log.exception(u"Failing to normalize '{0}'".format(text)) + log.exception(u"Failing to normalize '{0}'", text) return text @@ -323,7 +323,7 @@ def is_lyrics(text, artist=None): badTriggersOcc = [] nbLines = text.count('\n') if nbLines <= 1: - log.debug(u"Ignoring too short lyrics '{0}'".format(text)) + log.debug(u"Ignoring too short lyrics '{0}'", text) return False elif nbLines < 5: badTriggersOcc.append('too_short') @@ -341,7 +341,7 @@ def is_lyrics(text, artist=None): text, re.I)) if badTriggersOcc: - log.debug(u'Bad triggers detected: {0}'.format(badTriggersOcc)) + log.debug(u'Bad triggers detected: {0}', badTriggersOcc) return len(badTriggersOcc) < 2 @@ -409,7 +409,7 @@ def fetch_google(artist, title): data = json.load(data) if 'error' in data: reason = data['error']['errors'][0]['reason'] - log.debug(u'google lyrics backend error: {0}'.format(reason)) + log.debug(u'google lyrics backend error: {0}', reason) return if 'items' in data.keys(): @@ -424,7 +424,7 @@ def fetch_google(artist, title): continue if is_lyrics(lyrics, artist): - log.debug(u'got lyrics from {0}'.format(item['displayLink'])) + log.debug(u'got lyrics from {0}', item['displayLink']) return lyrics @@ -502,8 +502,8 @@ class LyricsPlugin(plugins.BeetsPlugin): """ # Skip if the item already has lyrics. if not force and item.lyrics: - log.log(loglevel, u'lyrics already present: {0} - {1}' - .format(item.artist, item.title)) + log.log(loglevel, u'lyrics already present: {0} - {1}', + item.artist, item.title) return lyrics = None @@ -515,11 +515,11 @@ class LyricsPlugin(plugins.BeetsPlugin): lyrics = u"\n\n---\n\n".join([l for l in lyrics if l]) if lyrics: - log.log(loglevel, u'fetched lyrics: {0} - {1}' - .format(item.artist, item.title)) + log.log(loglevel, u'fetched lyrics: {0} - {1}', + item.artist, item.title) else: - log.log(loglevel, u'lyrics not found: {0} - {1}' - .format(item.artist, item.title)) + log.log(loglevel, u'lyrics not found: {0} - {1}', + item.artist, item.title) fallback = self.config['fallback'].get() if fallback: lyrics = fallback @@ -539,6 +539,5 @@ class LyricsPlugin(plugins.BeetsPlugin): for backend in self.backends: lyrics = backend(artist, title) if lyrics: - log.debug(u'got lyrics from backend: {0}' - .format(backend.__name__)) + log.debug(u'got lyrics from backend: {0}', backend.__name__) return _scrape_strip_cruft(lyrics, True) diff --git a/beetsplug/mbcollection.py b/beetsplug/mbcollection.py index 610408232..764c4529f 100644 --- a/beetsplug/mbcollection.py +++ b/beetsplug/mbcollection.py @@ -16,12 +16,12 @@ from __future__ import print_function from beets.plugins import BeetsPlugin from beets.ui import Subcommand +from beets import logging from beets import ui from beets import config import musicbrainzngs import re -import logging SUBMISSION_CHUNK_SIZE = 200 UUID_REGEX = r'^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$' @@ -79,7 +79,7 @@ def update_album_list(album_list): if re.match(UUID_REGEX, aid): album_ids.append(aid) else: - log.info(u'skipping invalid MBID: {0}'.format(aid)) + log.info(u'skipping invalid MBID: {0}', aid) # Submit to MusicBrainz. print('Updating MusicBrainz collection {0}...'.format(collection_id)) diff --git a/beetsplug/mbsync.py b/beetsplug/mbsync.py index 989caeb99..105122639 100644 --- a/beetsplug/mbsync.py +++ b/beetsplug/mbsync.py @@ -14,10 +14,8 @@ """Update library's tags using MusicBrainz. """ -import logging - from beets.plugins import BeetsPlugin -from beets import autotag, library, ui, util +from beets import autotag, library, ui, util, logging from beets.autotag import hooks from beets import config from collections import defaultdict @@ -31,14 +29,13 @@ def mbsync_singletons(lib, query, move, pretend, write): """ for item in lib.items(query + ['singleton:true']): if not item.mb_trackid: - log.info(u'Skipping singleton {0}: has no mb_trackid' - .format(item.title)) + log.info(u'Skipping singleton {0}: has no mb_trackid', item.title) continue # Get the MusicBrainz recording info. track_info = hooks.track_for_mbid(item.mb_trackid) if not track_info: - log.info(u'Recording ID not found: {0}'.format(item.mb_trackid)) + log.info(u'Recording ID not found: {0}', item.mb_trackid) continue # Apply. @@ -54,7 +51,7 @@ def mbsync_albums(lib, query, move, pretend, write): # Process matching albums. for a in lib.albums(query): if not a.mb_albumid: - log.info(u'Skipping album {0}: has no mb_albumid'.format(a.id)) + log.info(u'Skipping album {0}: has no mb_albumid', a.id) continue items = list(a.items()) @@ -62,7 +59,7 @@ def mbsync_albums(lib, query, move, pretend, write): # Get the MusicBrainz album information. album_info = hooks.album_for_mbid(a.mb_albumid) if not album_info: - log.info(u'Release ID not found: {0}'.format(a.mb_albumid)) + log.info(u'Release ID not found: {0}', a.mb_albumid) continue # Map recording MBIDs to their information. Recordings can appear @@ -109,7 +106,7 @@ def mbsync_albums(lib, query, move, pretend, write): # Move album art (and any inconsistent items). if move and lib.directory in util.ancestry(items[0].path): - log.debug(u'moving album {0}'.format(a.id)) + log.debug(u'moving album {0}', a.id) a.move() diff --git a/beetsplug/missing.py b/beetsplug/missing.py index 74f4d4b6c..2ebe3edf8 100644 --- a/beetsplug/missing.py +++ b/beetsplug/missing.py @@ -14,8 +14,7 @@ """List missing tracks. """ -import logging - +from beets import logging from beets.autotag import hooks from beets.library import Item from beets.plugins import BeetsPlugin @@ -43,10 +42,8 @@ def _missing(album): for track_info in getattr(album_info, 'tracks', []): if track_info.track_id not in item_mbids: item = _item(track_info, album_info, album.id) - log.debug(u'{0}: track {1} in album {2}' - .format(PLUGIN, - track_info.track_id, - album_info.album_id)) + log.debug(u'{0}: track {1} in album {2}', + PLUGIN, track_info.track_id, album_info.album_id) yield item diff --git a/beetsplug/mpdstats.py b/beetsplug/mpdstats.py index c198445dc..5a5d27b4e 100644 --- a/beetsplug/mpdstats.py +++ b/beetsplug/mpdstats.py @@ -13,13 +13,13 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -import logging import mpd import socket import select import time import os +from beets import logging from beets import ui from beets import config from beets import plugins @@ -71,7 +71,7 @@ class MPDClientWrapper(object): if host[0] in ['/', '~']: host = os.path.expanduser(host) - log.info(u'mpdstats: connecting to {0}:{1}'.format(host, port)) + log.info(u'mpdstats: connecting to {0}:{1}', host, port) try: self.client.connect(host, port) except socket.error as e: @@ -99,7 +99,7 @@ class MPDClientWrapper(object): try: return getattr(self.client, command)() except (select.error, mpd.ConnectionError) as err: - log.error(u'mpdstats: {0}'.format(err)) + log.error(u'mpdstats: {0}', err) if retries <= 0: # if we exited without breaking, we couldn't reconnect in time :( @@ -171,9 +171,7 @@ class MPDStats(object): if item: return item else: - log.info(u'mpdstats: item not found: {0}'.format( - displayable_path(path) - )) + log.info(u'mpdstats: item not found: {0}', displayable_path(path)) @staticmethod def update_item(item, attribute, value=None, increment=None): @@ -192,11 +190,10 @@ class MPDStats(object): item[attribute] = value item.store() - log.debug(u'mpdstats: updated: {0} = {1} [{2}]'.format( - attribute, - item[attribute], - displayable_path(item.path), - )) + log.debug(u'mpdstats: updated: {0} = {1} [{2}]', + attribute, + item[attribute], + displayable_path(item.path)) def update_rating(self, item, skipped): """Update the rating for a beets item. @@ -232,17 +229,13 @@ class MPDStats(object): """Updates the play count of a song. """ self.update_item(song['beets_item'], 'play_count', increment=1) - log.info(u'mpdstats: played {0}'.format( - displayable_path(song['path']) - )) + log.info(u'mpdstats: played {0}', displayable_path(song['path'])) def handle_skipped(self, song): """Updates the skip count of a song. """ self.update_item(song['beets_item'], 'skip_count', increment=1) - log.info(u'mpdstats: skipped {0}'.format( - displayable_path(song['path']) - )) + log.info(u'mpdstats: skipped {0}', displayable_path(song['path'])) def on_stop(self, status): log.info(u'mpdstats: stop') @@ -264,9 +257,7 @@ class MPDStats(object): return if is_url(path): - log.info(u'mpdstats: playing stream {0}'.format( - displayable_path(path) - )) + log.info(u'mpdstats: playing stream {0}', displayable_path(path)) return played, duration = map(int, status['time'].split(':', 1)) @@ -275,9 +266,7 @@ class MPDStats(object): if self.now_playing and self.now_playing['path'] != path: self.handle_song_change(self.now_playing) - log.info(u'mpdstats: playing {0}'.format( - displayable_path(path) - )) + log.info(u'mpdstats: playing {0}', displayable_path(path)) self.now_playing = { 'started': time.time(), @@ -302,8 +291,7 @@ class MPDStats(object): if handler: handler(status) else: - log.debug(u'mpdstats: unhandled status "{0}"'. - format(status)) + log.debug(u'mpdstats: unhandled status "{0}"', status) events = self.mpd.events() diff --git a/beetsplug/play.py b/beetsplug/play.py index 770b84284..7f9ff3ce9 100644 --- a/beetsplug/play.py +++ b/beetsplug/play.py @@ -16,12 +16,12 @@ """ from beets.plugins import BeetsPlugin from beets.ui import Subcommand +from beets import logging from beets import config from beets import ui from beets import util from os.path import relpath import platform -import logging import shlex from tempfile import NamedTemporaryFile @@ -101,10 +101,9 @@ def play_music(lib, opts, args): # Invoke the command and log the output. output = util.command_output(command) if output: - log.debug(u'Output of {0}: {1}'.format( - util.displayable_path(command[0]), - output.decode('utf8', 'ignore'), - )) + log.debug(u'Output of {0}: {1}', + util.displayable_path(command[0]), + output.decode('utf8', 'ignore')) else: log.debug(u'play: no output') diff --git a/beetsplug/replaygain.py b/beetsplug/replaygain.py index 40b3a3a85..5d50f61c5 100644 --- a/beetsplug/replaygain.py +++ b/beetsplug/replaygain.py @@ -12,7 +12,6 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -import logging import subprocess import os import collections @@ -20,6 +19,7 @@ import itertools import sys import warnings +from beets import logging from beets import ui from beets.plugins import BeetsPlugin from beets.util import syspath, command_output, displayable_path @@ -180,9 +180,9 @@ class CommandBackend(Backend): cmd = cmd + ['-d', str(self.gain_offset)] cmd = cmd + [syspath(i.path) for i in items] - log.debug(u'replaygain: analyzing {0} files'.format(len(items))) - log.debug(u"replaygain: executing {0}" - .format(" ".join(map(displayable_path, cmd)))) + log.debug(u'replaygain: analyzing {0} files', len(items)) + log.debug(u"replaygain: executing {0}", + " ".join(map(displayable_path, cmd))) output = call(cmd) log.debug(u'replaygain: analysis finished') results = self.parse_tool_output(output, @@ -199,7 +199,7 @@ class CommandBackend(Backend): for line in text.split('\n')[1:num_lines + 1]: parts = line.split('\t') if len(parts) != 6 or parts[0] == 'File': - log.debug(u'replaygain: bad tool output: {0}'.format(text)) + log.debug(u'replaygain: bad tool output: {0}', text) raise ReplayGainError('mp3gain failed') d = { 'file': parts[0], @@ -548,14 +548,8 @@ class AudioToolsBackend(Backend): # be obtained from an audiofile instance. rg_track_gain, rg_track_peak = rg.title_gain(audiofile.to_pcm()) - log.debug( - u'ReplayGain for track {0} - {1}: {2:.2f}, {3:.2f}'.format( - item.artist, - item.title, - rg_track_gain, - rg_track_peak - ) - ) + log.debug(u'ReplayGain for track {0} - {1}: {2:.2f}, {3:.2f}', + item.artist, item.title, rg_track_gain, rg_track_peak) return Gain(gain=rg_track_gain, peak=rg_track_peak) def compute_album_gain(self, album): @@ -563,12 +557,7 @@ class AudioToolsBackend(Backend): :rtype: :class:`AlbumGain` """ - log.debug( - u'Analysing album {0} - {1}'.format( - album.albumartist, - album.album - ) - ) + log.debug(u'Analysing album {0} - {1}', album.albumartist, album.album) # The first item is taken and opened to get the sample rate to # initialize the replaygain object. The object is used for all the @@ -584,26 +573,14 @@ class AudioToolsBackend(Backend): track_gains.append( Gain(gain=rg_track_gain, peak=rg_track_peak) ) - log.debug( - u'ReplayGain for track {0} - {1}: {2:.2f}, {3:.2f}'.format( - item.artist, - item.title, - rg_track_gain, - rg_track_peak - ) - ) + log.debug(u'ReplayGain for track {0} - {1}: {2:.2f}, {3:.2f}', + item.artist, item.title, rg_track_gain, rg_track_peak) # After getting the values for all tracks, it's possible to get the # album values. rg_album_gain, rg_album_peak = rg.album_gain() - log.debug( - u'ReplayGain for Album {0} - {1}: {2:.2f}, {3:.2f}'.format( - album.albumartist, - album.album, - rg_album_gain, - rg_album_peak - ) - ) + log.debug(u'ReplayGain for Album {0} - {1}: {2:.2f}, {3:.2f}', + album.albumartist, album.album, rg_album_gain, rg_album_peak) return AlbumGain( Gain(gain=rg_album_gain, peak=rg_album_peak), @@ -674,19 +651,16 @@ class ReplayGainPlugin(BeetsPlugin): item.rg_track_peak = track_gain.peak item.store() - log.debug(u'replaygain: applied track gain {0}, peak {1}'.format( - item.rg_track_gain, - item.rg_track_peak - )) + log.debug(u'replaygain: applied track gain {0}, peak {1}', + item.rg_track_gain, item.rg_track_peak) def store_album_gain(self, album, album_gain): album.rg_album_gain = album_gain.gain album.rg_album_peak = album_gain.peak album.store() - log.debug(u'replaygain: applied album gain {0}, peak {1}'.format( - album.rg_album_gain, - album.rg_album_peak)) + log.debug(u'replaygain: applied album gain {0}, peak {1}', + album.rg_album_gain, album.rg_album_peak) def handle_album(self, album, write): """Compute album and track replay gain store it in all of the @@ -697,12 +671,11 @@ class ReplayGainPlugin(BeetsPlugin): items, nothing is done. """ if not self.album_requires_gain(album): - log.info(u'Skipping album {0} - {1}'.format(album.albumartist, - album.album)) + log.info(u'Skipping album {0} - {1}', + album.albumartist, album.album) return - log.info(u'analyzing {0} - {1}'.format(album.albumartist, - album.album)) + log.info(u'analyzing {0} - {1}', album.albumartist, album.album) try: album_gain = self.backend_instance.compute_album_gain(album) @@ -721,7 +694,7 @@ class ReplayGainPlugin(BeetsPlugin): if write: item.try_write() except ReplayGainError as e: - log.info(u"ReplayGain error: {0}".format(e)) + log.info(u"ReplayGain error: {0}", e) except FatalReplayGainError as e: raise ui.UserError( u"Fatal replay gain error: {0}".format(e) @@ -735,12 +708,10 @@ class ReplayGainPlugin(BeetsPlugin): in the item, nothing is done. """ if not self.track_requires_gain(item): - log.info(u'Skipping track {0} - {1}' - .format(item.artist, item.title)) + log.info(u'Skipping track {0} - {1}', item.artist, item.title) return - log.info(u'analyzing {0} - {1}' - .format(item.artist, item.title)) + log.info(u'analyzing {0} - {1}', item.artist, item.title) try: track_gains = self.backend_instance.compute_track_gain([item]) @@ -755,7 +726,7 @@ class ReplayGainPlugin(BeetsPlugin): if write: item.try_write() except ReplayGainError as e: - log.info(u"ReplayGain error: {0}".format(e)) + log.info(u"ReplayGain error: {0}", e) except FatalReplayGainError as e: raise ui.UserError( u"Fatal replay gain error: {0}".format(e) diff --git a/beetsplug/rewrite.py b/beetsplug/rewrite.py index 55b705492..8a59bdbfd 100644 --- a/beetsplug/rewrite.py +++ b/beetsplug/rewrite.py @@ -16,10 +16,10 @@ formats. """ import re -import logging from collections import defaultdict from beets.plugins import BeetsPlugin +from beets import logging from beets import ui from beets import library @@ -59,7 +59,7 @@ class RewritePlugin(BeetsPlugin): if fieldname not in library.Item._fields: raise ui.UserError("invalid field name (%s) in rewriter" % fieldname) - log.debug(u'adding template field {0}'.format(key)) + log.debug(u'adding template field {0}', key) pattern = re.compile(pattern.lower()) rules[fieldname].append((pattern, value)) if fieldname == 'artist': diff --git a/beetsplug/scrub.py b/beetsplug/scrub.py index c53c27590..7c5b097cb 100644 --- a/beetsplug/scrub.py +++ b/beetsplug/scrub.py @@ -15,8 +15,8 @@ """Cleans extraneous metadata from files' tags via a command or automatically whenever tags are written. """ -import logging +from beets import logging from beets.plugins import BeetsPlugin from beets import ui from beets import util @@ -64,8 +64,7 @@ class ScrubPlugin(BeetsPlugin): # Walk through matching files and remove tags. for item in lib.items(ui.decargs(args)): - log.info(u'scrubbing: {0}'.format( - util.displayable_path(item.path))) + log.info(u'scrubbing: {0}', util.displayable_path(item.path)) # Get album art if we need to restore it. if opts.write: @@ -132,14 +131,13 @@ def _scrub(path): del f[tag] f.save() except IOError as exc: - log.error(u'could not scrub {0}: {1}'.format( - util.displayable_path(path), exc, - )) + log.error(u'could not scrub {0}: {1}', + util.displayable_path(path), exc) # Automatically embed art into imported albums. @ScrubPlugin.listen('write') def write_item(path): if not scrubbing and config['scrub']['auto']: - log.debug(u'auto-scrubbing {0}'.format(util.displayable_path(path))) + log.debug(u'auto-scrubbing {0}', util.displayable_path(path)) _scrub(path) diff --git a/beetsplug/spotify.py b/beetsplug/spotify.py index 7d424c828..704660894 100644 --- a/beetsplug/spotify.py +++ b/beetsplug/spotify.py @@ -2,10 +2,9 @@ from __future__ import print_function import re import webbrowser import requests -import logging from beets.plugins import BeetsPlugin from beets.ui import decargs -from beets import ui +from beets import ui, logging from requests.exceptions import HTTPError log = logging.getLogger('beets') @@ -63,8 +62,7 @@ class SpotifyPlugin(BeetsPlugin): self.config['show_failures'].set(True) if self.config['mode'].get() not in ['list', 'open']: - log.warn(u'{0} is not a valid mode' - .format(self.config['mode'].get())) + log.warn(u'{0} is not a valid mode', self.config['mode'].get()) return False self.opts = opts @@ -81,7 +79,7 @@ class SpotifyPlugin(BeetsPlugin): log.debug(u'Your beets query returned no items, skipping spotify') return - log.info(u'Processing {0} tracks...'.format(len(items))) + log.info(u'Processing {0} tracks...', len(items)) for item in items: @@ -113,8 +111,7 @@ class SpotifyPlugin(BeetsPlugin): try: r.raise_for_status() except HTTPError as e: - log.debug(u'URL returned a {0} error' - .format(e.response.status_code)) + log.debug(u'URL returned a {0} error', e.response.status_code) failures.append(search_url) continue @@ -130,33 +127,31 @@ class SpotifyPlugin(BeetsPlugin): # Simplest, take the first result chosen_result = None if len(r_data) == 1 or self.config['tiebreak'].get() == "first": - log.debug(u'Spotify track(s) found, count: {0}' - .format(len(r_data))) + log.debug(u'Spotify track(s) found, count: {0}', len(r_data)) chosen_result = r_data[0] elif len(r_data) > 1: # Use the popularity filter - log.debug(u'Most popular track chosen, count: {0}' - .format(len(r_data))) + log.debug(u'Most popular track chosen, count: {0}', + len(r_data)) chosen_result = max(r_data, key=lambda x: x['popularity']) if chosen_result: results.append(chosen_result) else: - log.debug(u'No spotify track found: {0}'.format(search_url)) + log.debug(u'No spotify track found: {0}', search_url) failures.append(search_url) failure_count = len(failures) if failure_count > 0: if self.config['show_failures'].get(): - log.info(u'{0} track(s) did not match a Spotify ID:' - .format(failure_count)) + log.info(u'{0} track(s) did not match a Spotify ID:', + failure_count) for track in failures: - log.info(u'track: {0}'.format(track)) + log.info(u'track: {0}', track) log.info(u'') else: log.warn(u'{0} track(s) did not match a Spotify ID;\n' - u'use --show-failures to display' - .format(failure_count)) + u'use --show-failures to display', failure_count) return results diff --git a/beetsplug/the.py b/beetsplug/the.py index 5bc50415a..d146b3e69 100644 --- a/beetsplug/the.py +++ b/beetsplug/the.py @@ -15,7 +15,7 @@ """Moves patterns in path formats (suitable for moving articles).""" import re -import logging +from beets import logging from beets.plugins import BeetsPlugin __author__ = 'baobab@heresiarch.info' @@ -56,11 +56,11 @@ class ThePlugin(BeetsPlugin): try: re.compile(p) except re.error: - self._log.error(u'[the] invalid pattern: {0}'.format(p)) + self._log.error(u'[the] invalid pattern: {0}', p) else: if not (p.startswith('^') or p.endswith('$')): self._log.warn(u'[the] warning: \"{0}\" will not ' - 'match string start/end'.format(p)) + 'match string start/end', p) if self.config['a']: self.patterns = [PATTERN_A] + self.patterns if self.config['the']: @@ -99,7 +99,7 @@ class ThePlugin(BeetsPlugin): r = self.unthe(text, p) if r != text: break - self._log.debug(u'[the] \"{0}\" -> \"{1}\"'.format(text, r)) + self._log.debug(u'[the] \"{0}\" -> \"{1}\"', text, r) return r else: return u'' diff --git a/beetsplug/zero.py b/beetsplug/zero.py index ed41511c8..a8c62d42c 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -15,7 +15,7 @@ """ Clears tag fields in media files.""" import re -import logging +from beets import logging from beets.plugins import BeetsPlugin from beets.mediafile import MediaFile from beets.importer import action @@ -49,10 +49,10 @@ class ZeroPlugin(BeetsPlugin): for field in self.config['fields'].as_str_seq(): if field in ('id', 'path', 'album_id'): log.warn(u'[zero] field \'{0}\' ignored, zeroing ' - u'it would be dangerous'.format(field)) + u'it would be dangerous', field) continue if field not in MediaFile.fields(): - log.error(u'[zero] invalid field: {0}'.format(field)) + log.error(u'[zero] invalid field: {0}', field) continue try: @@ -97,5 +97,5 @@ class ZeroPlugin(BeetsPlugin): match = patterns is True if match: - log.debug(u'[zero] {0}: {1} -> None'.format(field, value)) + log.debug(u'[zero] {0}: {1} -> None', field, value) tags[field] = None diff --git a/test/_common.py b/test/_common.py index 64f2f7247..b222566b7 100644 --- a/test/_common.py +++ b/test/_common.py @@ -16,7 +16,6 @@ import time import sys import os -import logging import tempfile import shutil from contextlib import contextmanager @@ -30,7 +29,7 @@ except ImportError: # Mangle the search path to include the beets sources. sys.path.insert(0, '..') import beets.library -from beets import importer +from beets import importer, logging from beets.ui import commands import beets diff --git a/test/helper.py b/test/helper.py index 459e643a0..4dafb4c39 100644 --- a/test/helper.py +++ b/test/helper.py @@ -35,13 +35,13 @@ import os import os.path import shutil import subprocess -import logging from tempfile import mkdtemp, mkstemp from contextlib import contextmanager from StringIO import StringIO from enum import Enum import beets +from beets import logging from beets import config import beets.plugins from beets.library import Library, Item, Album diff --git a/test/test_logging.py b/test/test_logging.py new file mode 100644 index 000000000..0d2eb7291 --- /dev/null +++ b/test/test_logging.py @@ -0,0 +1,42 @@ +"""Stupid tests that ensure logging works as expected""" +import logging as log +from StringIO import StringIO + +import beets.logging as blog +from _common import unittest, TestCase + + +class LoggingTest(TestCase): + def test_logging_management(self): + l1 = log.getLogger("foo123") + l2 = blog.getLogger("foo123") + self.assertEqual(l1, l2) + self.assertEqual(l1.__class__, log.Logger) + + l3 = blog.getLogger("bar123") + l4 = log.getLogger("bar123") + self.assertEqual(l3, l4) + self.assertEqual(l3.__class__, blog.StrFormatLogger) + + l5 = l3.getChild("shalala") + self.assertEqual(l5.__class__, blog.StrFormatLogger) + + def test_str_format_logging(self): + l = blog.getLogger("baz123") + stream = StringIO() + handler = log.StreamHandler(stream) + + l.addHandler(handler) + l.propagate = False + + l.warning("foo {0} {bar}", "oof", bar="baz") + handler.flush() + self.assertTrue(stream.getvalue(), "foo oof baz") + + +def suite(): + return unittest.TestLoader().loadTestsFromName(__name__) + + +if __name__ == '__main__': + unittest.main(defaultTest='suite')