Writing Plugins#
In Moe, almost everything is a plugin. Plugins are designed to interact with other plugins primarily through the various hooks available.
Creating plugins in Moe is extremely simple. For example, below is a plugin that implements the create_path_template_func
hook to add a canon_artist
function for use in path templates.
import moe
@moe.hookimpl
def create_path_template_func():
return [canon_artist]
def canon_artist(artist):
if artist == "The Jimi Hendrix Experience":
return "Jimi Hendrix"
return artist
Plugins can exist either locally in your configuration directory, or you can opt to share your plugin by publishing it to PyPI.
Local Plugins#
You can create a local plugin by adding a module <plugin_name>.py
or package <plugin_name>/my_module.py
in a plugins
directory next to your configuration e.g. <configuration directory>/plugins/<my_plugin>
.
Important
The name of your local plugin cannot conflict with any other modules in the current namespace. For example, you can’t name your plugin random
because it conflicts with the random
module in the standard library. It may be useful to preface any local plugins with moe_
or any other prefix of your choice if you think there may be a potential conflict.
Once you create a plugin, all you have to do is enable it in your configuration to start using it!
Published Plugins#
If you’d like to make your plugin available on pip, there are a few required steps:
Preface your project name with
moe_
e.g.moe_my_plugin
when publishing to PyPI.Note
It’s encouraged that the actual name of your plugin module or package not include the
moe_
prefix. The prefix is only necessary for the name of your project on PyPI.Include the entry_point group
moe
in yoursetup.py
orpyproject.toml
.For example, if using poetry, include the following in your
pyproject.toml
.[tool.poetry.plugins."moe"] "<plugin_name>" = "<plugin_module or package>"
See also
Once you’ve accomplished the above, your plugin will be automatically loaded by Moe provided the user has installed your package and enabled the plugin in their configuration.
Tip
Check out the plugin_template repository to quickly create a plugin to publish to PyPI complete with CI scripts and configuration files consistent with the rest of Moe.
Core vs CLI#
Because Moe includes both a library as well as a command-line interface to that library, many of the existing plugins are split into two parts: a core module and a cli module. If your plugin is attempting to affect both parts of Moe, it should also be split accordingly, but can be contained under a single package. In this case, the name of the package should simply be the name of your plugin. When enabling or disabling plugins, users only need to specify the name of the package, and not the individual sub-modules.
Registering Plugin Sub-Modules#
If your plugin is a package consisting of one or more sub-modules, they must each be explicitly registered for them to be included in the plugin system. This is a common occurrence if your plugin has both a cli
and core
sub-module, for instance.
When your plugin is loaded by Moe, it is actually just loading its __init__.py
. Therefore, the rest of your sub-modules must be explicitly registered for Moe to see them. For example, the add
plugin has the following in its __init__.py
:
@moe.hookimpl
def plugin_registration():
"""Only register the cli sub-plugin if the cli is enabled."""
config.CONFIG.pm.register(add_core, "add_core")
if "cli" in config.CONFIG.enabled_plugins:
config.CONFIG.pm.register(add_cli, "add_cli``)
See also
The plugin_registration()
hook.