Install & Compatibility
Where this runs
tested against v5.8.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.128s · 18.2MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.6s · import 0.110s · 19MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
DriverManager
✓ from stevedore.driver import DriverManager
Used for managing a single named plugin.
ExtensionManager
✓ from stevedore.extension import ExtensionManager
Used for managing multiple extensions within a namespace.
NamedExtensionManager
✓ from stevedore.named import NamedExtensionManager
Manages a specific set of named extensions from a namespace.
EnabledExtensionManager
✓ from stevedore.enabled import EnabledExtensionManager
Manages extensions based on an 'enabled' filter.
This quickstart demonstrates how to define a plugin interface and a concrete plugin, then use `stevedore.ExtensionManager` to discover and load it. It simulates `setuptools` entry point registration for a self-contained, runnable example. In a real application, plugins would be installed as separate packages declaring their entry points in `setup.py` or `pyproject.toml`. [1, 3, 5]
import os
from setuptools import setup, find_packages
from stevedore import extension
# 1. Define a plugin interface (e.g., in myapp/plugins/base.py)
# In a real scenario, this would be in a separate package.
# For this quickstart, we'll simulate it.
plugin_base_code = '''
import abc
class FormatterBase(abc.ABC):
@abc.abstractmethod
def format(self, data):
"""Format the data and return a string."""
pass
'''
# 2. Implement a concrete plugin (e.g., in myapp_simple_formatter/formatter.py)
# In a real scenario, this would be in a separate package.
plugin_impl_code = '''
from myapp.plugins.base import FormatterBase
class SimpleFormatter(FormatterBase):
def format(self, data):
return f"Simple format: {data['value']}"
'''
# Create dummy files for demonstration
if not os.path.exists('myapp/plugins'):
os.makedirs('myapp/plugins')
with open('myapp/plugins/base.py', 'w') as f:
f.write(plugin_base_code)
if not os.path.exists('myapp_simple_formatter'):
os.makedirs('myapp_simple_formatter')
with open('myapp_simple_formatter/formatter.py', 'w') as f:
f.write(plugin_impl_code)
with open('myapp/__init__.py', 'w') as f: pass
with open('myapp_simple_formatter/__init__.py', 'w') as f: pass
# 3. Define entry points in setup.py (or pyproject.toml)
# For a runnable quickstart, we'll use a dummy setup for the plugin
# and then manually register it to simulate installation.
# In a real project, myapp_simple_formatter would have its own setup.py
# and be installed via pip install -e .
# Simulate plugin registration by creating a pseudo-entry-point
# This is for quickstart demonstration; usually setuptools handles this via installation.
# This specific 'hack' for dynamic registration during runtime is not standard Stevedore usage,
# but it makes the quickstart runnable without a full package installation process.
# We'll use a hack to make the quickstart self-contained and runnable.
# In a real scenario, 'myapp_simple_formatter' would be an installed package
# with its entry point declared in its setup.py (or pyproject.toml).
# To simulate: we directly add the module to sys.modules and define a mock entry_points function.
import sys
sys.path.insert(0, os.path.abspath('.'))
# Temporarily import the base and plugin to make them available
from myapp.plugins.base import FormatterBase
from myapp_simple_formatter.formatter import SimpleFormatter
# Mock the entry point discovery for demonstration
def mock_entry_points(group=None):
if group == 'myapp.formatters':
class MockEntryPoint:
def __init__(self, name, load_callable):
self.name = name
self._load_callable = load_callable
def load(self):
return self._load_callable
return {
'simple': MockEntryPoint('simple', SimpleFormatter)
}
return {}
# Replace the real entry_points discovery for this script's scope
# This is a highly simplified mock for quickstart purposes and not how stevedore usually discovers plugins
# In practice, entry points are discovered via 'importlib.metadata.entry_points()' after package installation.
import stevedore.extension
stevedore.extension.entry_points = mock_entry_points
# 4. Use stevedore in your application to load plugins
def main():
print("Loading formatters...")
mgr = extension.ExtensionManager(
namespace='myapp.formatters',
invoke_on_load=True
)
if not mgr.extensions:
print("No formatters found. Ensure plugin packages are installed and define 'myapp.formatters' entry points.")
return
print(f"Found {len(mgr.extensions)} formatter(s).")
for ext in mgr.extensions:
print(f" - {ext.name}: {ext.obj.format({'value': 123})}")
if __name__ == '__main__':
main()
# Clean up dummy files/dirs
import shutil
shutil.rmtree('myapp')
shutil.rmtree('myapp_simple_formatter')
Errors
Common errors & fixes
No entry points found for group 'my_plugin_group'
The `entry_points` in the plugin's `setup.py` or `pyproject.toml` do not define any entry points under the specified group name, or the plugin package is not installed in the environment.
fixEnsure the plugin package's `setup.py` (or `pyproject.toml`) correctly defines `entry_points` under the specified group and that the plugin package is installed (e.g., `pip install -e .` for development or `pip install my-plugin-package`).
ModuleNotFoundError: No module named 'my_plugin_package.plugins'
The `entry_points` definition in the plugin's `setup.py` or `pyproject.toml` refers to a module path or class name that does not exist or is misspelled within the plugin package.
fixVerify that the module path and class name specified in the `entry_points` definition (e.g., in `setup.py` or `pyproject.toml`) are correct and that the corresponding Python file and class exist within the plugin package.
TypeError: __init__() missing 1 required positional argument: 'config_object'
When `ExtensionManager` is initialized with `invoke_on_load=True`, it attempts to instantiate plugin classes, but the provided `invoke_args` or `invoke_kwargs` do not match the plugin's `__init__` method signature.
fixPass the required arguments to the plugin's constructor via `invoke_args` or `invoke_kwargs` when initializing `ExtensionManager` (e.g., `manager = ExtensionManager('group', invoke_on_load=True, invoke_kwargs={'config_object': my_config})`). Upgrade
Version history
5.9.1latest on PyPI · released Aug 20, 2026
Audit
Dependencies
setuptoolsrequiredStevedore relies on setuptools entry points for plugin discovery and loading.