Extension plugins

Extensions are core application components, and can be enabled and configured per project. An extension can do many things, such as loading new or expanding existing ancestry data, or generating additional content for your site.

Creating an extension

  1. Create a new class that extends betty.project.extension.Extension and implements the abstract methods, for example:

    from typing import override
    from betty.project.extension import Extension
    
    class MyExtension(Extension):
      @override
      @classmethod
      def plugin_id(cls) -> MachineName:
          return "my-module-my-extension"
    
      # Implement remaining abstract methods...
      ...
    
  2. Tell Betty about your extension by registering it as an entry point. Given the extension above in a module my_package.my_module, add the following to your Python package:

[project.entry-points.'betty.extension']
'my-module-my-extension' = 'my_package.my_module.MyExtension'
SETUP = {
    'entry_points': {
        'betty.extension': [
            'my-module-my-extension=my_package.my_module.MyExtension',
        ],
    },
}
if __name__ == '__main__':
    setup(**SETUP)

Asset management

Extensions can enable asset management to provide translations, templates, and more, by overriding betty.project.extension.Extension.assets_directory_path() to return the path on disk where the extension’s assets are located. This may be anywhere in your Python package.

from typing import override
from betty.project.extension import Extension

class MyExtension(Extension):
    @override
    @classmethod
    def assets_directory_path(cls) -> Path | None:
        # A directory named "assets" in the same parent directory as the current Python file.
        return Path(__file__).parent / 'assets'

   # Implement remaining abstract methods...
   ...

Event handling

Extensions can act on events by overriding betty.project.extension.Extension.register_event_handlers(). Any number of events may be handled, and any number of handlers may be registered per event. Handlers are invoked in their order of registration.

from typing import override
from betty.project.load import LoadAncestryEvent
from betty.project.extension import Extension

def _load_ancestry(event: LoadAncestryEvent) -> None:
    # Do what this function should do...
    ...

class MyExtension(Extension):
    @override
    @classmethod
    def register_event_handlers(self, registry: EventHandlerRegistry) -> None:
        registry.add_handler(LoadAncestryEvent, _load_ancestry)

   # Implement remaining abstract methods...
   ...

See also

Read more about event dispatching and Betty’s built-in events at Event dispatching.

Dependencies

Important

Any dependencies on other Python packages must be declared by your extension’s Python package.

Extensions have fine-grained control over which other extensions they require, and the order in which they appear in the extension dependency tree:

betty.project.extension.Extension.depends_on()

Declare required other extensions. This ensures those extensions are enabled and appear before your extension in the extension dependency tree.

betty.project.extension.Extension.comes_after()

Declare other extensions that are not required, but if they are enabled, then your extension will appear after them in the extension dependency tree.

betty.project.extension.Extension.comes_before()

Declare other extensions that are not required, but if they are enabled, then your extension will appear before them in the extension dependency tree.

Optional functionality

Extensions can optionally provide the following functionality:

betty.project.extension.ConfigurableExtension

Enable configuration management for the extension.

betty.project.extension.Theme

Mark the extension as being a theme, e.g. an extension that determines the overall look and feel of a site.

betty.html.CssProvider

Add additional CSS files to generated pages.

betty.html.JsProvider

Add additional JavaScript files to generated pages.

betty.jinja2.Jinja2Provider

Integrate the extension with Jinja2.

See also

Read more about how to use extensions and Betty’s built-in extensions at Extensions.