mirror of
https://github.com/beetbox/beets.git
synced 2026-01-09 01:15:38 +01:00
only load plugins from specified modules
Eliminate the __subclasses__ trick for finding all plugins. Now we explicitly look in each plugin module for a plugin class. This allows us to import plugin modules with unintentionally loading them. This lets us reuse the image embedding machinery without copypasta.
This commit is contained in:
parent
e316d0ea30
commit
71a5a5b02f
3 changed files with 14 additions and 28 deletions
|
|
@ -22,7 +22,6 @@ from collections import defaultdict
|
|||
from beets import mediafile
|
||||
|
||||
PLUGIN_NAMESPACE = 'beetsplug'
|
||||
DEFAULT_PLUGINS = []
|
||||
|
||||
# Plugins using the Last.fm API can share the same API key.
|
||||
LASTFM_KEY = '2dc3914abf35f0d9c92d97d8f8e42b43'
|
||||
|
|
@ -151,24 +150,29 @@ class BeetsPlugin(object):
|
|||
return func
|
||||
return helper
|
||||
|
||||
_classes = set()
|
||||
def load_plugins(names=()):
|
||||
"""Imports the modules for a sequence of plugin names. Each name
|
||||
must be the name of a Python module under the "beetsplug" namespace
|
||||
package in sys.path; the module indicated should contain the
|
||||
BeetsPlugin subclasses desired. A default set of plugins is also
|
||||
loaded.
|
||||
BeetsPlugin subclasses desired.
|
||||
"""
|
||||
for name in itertools.chain(names, DEFAULT_PLUGINS):
|
||||
for name in names:
|
||||
modname = '%s.%s' % (PLUGIN_NAMESPACE, name)
|
||||
try:
|
||||
try:
|
||||
__import__(modname, None, None)
|
||||
namespace = __import__(modname, None, None)
|
||||
except ImportError as exc:
|
||||
# Again, this is hacky:
|
||||
if exc.args[0].endswith(' ' + name):
|
||||
log.warn('** plugin %s not found' % name)
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
for obj in getattr(namespace, name).__dict__.values():
|
||||
if isinstance(obj, type) and issubclass(obj, BeetsPlugin):
|
||||
_classes.add(obj)
|
||||
|
||||
except:
|
||||
log.warn('** error loading plugin %s' % name)
|
||||
log.warn(traceback.format_exc())
|
||||
|
|
@ -181,7 +185,7 @@ def find_plugins():
|
|||
"""
|
||||
load_plugins()
|
||||
plugins = []
|
||||
for cls in BeetsPlugin.__subclasses__():
|
||||
for cls in _classes:
|
||||
# Only instantiate each plugin class once.
|
||||
if cls not in _instances:
|
||||
_instances[cls] = cls()
|
||||
|
|
|
|||
|
|
@ -22,34 +22,14 @@ from subprocess import Popen, PIPE
|
|||
import imghdr
|
||||
|
||||
from beets.plugins import BeetsPlugin
|
||||
from beets import ui, library, util, mediafile
|
||||
from beets import ui, library, util
|
||||
from beetsplug.embedart import _embed
|
||||
|
||||
log = logging.getLogger('beets')
|
||||
DEVNULL = open(os.devnull, 'wb')
|
||||
conf = {}
|
||||
|
||||
|
||||
def _embed(path, items):
|
||||
"""Embed an image file, located at `path`, into each item.
|
||||
"""
|
||||
data = open(util.syspath(path), 'rb').read()
|
||||
kindstr = imghdr.what(None, data)
|
||||
if kindstr not in ('jpeg', 'png'):
|
||||
log.error('A file of type %s is not allowed as coverart.' % kindstr)
|
||||
return
|
||||
log.debug('Embedding album art.')
|
||||
for item in items:
|
||||
try:
|
||||
f = mediafile.MediaFile(util.syspath(item.path))
|
||||
except mediafile.UnreadableFileError as exc:
|
||||
log.warn('Could not embed art in {0}: {1}'.format(
|
||||
repr(item.path), exc
|
||||
))
|
||||
continue
|
||||
f.art = data
|
||||
f.save()
|
||||
|
||||
|
||||
def encode(source, dest):
|
||||
log.info('Started encoding ' + source)
|
||||
temp_dest = dest + '~'
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ Changelog
|
|||
* Fix a VFS bug leading to a crash in the :doc:`/plugins/bpd` when files had
|
||||
non-ASCII extensions.
|
||||
* Add a human-readable error message when writing files' tags fails.
|
||||
* Changed plugin loading so that modules can be imported without
|
||||
unintentionally loading the plugins they contain.
|
||||
|
||||
.. _Tomahawk resolver: http://beets.radbox.org/blog/tomahawk-resolver.html
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue