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
PluginManager
which code will use to find instances of your plugins - Your new plugin manager class should specify the property
NAMESPACE
for 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')
- MyPluginManager.get_available_plugins()
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
BlockStructureTransformer
class lives here: - The class
TransformerRegistry
is a subclass ofPluginManager
- A good example transformer is
GradesTransformer
- The 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
PluginManager
is defined here: - Course tab plugins have to be defined as subclasses of the base
CourseTab
class - The plugins are registered in setup.py
For more details, see Adding a new course tab.