importsource: Catch importer crash when skipping; Fix original changelog entry; Add new tests (#6203)

Prevents a crash when "skip" is selected in the importer and
`task.imported_items()` runs into a condition branch that supposedly
should never be reached:

```
  File "beets/beets/importer/tasks.py", line 254, in imported_items
    assert False
           ^^^^^
AssertionError
```

- Since for items/albums that should be skipped, looping through
`task.imported_items()` is not required anyway, the fix here is to exit
early from the function that calls it.
- Additionally this PR fixes the original changelog entry which was
located at an older releases "new features list". Also now it briefly
explains to changelog readers what the plugin actually does.
- Two new tests were added that proof that "skip doesn't crash" and
reimports never "suggest removal of source files"

---------

Co-authored-by: Doron Behar <doron.behar@gmail.com>
This commit is contained in:
J0J0 Todos 2025-12-21 20:35:27 +01:00 committed by GitHub
commit 5d1210ada5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 37 additions and 2 deletions

View file

@ -39,6 +39,8 @@ class ImportSourcePlugin(BeetsPlugin):
)
def prevent_suggest_removal(self, session, task):
if task.skip:
return
for item in task.imported_items():
if "mb_albumid" in item:
self.stop_suggestions_for_albums.add(item.mb_albumid)

View file

@ -24,6 +24,9 @@ New features:
to receive extra verbose logging around last.fm results and how they are
resolved. The ``extended_debug`` config setting and ``--debug`` option
have been removed.
- :doc:`plugins/importsource`: Added new plugin that tracks original import
paths and optionally suggests removing source files when items are removed
from the library.
- :doc:`plugins/mbpseudo`: Add a new `mbpseudo` plugin to proactively receive
MusicBrainz pseudo-releases as recommendations during import.
- Added support for Python 3.13.
@ -491,7 +494,6 @@ New features:
``beet list -a title:something`` or ``beet list artpath:cover``. Consequently
album queries involving ``path`` field have been sped up, like ``beet list -a
path:/path/``.
- :doc:`plugins/importsource`: Added plugin
- :doc:`plugins/ftintitle`: New ``keep_in_artist`` option for the plugin, which
allows keeping the "feat." part in the artist metadata while still changing
the title.

View file

@ -18,7 +18,7 @@
import os
import time
from beets import importer
from beets import importer, plugins
from beets.test.helper import AutotagImportTestCase, PluginMixin, control_stdin
from beets.util import syspath
from beetsplug.importsource import ImportSourcePlugin
@ -113,3 +113,34 @@ class ImportSourceTest(PluginMixin, AutotagImportTestCase):
assert current_mtime == original_mtime, (
f"Source file timestamp changed: {path}"
)
def test_prevent_suggest_removal_on_reimport(self):
"""Test that removal suggestions are prevented during reimport."""
album = self.lib.albums().get()
mb_albumid = album.mb_albumid
# Reimport from library
reimporter = self.setup_importer(import_dir=self.libdir)
reimporter.add_choice(importer.Action.APPLY)
reimporter.run()
plugin = plugins._instances[0]
assert mb_albumid in plugin.stop_suggestions_for_albums
# Calling suggest_removal should exit early without prompting
item = self.lib.items().get()
plugin.suggest_removal(item)
assert os.path.exists(item.source_path)
def test_prevent_suggest_removal_handles_skipped_task(self):
"""Test that skipped tasks don't crash prevent_suggest_removal."""
class MockTask:
skip = True
def imported_items(self):
return "whatever"
plugin = plugins._instances[0]
mock_task = MockTask()
plugin.prevent_suggest_removal(None, mock_task)