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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions