From b325c5a2d84253aeb3fdc01ba848e1f7bd8c6726 Mon Sep 17 00:00:00 2001 From: Sebastian Mohr Date: Wed, 17 Sep 2025 20:55:02 +0200 Subject: [PATCH] Fixed issue with mpdstats test and removed unregister_all function as it introduces issues. --- beets/test/helper.py | 27 ++++++++++++++----------- test/plugins/test_mpdstats.py | 38 ++++++++++++++++++++++------------- test/test_plugins.py | 9 ++++----- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/beets/test/helper.py b/beets/test/helper.py index 9b884e866..1488a24fa 100644 --- a/beets/test/helper.py +++ b/beets/test/helper.py @@ -551,7 +551,7 @@ class PluginMixin(TestHelper): def teardown_beets(self): super().teardown_beets() self.unload_plugins() - self.unregister_plugin(self.plugin) + self.unregister_plugin(name=self.plugin) @staticmethod def register_plugin( @@ -599,12 +599,6 @@ class PluginMixin(TestHelper): if hasattr(parent_pkg, name): delattr(parent_pkg, name) - def unregister_all_plugins(self) -> None: - # Remove plugin modules from sys.modules - for mod in list(sys.modules): - if mod.startswith("beetsplug."): - del sys.modules[mod] - def load_plugins(self, *plugins: str) -> None: """Load and initialize plugins by names. @@ -644,17 +638,26 @@ class PluginMixin(TestHelper): raise ValueError(f"No plugin found with name {name}") @contextmanager - def plugins(self, *plugins: tuple[str, type[beets.plugins.BeetsPlugin]]): + def plugins( + self, *plugins: tuple[str, type[beets.plugins.BeetsPlugin]] | str + ): """Context manager to register and load multiple plugins.""" self.unload_plugins() - for name, plugin_type in plugins: - self.register_plugin(plugin_type, name) - self.load_plugins(*(name for name, _ in plugins)) + + names = [] + for plug in plugins: + if isinstance(plug, str): + names.append(plug) + else: + names.append(plug[0]) + self.register_plugin(plug[1], plug[0]) + self.load_plugins(*names) yield self.unload_plugins() - self.unregister_all_plugins() + for name in names: + self.unregister_plugin(name) @contextmanager def configure_plugin(self, config: Any): diff --git a/test/plugins/test_mpdstats.py b/test/plugins/test_mpdstats.py index 6f5d3f3ce..70e4f7932 100644 --- a/test/plugins/test_mpdstats.py +++ b/test/plugins/test_mpdstats.py @@ -13,15 +13,15 @@ # included in all copies or substantial portions of the Software. -from unittest.mock import ANY, Mock, call, patch +from unittest.mock import ANY, Mock, call from beets import util from beets.library import Item from beets.test.helper import PluginTestCase -from beetsplug.mpdstats import MPDStats +from beetsplug.mpdstats import MPDClientWrapper, MPDStats -class MPDStatsTest(PluginTestCase): +class TestMPDStats(PluginTestCase): plugin = "mpdstats" def test_update_rating(self): @@ -53,24 +53,34 @@ class MPDStatsTest(PluginTestCase): {"state": "play", "songid": 1, "time": "0:1"}, {"state": "stop"}, ] + EVENTS = [["player"]] * (len(STATUSES) - 1) + [KeyboardInterrupt] item_path = util.normpath("/foo/bar.flac") songid = 1 - @patch( - "beetsplug.mpdstats.MPDClientWrapper", - return_value=Mock( - **{ - "events.side_effect": EVENTS, - "status.side_effect": STATUSES, - "currentsong.return_value": (item_path, songid), - } - ), - ) - def test_run_mpdstats(self, mpd_mock): + def test_run_mpdstats(self, monkeypatch): item = Item(title="title", path=self.item_path, id=1) item.add(self.lib) + statuses = iter(self.STATUSES) + events = iter(self.EVENTS) + + def iter_event_or_raise(*args): + i = next(events) + if i is KeyboardInterrupt: + raise i + return i + + monkeypatch.setattr( + MPDClientWrapper, "status", lambda _: next(statuses) + ) + monkeypatch.setattr( + MPDClientWrapper, + "currentsong", + lambda x: (self.item_path, self.songid), + ) + monkeypatch.setattr(MPDClientWrapper, "events", iter_event_or_raise) + monkeypatch.setattr(MPDClientWrapper, "connect", lambda *_: None) log = Mock() try: MPDStats(self.lib, log).run() diff --git a/test/test_plugins.py b/test/test_plugins.py index 448a567d7..b169a3d9b 100644 --- a/test/test_plugins.py +++ b/test/test_plugins.py @@ -506,11 +506,10 @@ class TestImportPlugin(PluginMixin): def test_import_plugin(self, caplog, plugin_name): """Test that a plugin is importable without an error.""" caplog.set_level(logging.WARNING) - self.load_plugins(plugin_name) - - assert "PluginImportError" not in caplog.text, ( - f"Plugin '{plugin_name}' has issues during import." - ) + with self.plugins(plugin_name): + assert "PluginImportError" not in caplog.text, ( + f"Plugin '{plugin_name}' has issues during import." + ) def test_import_error(self, caplog): """Test that an invalid plugin raises PluginImportError."""