Skip to content

Commit 1d4a2c3

Browse files
committed
Add a new hook for badfiles pre-import user interaction, instead of flagging the task.
1 parent 9c17d9a commit 1d4a2c3

File tree

4 files changed

+48
-19
lines changed

4 files changed

+48
-19
lines changed

beets/importer.py

-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,6 @@ class ImportTask(BaseImportTask):
472472
def __init__(self, toppath, paths, items):
473473
super(ImportTask, self).__init__(toppath, paths, items)
474474
self.choice_flag = None
475-
self.skip_summary_judgement = False
476475
self.cur_album = None
477476
self.cur_artist = None
478477
self.candidates = []

beets/plugins.py

+16
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,22 @@ def send(event, **arguments):
501501
return results
502502

503503

504+
def send_seq(event, **arguments):
505+
"""Like `send` but passes the result of the previous event handler to the
506+
next, and returns only the result of the last non-None event handler.
507+
508+
`event` is the name of the event to send, all other named arguments
509+
are passed along to the handlers.
510+
"""
511+
log.debug(u'Sequentially sending event: {0}', event)
512+
previous = None
513+
for handler in event_handlers()[event]:
514+
result = handler(previous=previous, **arguments)
515+
previous = result or previous
516+
517+
return previous
518+
519+
504520
def feat_tokens(for_artist=True):
505521
"""Return a regular expression that matches phrases like "featuring"
506522
that separate a main artist or a song title from secondary artists.

beets/ui/commands.py

+16-14
Original file line numberDiff line numberDiff line change
@@ -698,25 +698,29 @@ def choose_match(self, task):
698698
print_(displayable_path(task.paths, u'\n') +
699699
u' ({0} items)'.format(len(task.items)))
700700

701-
# Call here so plugins have the option to skip `_summary_judgement`
702-
choices = self._get_choices(task)
703-
704-
if not task.skip_summary_judgement:
705-
# Take immediate action if appropriate.
706-
action = _summary_judgment(task.rec)
707-
if action == importer.action.APPLY:
708-
match = task.candidates[0]
709-
show_change(task.cur_artist, task.cur_album, match)
710-
return match
711-
elif action is not None:
712-
return action
701+
# Let plugins display info or prompt the user before we go through the
702+
# process of selecting candidate.
703+
action = plugins.send_seq('import_task_before_choice',
704+
session=self, task=task)
705+
if action is not None:
706+
return action
707+
708+
# Take immediate action if appropriate.
709+
action = _summary_judgment(task.rec)
710+
if action == importer.action.APPLY:
711+
match = task.candidates[0]
712+
show_change(task.cur_artist, task.cur_album, match)
713+
return match
714+
elif action is not None:
715+
return action
713716

714717
# Loop until we have a choice.
715718
while True:
716719
# Ask for a choice from the user. The result of
717720
# `choose_candidate` may be an `importer.action`, an
718721
# `AlbumMatch` object for a specific selection, or a
719722
# `PromptChoice`.
723+
choices = self._get_choices(task)
720724
choice = choose_candidate(
721725
task.candidates, False, task.rec, task.cur_artist,
722726
task.cur_album, itemcount=len(task.items), choices=choices
@@ -745,8 +749,6 @@ def choose_match(self, task):
745749
assert isinstance(choice, autotag.AlbumMatch)
746750
return choice
747751

748-
choices = self._get_choices(task)
749-
750752
def choose_item(self, task):
751753
"""Ask the user for a choice about tagging a single item. Returns
752754
either an action constant or a TrackMatch object.

beetsplug/badfiles.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from beets.ui import Subcommand
3131
from beets.util import displayable_path, par_map
3232
from beets import ui
33+
from beets import importer
3334

3435

3536
class CheckerCommandException(Exception):
@@ -56,8 +57,8 @@ def __init__(self):
5657

5758
self.register_listener('import_task_start',
5859
self.on_import_task_start)
59-
self.register_listener('before_choose_candidate',
60-
self.on_before_choose_candidate)
60+
self.register_listener('import_task_before_choice',
61+
self.on_import_task_before_choice)
6162

6263
def run_command(self, cmd):
6364
self._log.debug(u"running command: {}",
@@ -171,9 +172,8 @@ def on_import_task_start(self, task, session):
171172

172173
if checks_failed:
173174
task._badfiles_checks_failed = checks_failed
174-
task.skip_summary_judgement = True
175175

176-
def on_before_choose_candidate(self, task, session):
176+
def on_import_task_before_choice(self, task, session, previous):
177177
if hasattr(task, '_badfiles_checks_failed'):
178178
ui.print_('{} one or more files failed checks:'
179179
.format(ui.colorize('text_warning', 'BAD')))
@@ -182,6 +182,18 @@ def on_before_choose_candidate(self, task, session):
182182
ui.print_(error_line)
183183

184184
ui.print_()
185+
ui.print_('What would you like to do?')
186+
187+
sel = ui.input_options(['aBort', 'skip', 'continue'])
188+
189+
if sel == 's':
190+
return importer.action.SKIP
191+
elif sel == 'c':
192+
return None
193+
elif sel == 'b':
194+
raise importer.ImportAbort()
195+
else:
196+
raise Exception('Unexpected selection: {}'.format(sel))
185197

186198
def command(self, lib, opts, args):
187199
# Get items from arguments

0 commit comments

Comments
 (0)