Files
edx-platform/common/lib/xmodule/xmodule/plugin.py

65 lines
2.1 KiB
Python

import pkg_resources
import logging
log = logging.getLogger(__name__)
class PluginNotFoundError(Exception):
pass
class Plugin(object):
"""
Base class for a system that uses entry_points to load plugins.
Implementing classes are expected to have the following attributes:
entry_point: The name of the entry point to load plugins from
"""
_plugin_cache = None
@classmethod
def load_class(cls, identifier, default=None):
"""
Loads a single class instance specified by identifier. If identifier
specifies more than a single class, then logs a warning and returns the
first class identified.
If default is not None, will return default if no entry_point matching
identifier is found. Otherwise, will raise a ModuleMissingError
"""
if cls._plugin_cache is None:
cls._plugin_cache = {}
if identifier not in cls._plugin_cache:
identifier = identifier.lower()
classes = list(pkg_resources.iter_entry_points(
cls.entry_point, name=identifier))
if len(classes) > 1:
log.warning("Found multiple classes for {entry_point} with "
"identifier {id}: {classes}. "
"Returning the first one.".format(
entry_point=cls.entry_point,
id=identifier,
classes=", ".join(
class_.module_name for class_ in classes)))
if len(classes) == 0:
if default is not None:
return default
raise PluginNotFoundError(identifier)
cls._plugin_cache[identifier] = classes[0].load()
return cls._plugin_cache[identifier]
@classmethod
def load_classes(cls):
"""
Returns a list of containing the identifiers and their corresponding classes for all
of the available instances of this plugin
"""
return [(class_.name, class_.load())
for class_
in pkg_resources.iter_entry_points(cls.entry_point)]