A small, dependency-free plugin framework: hook specs, entry-point discovery, and sync/async dispatch
Project description
pluginkit
A small, dependency-free plugin framework for Python: declare hook specifications, let plugins implement them, and discover plugins via entry points. Supports sync and async dispatch, hook ordering, wrappers, pipeline (fold) dispatch, and historic hooks - in a few readable files.
The library is three files under src/pluginkit/ (markers.py, manager.py,
exceptions.py), has zero runtime dependencies (standard library only), and
ships a py.typed marker.
from pluginkit import HookspecMarker, HookimplMarker, PluginManager
hookspec = HookspecMarker("greeter")
hookimpl = HookimplMarker("greeter")
class Specs:
@staticmethod
@hookspec
def greeting(name: str) -> str:
"""Return a greeting for the given name."""
class Casual:
@hookimpl
def greeting(self, name: str) -> str:
return f"hey {name}!"
pm = PluginManager("greeter")
pm.add_hookspecs(Specs)
pm.register(Casual(), name="casual")
print(pm.hook.greeting(name="Ada")) # ['hey Ada!']
What it supports
- collecting,
firstresult, and pipeline (fold/middleware) hooks; - call ordering with
tryfirst/trylast, plusoptionalhookandspecname; - generator wrappers that decorate results and observe exceptions safely;
- historic hooks replayed to plugins registered later;
- async dispatch via
AsyncPluginManager(awaits coroutine impls); - plugin lifecycle:
register,unregister(by name or object),set_blocked, lookup,call_extra; - registration-time validation and call-time argument checking (failures are loud);
- external plugin discovery via the stdlib
importlib.metadata(no setuptools); - thread-safe registry mutation.
Layout
src/pluginkit/ the library (pure - no demo code)
tour/ pluginkit-tour: a guided CLI walkthrough, one step per mechanism
examples/ standalone single-file recipes, run directly
plugins/smoothie-extra/ an external plugin distribution (its own uv project)
docs/ mkdocs + Material documentation
tests/ library, tour, and example tests
The tour and examples are two complementary ways to learn it: the tour is
a guided walkthrough on one host (pluginkit-tour run all), while the examples
are independent, real-world recipes you run on their own.
Use it
make install # uv sync (library + tour + external plugin)
make test # pytest (framework, tour, examples)
make lint # ruff + mypy + pyright
make docs-serve # serve the docs at http://127.0.0.1:8000
make docs-build # build the docs (strict)
Two ways to learn it
The tour (tour/) walks through one mechanism at a time on a single host:
make run # run every step
make run DEMO=wrapper # run one
uv run pluginkit-tour list
The examples apply the library to different realistic domains - see
examples/:
uv run python examples/report_builder.py
uv run python examples/notification_router.py
uv run python examples/validation_rules.py
uv run python examples/app_lifecycle.py
Documentation
Full docs (concepts, one page per mechanism, production/hardening notes, and a
generated API reference) live under docs/. Serve them with
make docs-serve.
Is it production ready?
It is solid - exception-safe wrappers, fail-fast validation, lifecycle management, resilient discovery, thread-safe mutation, strict typing, and a test suite. But for anything you ship, prefer pluggy itself: it is maintained and battle tested by pytest, tox, and datasette. See docs/production/vs-pluggy.md for the honest inventory of what differs.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pluginkit-0.1.0.tar.gz.
File metadata
- Download URL: pluginkit-0.1.0.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
76db3dd0b345dd4114ba7ac5440a8c1f668f4d78156e22b60973cceddf87812d
|
|
| MD5 |
9cbbc82cec24f0676f68c4e9ca5d2cd3
|
|
| BLAKE2b-256 |
d8d634b5bf554a9276cf398ebd2fb134b1e66fa4a8294a8d8a3d0b8944610188
|
Provenance
The following attestation bundles were made for pluginkit-0.1.0.tar.gz:
Publisher:
release.yml on winterop-com/pluginkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pluginkit-0.1.0.tar.gz -
Subject digest:
76db3dd0b345dd4114ba7ac5440a8c1f668f4d78156e22b60973cceddf87812d - Sigstore transparency entry: 1941968277
- Sigstore integration time:
-
Permalink:
winterop-com/pluginkit@a1612a20f4591d7782c9dd65fb5ac98e1dc5e243 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/winterop-com
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a1612a20f4591d7782c9dd65fb5ac98e1dc5e243 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pluginkit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pluginkit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88a2a70957082c3584d3b0dd3eb5b24d8cf5e4436da55a96f85f12ec987ea534
|
|
| MD5 |
32c93bdd927f2bff38718be06cbd55d5
|
|
| BLAKE2b-256 |
cc1e47acc5f8fd2b6dede2e3999052c3756ae8c8a6a19e393fc361047123e1fd
|
Provenance
The following attestation bundles were made for pluginkit-0.1.0-py3-none-any.whl:
Publisher:
release.yml on winterop-com/pluginkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pluginkit-0.1.0-py3-none-any.whl -
Subject digest:
88a2a70957082c3584d3b0dd3eb5b24d8cf5e4436da55a96f85f12ec987ea534 - Sigstore transparency entry: 1941968355
- Sigstore integration time:
-
Permalink:
winterop-com/pluginkit@a1612a20f4591d7782c9dd65fb5ac98e1dc5e243 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/winterop-com
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a1612a20f4591d7782c9dd65fb5ac98e1dc5e243 -
Trigger Event:
push
-
Statement type: