Skip to content

Commit

Permalink
Use PluginMixin in tests that load plugins manually
Browse files Browse the repository at this point in the history
A constant `preload_plugin` is used to disable loading the plugin in the
`setUp` initialisation, allowing the plugin to be loaded manually by the
tests.

Also added a cleanup instruction to remove listeners from configured
plugins, and removed this logic from several tests.
  • Loading branch information
snejus committed Jul 28, 2024
1 parent 9c75513 commit 199f307
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 92 deletions.
76 changes: 40 additions & 36 deletions beets/test/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,41 +221,6 @@ def teardown_beets(self):
beets.config.clear()
beets.config._materialized = False

def load_plugins(self, *plugins):
"""Load and initialize plugins by names.
Similar setting a list of plugins in the configuration. Make
sure you call ``unload_plugins()`` afterwards.
"""
# FIXME this should eventually be handled by a plugin manager
plugins = (self.plugin,) if hasattr(self, "plugin") else plugins
beets.config["plugins"] = plugins
beets.plugins.load_plugins(plugins)
beets.plugins.find_plugins()

# Take a backup of the original _types and _queries to restore
# when unloading.
Item._original_types = dict(Item._types)
Album._original_types = dict(Album._types)
Item._types.update(beets.plugins.types(Item))
Album._types.update(beets.plugins.types(Album))

Item._original_queries = dict(Item._queries)
Album._original_queries = dict(Album._queries)
Item._queries.update(beets.plugins.named_queries(Item))
Album._queries.update(beets.plugins.named_queries(Album))

def unload_plugins(self):
"""Unload all plugins and remove them from the configuration."""
# FIXME this should eventually be handled by a plugin manager
beets.config["plugins"] = []
beets.plugins._classes = set()
beets.plugins._instances = {}
Item._types = getattr(Item, "_original_types", {})
Album._types = getattr(Album, "_original_types", {})
Item._queries = getattr(Item, "_original_queries", {})
Album._queries = getattr(Album, "_original_queries", {})

# Library fixtures methods

def create_item(self, **values):
Expand Down Expand Up @@ -485,15 +450,54 @@ def setUp(self):

class PluginMixin:
plugin: ClassVar[str]
preload_plugin: ClassVar[bool] = True

def setUp(self):
super().setUp()
self.load_plugins()
if self.preload_plugin:
self.load_plugins()

def tearDown(self):
super().tearDown()
self.unload_plugins()

def load_plugins(self, *plugins: str) -> None:
"""Load and initialize plugins by names.
Similar setting a list of plugins in the configuration. Make
sure you call ``unload_plugins()`` afterwards.
"""
# FIXME this should eventually be handled by a plugin manager
plugins = (self.plugin,) if hasattr(self, "plugin") else plugins
beets.config["plugins"] = plugins
beets.plugins.load_plugins(plugins)
beets.plugins.find_plugins()

# Take a backup of the original _types and _queries to restore
# when unloading.
Item._original_types = dict(Item._types)
Album._original_types = dict(Album._types)
Item._types.update(beets.plugins.types(Item))
Album._types.update(beets.plugins.types(Album))

Item._original_queries = dict(Item._queries)
Album._original_queries = dict(Album._queries)
Item._queries.update(beets.plugins.named_queries(Item))
Album._queries.update(beets.plugins.named_queries(Album))

def unload_plugins(self) -> None:
"""Unload all plugins and remove them from the configuration."""
# FIXME this should eventually be handled by a plugin manager
for plugin_class in beets.plugins._instances:
plugin_class.listeners = None
beets.config["plugins"] = []
beets.plugins._classes = set()
beets.plugins._instances = {}
Item._types = getattr(Item, "_original_types", {})
Album._types = getattr(Album, "_original_types", {})
Item._queries = getattr(Item, "_original_queries", {})
Album._queries = getattr(Album, "_original_queries", {})


class PluginTestCase(PluginMixin, BeetsTestCase):
pass
Expand Down
9 changes: 4 additions & 5 deletions test/plugins/test_advancedrewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@
"""


from beets.test.helper import BeetsTestCase
from beets.test.helper import BeetsTestCase, PluginMixin
from beets.ui import UserError

PLUGIN_NAME = "advancedrewrite"


class AdvancedRewritePluginTest(BeetsTestCase):
def tearDown(self):
self.unload_plugins()
super().tearDown()
class AdvancedRewritePluginTest(PluginMixin, BeetsTestCase):
plugin = "advancedrewrite"
preload_plugin = False

def test_simple_rewrite_example(self):
self.config[PLUGIN_NAME] = [
Expand Down
6 changes: 0 additions & 6 deletions test/plugins/test_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
TerminalImportMixin,
control_stdin,
)
from beetsplug.edit import EditPlugin


class ModifyFileMocker:
Expand Down Expand Up @@ -135,10 +134,6 @@ def setUp(self):
{f: item[f] for f in item._fields} for item in self.album.items()
]

def tearDown(self):
EditPlugin.listeners = None
super().tearDown()

def assertCounts( # noqa
self,
mock_write,
Expand Down Expand Up @@ -338,7 +333,6 @@ def setUp(self):
self.matcher.matching = AutotagStub.GOOD

def tearDown(self):
EditPlugin.listeners = None
super().tearDown()
self.matcher.restore()

Expand Down
13 changes: 5 additions & 8 deletions test/plugins/test_filefilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,18 @@
"""Tests for the `filefilter` plugin.
"""
from beets import config
from beets.test.helper import ImportTestCase
from beets.test.helper import ImportTestCase, PluginMixin
from beets.util import bytestring_path
from beetsplug.filefilter import FileFilterPlugin


class FileFilterPluginMixin(ImportTestCase):
class FileFilterPluginMixin(PluginMixin, ImportTestCase):
plugin = "filefilter"
preload_plugin = False

def setUp(self):
super().setUp()
self.prepare_tracks_for_import()

def tearDown(self):
self.unload_plugins()
FileFilterPlugin.listeners = None
super().tearDown()

def prepare_tracks_for_import(self):
self.album_track, self.other_album_track, self.single_track = (
bytestring_path(self.prepare_album_for_import(1, album_path=p)[0])
Expand Down
10 changes: 4 additions & 6 deletions test/plugins/test_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import unittest

from beets import config, plugins
from beets.test.helper import BeetsTestCase, capture_log
from beets.test.helper import BeetsTestCase, PluginMixin, capture_log


def get_temporary_path():
Expand All @@ -29,13 +29,11 @@ def get_temporary_path():
return os.path.join(temporary_directory, temporary_name)


class HookTest(BeetsTestCase):
class HookTest(PluginMixin, BeetsTestCase):
plugin = "hook"
preload_plugin = False
TEST_HOOK_COUNT = 5

def tearDown(self):
self.unload_plugins()
super().tearDown()

def _add_hook(self, event, command):
hook = {"event": event, "command": command}

Expand Down
13 changes: 6 additions & 7 deletions test/plugins/test_playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@

import beets
from beets.test import _common
from beets.test.helper import BeetsTestCase
from beets.test.helper import PluginTestCase


class PlaylistTestCase(BeetsTestCase):
class PlaylistTestCase(PluginTestCase):
plugin = "playlist"
preload_plugin = False

def setUp(self):
super().setUp()

Expand Down Expand Up @@ -77,15 +80,11 @@ def setUp(self):
self.config["playlist"]["playlist_dir"] = self.playlist_dir

self.setup_test()
self.load_plugins("playlist")
self.load_plugins()

def setup_test(self):
raise NotImplementedError

def tearDown(self):
self.unload_plugins()
super().tearDown()


class PlaylistQueryTest:
def test_name_query_with_absolute_paths_in_playlist(self):
Expand Down
21 changes: 11 additions & 10 deletions test/plugins/test_replaygain.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
from mediafile import MediaFile

from beets import config
from beets.test.helper import AsIsImporterMixin, ImportTestCase, has_program
from beets.test.helper import (
AsIsImporterMixin,
ImportTestCase,
PluginMixin,
has_program,
)
from beetsplug.replaygain import (
FatalGstreamerPluginReplayGainError,
GStreamerBackend,
Expand Down Expand Up @@ -52,8 +57,11 @@ def reset_replaygain(item):
item.store()


class ReplayGainTestCase(ImportTestCase):
class ReplayGainTestCase(PluginMixin, ImportTestCase):
db_on_disk = True
plugin = "replaygain"
preload_plugin = False

backend: ClassVar[str]

def setUp(self):
Expand All @@ -63,14 +71,7 @@ def setUp(self):
super().setUp()
self.config["replaygain"]["backend"] = self.backend

try:
self.load_plugins("replaygain")
except Exception:
self.tearDown()

def tearDown(self):
self.unload_plugins()
super().tearDown()
self.load_plugins()


class ThreadedImportMixin:
Expand Down
12 changes: 5 additions & 7 deletions test/plugins/test_zero.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
from mediafile import MediaFile

from beets.library import Item
from beets.test.helper import BeetsTestCase, control_stdin
from beets.test.helper import BeetsTestCase, PluginMixin, control_stdin
from beets.util import syspath
from beetsplug.zero import ZeroPlugin


class ZeroPluginTest(BeetsTestCase):
class ZeroPluginTest(PluginMixin, BeetsTestCase):
plugin = "zero"
preload_plugin = False

def setUp(self):
super().setUp()
self.config["zero"] = {
Expand All @@ -17,11 +20,6 @@ def setUp(self):
"update_database": False,
}

def tearDown(self):
ZeroPlugin.listeners = None
super().tearDown()
self.unload_plugins()

def test_no_patterns(self):
self.config["zero"]["fields"] = ["comments", "month"]

Expand Down
7 changes: 0 additions & 7 deletions test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,6 @@ def setUp(self):
beetsplug.dummy = self.DummyModule
super().setUp()

def tearDown(self):
super().tearDown()
del beetsplug.dummy
sys.modules.pop("beetsplug.dummy")
self.DummyModule.DummyPlugin.listeners = None
self.DummyModule.DummyPlugin._raw_listeners = None

def test_command_level0(self):
self.config["verbose"] = 0
with helper.capture_log() as logs:
Expand Down

0 comments on commit 199f307

Please sign in to comment.