Creating a plugin¶
You can, and probably need to, extend byro with custom Python code using the official plugin API. You'll have to think of every plugin as an independent Django 'app' living in its own python package installed like any other python module.
The communication between byro and the plugins happens primarily using Django's signal dispatcher feature. The core modules of byro expose signals for different purposes. You can find their documentation in the signal list. We also provide guides for common plugin use cases, such as tracking custom member data, or importing and matching payments.
To create a new plugin, create a new python package which must be a valid Django app and must contain plugin metadata, as described below. You will need some boilerplate code for every plugin to get started. To save your time, we created a cookiecutter template that you can use like this:
(env)$ pip install cookiecutter
(env)$ cookiecutter https://github.com/byro/byro-plugin-cookiecutter
This will ask you some questions and then create a project folder for your plugin.
The following pages go into detail about the different types of plugins byro supports. While these instructions don't assume that you know a lot about byro, they do assume that you have prior knowledge about Django (e.g. its view layer, how its ORM works, etc.).
Plugin metadata¶
The plugin metadata lives inside a ByroPluginMeta class inside your app's
configuration class. byro itself reads three attributes from it and shows
them unchanged on the "About byro" page (see
Settings):
| Attribute | Type | Description |
|---|---|---|
| name | string | The human-readable name of your plugin |
| version | string | A human-readable version code of your plugin |
| description | string | A more verbose description of what your plugin does |
byro additionally reads document_categories (a dict mapping a category id
to a human-readable name) if your plugin wants to contribute its own
document categories (see Documents).
author and visible are convention only, from the cookiecutter
template below - byro itself never reads or evaluates them. Fill them in if
it helps document your plugin, but do not expect any effect inside byro.
A working example, living in byro_irc/apps.py, would be:
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class IRCApp(AppConfig):
name = 'byro_irc'
verbose_name = _("IRC")
class ByroPluginMeta:
name = _("IRC")
version = '1.0.0'
description = _("This plugin sends notifications via IRC.")
# Convention, not evaluated by byro:
author = _("irclover")
visible = True
Django picks up the single AppConfig subclass in your apps submodule
automatically. If that module defines more than one AppConfig subclass, mark
the one byro should use with default = True. The old default_app_config
variable has no effect since Django 4.1 and should not be used.
Warning
byro registers your plugin in INSTALLED_APPS by its bare module name. If
your AppConfig does not live in apps.py, Django falls back to a plain
AppConfig without ByroPluginMeta. byro starts without an error, but
silently ignores the plugin: its URLs are not included, it is not listed on
the plugins page, its document categories are missing, and its ready()
method never runs, so none of its signal receivers are connected.
Plugin registration¶
Somehow, byro needs to know that your plugin exists at all. For this purpose,
we make use of the
entry point
mechanism. To register a plugin that lives in a separate python package, your
pyproject.toml should contain something like this:
byro only evaluates the module part before the colon and adds that module to
INSTALLED_APPS; the part after the colon is a convention. If your project
still uses a setup.py, the same entry goes into its entry_points argument
under the [byro.plugin] group.
This will automatically make byro discover this plugin as soon as you have
installed it, e.g. through pip. During development, install your plugin in
editable mode with pip install -e . inside your plugin source directory to
make it discoverable.
Getting listed in the plugin catalog¶
Administrators install plugins with byroctl plugin add <shortname> from a
small catalog that ships with every byro release (see
Plugins). To get your plugin listed:
- publish regular GitHub releases (or releases on PyPI): byroctl installs the current release and pins the commit its tag points to, so a plain tag is not enough and a moved tag is treated as an integrity error;
- declare the byro versions you support as a dependency, for example
dependencies = ["byro>=2026.3"], so that an incompatible combination fails at build time instead of at runtime; - keep the
AppConfiginapps.py(see the warning above) and ship your translations as.pofiles; the image build compiles them; - open a pull request against
deploy/plugin-catalog.confin the byro repository with your plugin's short name, display name, description, package name, source and repository (maintainers: Releasing byro).
Signals¶
byro defines different signals which your plugin can listen for. We will go
into the details of the different signals in the signal list.
We suggest that you put your signal receivers into a signals submodule of
your plugin. You should extend your AppConfig in apps.py (see above) by the
following method to make your receivers available:
Views¶
Your plugin may define custom views. If you put an urls submodule into your
plugin module, byro will automatically import it and include it into the root
URL configuration with the namespace plugins:<label>:, where <label> is
your Django app label.
Warning
If you define custom URLs and views, you are on your own with checking that the user has appropriate permissions. byro ensures that you are dealing with an authenticated user, but nothing else.