From 6ad9283629d6df89d9ccc2e5f8bf456d04efa6eb Mon Sep 17 00:00:00 2001 From: J0J0 Todos Date: Sat, 17 Jan 2026 08:51:03 +0100 Subject: [PATCH 1/3] importsource: Only register listener if configured and remove the now redundant config sanity check in suggest_removal(). --- beetsplug/importsource.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/beetsplug/importsource.py b/beetsplug/importsource.py index e42be3f1f..67330ef1a 100644 --- a/beetsplug/importsource.py +++ b/beetsplug/importsource.py @@ -26,17 +26,19 @@ class ImportSourcePlugin(BeetsPlugin): } ) self.import_stages = [self.import_stage] - self.register_listener("item_removed", self.suggest_removal) - # In order to stop future removal suggestions for an album we keep - # track of `mb_albumid`s in this set. - self.stop_suggestions_for_albums = set() - # During reimports (import --library) both the import_task_choice and - # the item_removed event are triggered. The item_removed event is - # triggered first. For the import_task_choice event we prevent removal - # suggestions using the existing stop_suggestions_for_album mechanism. - self.register_listener( - "import_task_choice", self.prevent_suggest_removal - ) + # Only register removal suggestion listeners if the feature is enabled + if self.config["suggest_removal"]: + # In order to stop future removal suggestions for an album we keep + # track of `mb_albumid`s in this set. + self.stop_suggestions_for_albums = set() + self.register_listener("item_removed", self.suggest_removal) + # During reimports (import --library) both the import_task_choice and + # the item_removed event are triggered. The item_removed event is + # triggered first. For the import_task_choice event we prevent removal + # suggestions using the existing stop_suggestions_for_album mechanism. + self.register_listener( + "import_task_choice", self.prevent_suggest_removal + ) def prevent_suggest_removal(self, session, task): if task.skip: @@ -60,10 +62,7 @@ class ImportSourcePlugin(BeetsPlugin): def suggest_removal(self, item): """Prompts the user to delete the original path the item was imported from.""" - if ( - not self.config["suggest_removal"] - or item.mb_albumid in self.stop_suggestions_for_albums - ): + if item.mb_albumid in self.stop_suggestions_for_albums: return if "source_path" not in item: From ad2100105fcb34a1ec5302ee14d9d597e5a0a89f Mon Sep 17 00:00:00 2001 From: J0J0 Todos Date: Sat, 17 Jan 2026 09:10:21 +0100 Subject: [PATCH 2/3] importsource: Test listeners based on config --- test/plugins/test_importsource.py | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/plugins/test_importsource.py b/test/plugins/test_importsource.py index 7306558a1..16fe1f191 100644 --- a/test/plugins/test_importsource.py +++ b/test/plugins/test_importsource.py @@ -142,3 +142,35 @@ class ImportSourceTest(IOMixin, PluginMixin, AutotagImportTestCase): plugin = plugins._instances[0] mock_task = MockTask() plugin.prevent_suggest_removal(None, mock_task) + + +class ImportSourceTestListenerRegistration(PluginMixin, AutotagImportTestCase): + """Test listener registration based on config.""" + + plugin = "importsource" + preload_plugin = False + + def setUp(self): + preserve_plugin_listeners() + super().setUp() + + def test_listeners_not_registered_when_disabled(self): + """Test that listeners are not registered when suggest_removal is False.""" + self.config[self.plugin]["suggest_removal"] = False + self.load_plugins() + + plugin = plugins._instances[0] + assert not hasattr(plugin, "stop_suggestions_for_albums") + assert "item_removed" not in plugin._raw_listeners + assert "import_task_choice" not in plugin._raw_listeners + + def test_listeners_registered_when_enabled(self): + """Test that listeners are registered when suggest_removal is True.""" + self.config[self.plugin]["suggest_removal"] = True + self.load_plugins() + + plugin = plugins._instances[0] + assert hasattr(plugin, "stop_suggestions_for_albums") + assert isinstance(plugin.stop_suggestions_for_albums, set) + assert "item_removed" in plugin._raw_listeners + assert "import_task_choice" in plugin._raw_listeners From 690511d2ad6a6b7eb99798fd3795c195f8e0d54d Mon Sep 17 00:00:00 2001 From: J0J0 Todos <2733783+JOJ0@users.noreply.github.com> Date: Sun, 1 Mar 2026 10:30:51 +0100 Subject: [PATCH 3/3] Update beetsplug/importsource.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- beetsplug/importsource.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/beetsplug/importsource.py b/beetsplug/importsource.py index 67330ef1a..39ba5b6ab 100644 --- a/beetsplug/importsource.py +++ b/beetsplug/importsource.py @@ -26,11 +26,12 @@ class ImportSourcePlugin(BeetsPlugin): } ) self.import_stages = [self.import_stage] + # In order to stop future removal suggestions for an album we keep + # track of `mb_albumid`s in this set. Always initialize to avoid + # AttributeError when methods access this even if feature disabled. + self.stop_suggestions_for_albums = set() # Only register removal suggestion listeners if the feature is enabled if self.config["suggest_removal"]: - # In order to stop future removal suggestions for an album we keep - # track of `mb_albumid`s in this set. - self.stop_suggestions_for_albums = set() self.register_listener("item_removed", self.suggest_removal) # During reimports (import --library) both the import_task_choice and # the item_removed event are triggered. The item_removed event is