mirror of
https://github.com/beetbox/beets.git
synced 2025-12-30 12:32:33 +01:00
Merge pull request #1217 from brunal/logging
Use a standard logger for the import log
This commit is contained in:
commit
a86fb19f92
7 changed files with 51 additions and 37 deletions
|
|
@ -26,6 +26,7 @@ from tempfile import mkdtemp
|
|||
from bisect import insort, bisect_left
|
||||
from contextlib import contextmanager
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from beets import logging
|
||||
from beets import autotag
|
||||
|
|
@ -174,14 +175,13 @@ class ImportSession(object):
|
|||
"""Controls an import action. Subclasses should implement methods to
|
||||
communicate with the user or otherwise make decisions.
|
||||
"""
|
||||
def __init__(self, lib, logfile, paths, query):
|
||||
"""Create a session. `lib` is a Library object. `logfile` is a
|
||||
file-like object open for writing or None if no logging is to be
|
||||
performed. Either `paths` or `query` is non-null and indicates
|
||||
def __init__(self, lib, loghandler, paths, query):
|
||||
"""Create a session. `lib` is a Library object. `loghandler` is a
|
||||
logging.Handler. Either `paths` or `query` is non-null and indicates
|
||||
the source of files to be imported.
|
||||
"""
|
||||
self.lib = lib
|
||||
self.logfile = logfile
|
||||
self.logger = self._setup_logging(loghandler)
|
||||
self.paths = paths
|
||||
self.query = query
|
||||
self.seen_idents = set()
|
||||
|
|
@ -191,6 +191,14 @@ class ImportSession(object):
|
|||
if self.paths:
|
||||
self.paths = map(normpath, self.paths)
|
||||
|
||||
def _setup_logging(self, loghandler):
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.propagate = False
|
||||
if not loghandler:
|
||||
loghandler = logging.NullHandler()
|
||||
logger.handlers = [loghandler]
|
||||
return logger
|
||||
|
||||
def set_config(self, config):
|
||||
"""Set `config` property from global import config and make
|
||||
implied changes.
|
||||
|
|
@ -225,13 +233,10 @@ class ImportSession(object):
|
|||
self.want_resume = config['resume'].as_choice([True, False, 'ask'])
|
||||
|
||||
def tag_log(self, status, paths):
|
||||
"""Log a message about a given album to logfile. The status should
|
||||
reflect the reason the album couldn't be tagged.
|
||||
"""Log a message about a given album to the importer log. The status
|
||||
should reflect the reason the album couldn't be tagged.
|
||||
"""
|
||||
if self.logfile:
|
||||
print(u'{0} {1}'.format(status, displayable_path(paths)),
|
||||
file=self.logfile)
|
||||
self.logfile.flush()
|
||||
self.logger.info(u'{0} {1}', status, displayable_path(paths))
|
||||
|
||||
def log_choice(self, task, duplicate=False):
|
||||
"""Logs the task's current choice if it should be logged. If
|
||||
|
|
@ -269,6 +274,7 @@ class ImportSession(object):
|
|||
def run(self):
|
||||
"""Run the import task.
|
||||
"""
|
||||
self.logger.info(u'import started {0}', time.asctime())
|
||||
self.set_config(config['import'])
|
||||
|
||||
# Set up the pipeline.
|
||||
|
|
|
|||
|
|
@ -92,3 +92,16 @@ if PY26:
|
|||
return logger
|
||||
|
||||
my_manager.getLogger = new_getLogger
|
||||
|
||||
|
||||
# Offer NullHandler in Python 2.6 to reduce the difference with never versions
|
||||
if PY26:
|
||||
class NullHandler(Handler):
|
||||
def handle(self, record):
|
||||
pass
|
||||
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
def createLock(self):
|
||||
self.lock = None
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ interface.
|
|||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import time
|
||||
import codecs
|
||||
import platform
|
||||
import re
|
||||
import shlex
|
||||
|
|
@ -825,29 +823,22 @@ def import_files(lib, paths, query):
|
|||
|
||||
# Open the log.
|
||||
if config['import']['log'].get() is not None:
|
||||
logpath = config['import']['log'].as_filename()
|
||||
logpath = syspath(config['import']['log'].as_filename())
|
||||
try:
|
||||
logfile = codecs.open(syspath(logpath), 'a', 'utf8')
|
||||
loghandler = logging.FileHandler(logpath)
|
||||
except IOError:
|
||||
raise ui.UserError(u"could not open log file for writing: %s" %
|
||||
displayable_path(logpath))
|
||||
print(u'import started', time.asctime(), file=logfile)
|
||||
raise ui.UserError(u"could not open log file for writing: "
|
||||
u"{0}".format(displayable_path(loghandler)))
|
||||
else:
|
||||
logfile = None
|
||||
loghandler = None
|
||||
|
||||
# Never ask for input in quiet mode.
|
||||
if config['import']['resume'].get() == 'ask' and \
|
||||
config['import']['quiet']:
|
||||
config['import']['resume'] = False
|
||||
|
||||
session = TerminalImportSession(lib, logfile, paths, query)
|
||||
try:
|
||||
session.run()
|
||||
finally:
|
||||
# If we were logging, close the file.
|
||||
if logfile:
|
||||
print(u'', file=logfile)
|
||||
logfile.close()
|
||||
session = TerminalImportSession(lib, loghandler, paths, query)
|
||||
session.run()
|
||||
|
||||
# Emit event.
|
||||
plugins.send('import', lib=lib, paths=paths)
|
||||
|
|
|
|||
|
|
@ -115,9 +115,9 @@ def album(lib=None):
|
|||
|
||||
|
||||
# Dummy import session.
|
||||
def import_session(lib=None, logfile=None, paths=[], query=[], cli=False):
|
||||
def import_session(lib=None, loghandler=None, paths=[], query=[], cli=False):
|
||||
cls = commands.TerminalImportSession if cli else importer.ImportSession
|
||||
return cls(lib, logfile, paths, query)
|
||||
return cls(lib, loghandler, paths, query)
|
||||
|
||||
|
||||
# A test harness for all beets tests.
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ class TestHelper(object):
|
|||
config['import']['autotag'] = False
|
||||
config['import']['resume'] = False
|
||||
|
||||
return TestImportSession(self.lib, logfile=None, query=None,
|
||||
return TestImportSession(self.lib, loghandler=None, query=None,
|
||||
paths=[import_dir])
|
||||
|
||||
# Library fixtures methods
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# This file is part of beets.
|
||||
# Copyright 2015, Adrian Sampson.
|
||||
#
|
||||
|
|
@ -33,6 +34,7 @@ from beets.mediafile import MediaFile
|
|||
from beets import autotag
|
||||
from beets.autotag import AlbumInfo, TrackInfo, AlbumMatch
|
||||
from beets import config
|
||||
from beets import logging
|
||||
|
||||
|
||||
class AutotagStub(object):
|
||||
|
|
@ -209,7 +211,7 @@ class ImportHelper(TestHelper):
|
|||
config['import']['link'] = link
|
||||
|
||||
self.importer = TestImportSession(
|
||||
self.lib, logfile=None, query=None,
|
||||
self.lib, loghandler=None, query=None,
|
||||
paths=[import_dir or self.import_dir]
|
||||
)
|
||||
|
||||
|
|
@ -1219,15 +1221,17 @@ class ImportDuplicateSingletonTest(unittest.TestCase, TestHelper):
|
|||
class TagLogTest(_common.TestCase):
|
||||
def test_tag_log_line(self):
|
||||
sio = StringIO.StringIO()
|
||||
session = _common.import_session(logfile=sio)
|
||||
handler = logging.StreamHandler(sio)
|
||||
session = _common.import_session(loghandler=handler)
|
||||
session.tag_log('status', 'path')
|
||||
assert 'status path' in sio.getvalue()
|
||||
self.assertIn('status path', sio.getvalue())
|
||||
|
||||
def test_tag_log_unicode(self):
|
||||
sio = StringIO.StringIO()
|
||||
session = _common.import_session(logfile=sio)
|
||||
session.tag_log('status', 'caf\xc3\xa9')
|
||||
assert 'status caf' in sio.getvalue()
|
||||
handler = logging.StreamHandler(sio)
|
||||
session = _common.import_session(loghandler=handler)
|
||||
session.tag_log('status', u'café') # send unicode
|
||||
self.assertIn(u'status café', sio.getvalue())
|
||||
|
||||
|
||||
class ResumeImportTest(unittest.TestCase, TestHelper):
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ class TerminalImportSessionSetup(object):
|
|||
self.io = DummyIO()
|
||||
self.io.install()
|
||||
self.importer = TestTerminalImportSession(
|
||||
self.lib, logfile=None, query=None, io=self.io,
|
||||
self.lib, loghandler=None, query=None, io=self.io,
|
||||
paths=[import_dir or self.import_dir],
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue