How to add a new plugin entry point to edX platform
Background
Open edX is a very powerful platform and can be extended in many ways. This document describes the best practices that should be used to add new plugin entry points which allow any installed Python library to provide new capabilities.
Technical Details
Open edX uses Stevedore from Open Stack to provide support for plugins. There are a few steps necessary to declare your new entry point:
The first step is to implement a subclass of
PluginManagerwhich code will use to find instances of your pluginsYour new plugin manager class should specify the property
NAMESPACEfor your chosen entry point namespacee.g.
MY_PLUGIN_NAMESPACE = 'my_organization.my_plugin' class MyPluginManager(PluginManager): """ Manager for my plugins. """ NAMESPACE = MY_PLUGIN_NAMESPACE
In a Python library, a new plugin can be registered in setup.py
e.g.
from setuptools import setup setup( name="My Library", version="1.0", install_requires=["setuptools"], requires=[], entry_points={ "my_organization.my_plugin": [ "first_plugin = my_organization.plugins:FirstPlugin", }, )
The platform now can access the plugins in one of two ways:
MyPluginManager.get_available_plugins()
Returns the list of plugins registered by all the installed libraries.
MyPluginManager.get_plugin(plugin_name)
Returns the named plugin declared for the entry point (or raises an exception if one isn't found).
e.g.
my_plugin = MyPluginManager.get_plugin('first_plugin')
Typically the platform code will work with the full list of available plugins
This is because, by definition, installed plugins are not known by name to the platform
Instead, the platform should iterate the list of plugins and decide how to handle them
Foe example, an authoring UI could present the list of options to the author who could then pick one
The name of the chosen plugin would then be persisted
Then a learner-facing UI would request that plugin by name and then use it appropriately, e.g. render it as a view
Example 1: Block Transformers
The Course Blocks API provides a plugin mechanism to allow new transformers to be added.
The base
BlockStructureTransformerclass lives here:The class
TransformerRegistryis a subclass ofPluginManagerA good example transformer is
GradesTransformerThe transformer plugins are registered in setup.py
Example 2: Course Tabs
The tabs shown for a course are defined as plugins, so that features can introduce new ones.
A subclass of
PluginManageris defined here:Course tab plugins have to be defined as subclasses of the base
CourseTabclassThe plugins are registered in setup.py
For more details, see Adding a new course tab.