Is there a hook event for successful imports only?

I want to write a hook that can “clean up” imported albums after they’re successfully imported (for various reasons, I don’t want to just let beet move the files; I’d rather beet do a copy and then let me clean up the old files myself).

However, I can’t seem to find a hook event that fits this fairly basic use-case.

  • The import event seemed like the most promising option, since the documentation says:

    called after a beet import command finishes (the lib keyword argument is a Library object; paths is a list of paths (strings) that were imported

    However, this seems to be misleading, since the event fires after every import command (even those that didn’t “finish”) and paths contains every path that was passed to import, regardless of whether it was actually imported or not (if it was skipped, for instance). So with no clear way for my script to distinguish between actually-imported albums and non-imported ones, this event doesn’t work.

  • album_imported also seemed promising, since it does correctly fire only after an album is actually imported, but unfortunately there’s nothing in the lib or album parameters that tells me which path was actually being imported, so the hook has no way to clean up just those files.

  • import_task_apply also seemed relevant but it doesn’t seem to fire at all, my test command wasn’t firing after an import whether successful or not; and anyway even if it had, it wasn’t clear whether any of its parameters would include the path being imported anyway.

Short of writing a full plugin with a new pipeline stage, is there any way for hook to accomplish what I’m trying to do here? And if not, would it be possible to add some sort of new parameter to the import callback that itemizes whether each item in paths was actually imported or not? That seems like a pretty generically useful thing to have.


Okay with a bit more experimentation, I think I’ve found it; import_task_files seems to fire at the right time, and task.paths is a list containing the precise paths that were imported, one task at a time. Excellent!

My only remaining question is, given whatever format-string syntax Beets is using, is there a way for me to easily do the equivalent of " ".join(task.paths) in the hook’s command? The usual {*task.paths} doesn’t appear to work. For now I’m just doing {task.paths[0]} which is good enough for most cases since most album imports are from a single path, but I can imagine scenarios where task.paths might have length greater than 1.

Cool! FWIW, those templates use Python’s str.format templates. Unfortunately, that system can only really do simple lookups and (while I would be happy to be proven wrong) I don’t think there is a way to invoke str.join from there.