mirror of
https://github.com/beetbox/beets.git
synced 2026-01-03 22:42:44 +01:00
Check files during import, show checker warnings and errors along with tagging choices.
This commit is contained in:
parent
d226632eeb
commit
e96b5a7eba
3 changed files with 65 additions and 19 deletions
|
|
@ -472,6 +472,7 @@ class ImportTask(BaseImportTask):
|
|||
def __init__(self, toppath, paths, items):
|
||||
super(ImportTask, self).__init__(toppath, paths, items)
|
||||
self.choice_flag = None
|
||||
self.skip_summary_judgement = False
|
||||
self.cur_album = None
|
||||
self.cur_artist = None
|
||||
self.candidates = []
|
||||
|
|
|
|||
|
|
@ -698,14 +698,18 @@ class TerminalImportSession(importer.ImportSession):
|
|||
print_(displayable_path(task.paths, u'\n') +
|
||||
u' ({0} items)'.format(len(task.items)))
|
||||
|
||||
# Take immediate action if appropriate.
|
||||
action = _summary_judgment(task.rec)
|
||||
if action == importer.action.APPLY:
|
||||
match = task.candidates[0]
|
||||
show_change(task.cur_artist, task.cur_album, match)
|
||||
return match
|
||||
elif action is not None:
|
||||
return action
|
||||
# Call here so plugins have the option to skip `_summary_judgement`
|
||||
choices = self._get_choices(task)
|
||||
|
||||
if not task.skip_summary_judgement:
|
||||
# Take immediate action if appropriate.
|
||||
action = _summary_judgment(task.rec)
|
||||
if action == importer.action.APPLY:
|
||||
match = task.candidates[0]
|
||||
show_change(task.cur_artist, task.cur_album, match)
|
||||
return match
|
||||
elif action is not None:
|
||||
return action
|
||||
|
||||
# Loop until we have a choice.
|
||||
while True:
|
||||
|
|
@ -713,7 +717,6 @@ class TerminalImportSession(importer.ImportSession):
|
|||
# `choose_candidate` may be an `importer.action`, an
|
||||
# `AlbumMatch` object for a specific selection, or a
|
||||
# `PromptChoice`.
|
||||
choices = self._get_choices(task)
|
||||
choice = choose_candidate(
|
||||
task.candidates, False, task.rec, task.cur_artist,
|
||||
task.cur_album, itemcount=len(task.items), choices=choices
|
||||
|
|
@ -742,6 +745,8 @@ class TerminalImportSession(importer.ImportSession):
|
|||
assert isinstance(choice, autotag.AlbumMatch)
|
||||
return choice
|
||||
|
||||
choices = self._get_choices(task)
|
||||
|
||||
def choose_item(self, task):
|
||||
"""Ask the user for a choice about tagging a single item. Returns
|
||||
either an action constant or a TrackMatch object.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ from beets.plugins import BeetsPlugin
|
|||
from beets.ui import Subcommand
|
||||
from beets.util import displayable_path, par_map
|
||||
from beets import ui
|
||||
from beets import importer
|
||||
|
||||
|
||||
class CheckerCommandException(Exception):
|
||||
|
|
@ -54,6 +55,11 @@ class BadFiles(BeetsPlugin):
|
|||
super(BadFiles, self).__init__()
|
||||
self.verbose = False
|
||||
|
||||
self.register_listener('import_task_start',
|
||||
self.on_import_task_start)
|
||||
self.register_listener('before_choose_candidate',
|
||||
self.on_before_choose_candidate)
|
||||
|
||||
def run_command(self, cmd):
|
||||
self._log.debug(u"running command: {}",
|
||||
displayable_path(list2cmdline(cmd)))
|
||||
|
|
@ -115,7 +121,7 @@ class BadFiles(BeetsPlugin):
|
|||
if not checker:
|
||||
self._log.error(u"no checker specified in the config for {}",
|
||||
ext)
|
||||
return
|
||||
return []
|
||||
path = item.path
|
||||
if not isinstance(path, six.text_type):
|
||||
path = item.path.decode(sys.getfilesystemencoding())
|
||||
|
|
@ -130,25 +136,59 @@ class BadFiles(BeetsPlugin):
|
|||
)
|
||||
else:
|
||||
self._log.error(u"error invoking {}: {}", e.checker, e.msg)
|
||||
return
|
||||
return []
|
||||
|
||||
error_lines = []
|
||||
|
||||
if status > 0:
|
||||
ui.print_(u"{}: checker exited with status {}"
|
||||
.format(ui.colorize('text_error', dpath), status))
|
||||
error_lines.append(u"{}: checker exited with status {}"
|
||||
.format(ui.colorize('text_error', dpath), status))
|
||||
for line in output:
|
||||
ui.print_(u" {}".format(line))
|
||||
error_lines.append(u" {}".format(line))
|
||||
|
||||
elif errors > 0:
|
||||
ui.print_(u"{}: checker found {} errors or warnings"
|
||||
.format(ui.colorize('text_warning', dpath), errors))
|
||||
error_lines.append(u"{}: checker found {} errors or warnings"
|
||||
.format(ui.colorize('text_warning', dpath), errors))
|
||||
for line in output:
|
||||
ui.print_(u" {}".format(line))
|
||||
error_lines.append(u" {}".format(line))
|
||||
elif self.verbose:
|
||||
ui.print_(u"{}: ok".format(ui.colorize('text_success', dpath)))
|
||||
error_lines.append(u"{}: ok".format(ui.colorize('text_success', dpath)))
|
||||
|
||||
return error_lines
|
||||
|
||||
def on_import_task_start(self, task, session):
|
||||
checks_failed = []
|
||||
|
||||
for item in task.items:
|
||||
error_lines = self.check_item(item)
|
||||
if error_lines:
|
||||
checks_failed.append(error_lines)
|
||||
|
||||
if checks_failed:
|
||||
task._badfiles_checks_failed = checks_failed
|
||||
task.skip_summary_judgement = True
|
||||
|
||||
def on_before_choose_candidate(self, task, session):
|
||||
if hasattr(task, '_badfiles_checks_failed'):
|
||||
ui.print_('{} one or more files failed checks:'
|
||||
.format(ui.colorize('text_warning', 'BAD')))
|
||||
for error in task._badfiles_checks_failed:
|
||||
for error_line in error:
|
||||
ui.print_(error_line)
|
||||
|
||||
ui.print_()
|
||||
|
||||
|
||||
def command(self, lib, opts, args):
|
||||
# Get items from arguments
|
||||
items = lib.items(ui.decargs(args))
|
||||
self.verbose = opts.verbose
|
||||
par_map(self.check_item, items)
|
||||
|
||||
def check_and_print(item):
|
||||
for error_line in self.check_item(item):
|
||||
ui.print_(error_line)
|
||||
|
||||
par_map(check_and_print, items)
|
||||
|
||||
def commands(self):
|
||||
bad_command = Subcommand('bad',
|
||||
|
|
|
|||
Loading…
Reference in a new issue