Skip to content

Make prioritization pluggable #541

@pboisver

Description

@pboisver

Example plugin code using importlib.metadata

Using importlib.metadata (introduced in Python 3.8) is the modern, "official" way to handle plugins. Instead of scanning folders, your app asks the Python environment: "Who has registered themselves under my specific group name?"

1. The Plugin Side (plugin_a/pyproject.toml)

The plugin "advertises" itself in its packaging metadata. This is the key step that makes it discoverable.

[project]
name = "my-plugin-a"
version = "0.1.0"
dependencies = ["my-base-app"]

This registers the plugin under a custom group name

[project.entry-points."my_app.plugins"]
hello_plugin = "my_plugin_a.module:HelloPlugin"

2. The Application Side (my_app/main.py)

Your main application uses entry_points() to find and load everything registered under "my_app.plugins".

from importlib.metadata import entry_points
def load_plugins():
# 1. Look up all entry points registered to this group
# Note: in Python 3.10+, you can use entry_points(group='...')
eps = entry_points().select(group='my_app.plugins')

plugins = []
for entry in eps:
    print(f"Discovering: {entry.name} from {entry.value}")
    
    # 2. Load the class/function referenced in the metadata
    plugin_class = entry.load()
    
    # 3. Instantiate and store
    plugins.append(plugin_class())
    
return plugins

if name == "main":
active_plugins = load_plugins()
for p in active_plugins:
p.run() # Assuming your plugin has a .run() method

Why this is better than folder scanning:

  1. Zero Path Logic: You don't need to know where the plugin is installed (site-packages, a virtualenv, or a local editable install). If pip knows about it, your app knows about it [1, 2].
  2. Performance: Python doesn't have to crawl the file system; it just reads the pre-generated metadata files [2].
  3. Naming Freedom: Plugins can be named anything (e.g., super-cool-addon) but still register themselves under your app's specific namespace [2].
  4. No init.py Required: It works perfectly with or without namespace packages [1].

Pro-Tip: Testing locally

If you are developing a plugin locally, you must install it in "editable" mode for the entry points to be generated in your environment:

pip install -e ./path/to/plugin_a

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions