Plugin
Plugins bieten einen Erweiterungsmechanismus für quickli-Anwendungen, ohne den Anwendungscode im Kern zu verändern. Jedes Plugin kapselt eine Reihe von Command-Handlern und -Ressourcen und registriert diese über einen strikten Vertrag bei einer Application-Instanz.
Plugins befinden sich in der Architektur auf derselben Ebene wie reguläre Anwendungsbefehle:
Application
├── Command (direkt von der Anwendung registriert)
└── Plugin ← du bist hier
└── Command (von plugin.register() registriert)
Der Plugin-Schnittstellenvertrag
Jedes Plugin muss quickli.Plugin unterklassen und drei erforderliche abstrakte Elemente implementieren:
| Element | Art | Beschreibung |
|---|---|---|
name | @property -> str | Eindeutiger, nicht leerer String-Bezeichner für das Plugin (z. B. "security-audit"). |
description | @property -> str | Kurze Beschreibung der vom Plugin bereitgestellten Funktionen. |
register(application) | method(Application) -> None | Hook-Methode, in der das Plugin Befehle, Unterbefehle oder Ressourcen an der Application registriert. |
Vollständiges Plugin-Beispiel
import quickli
class DatabasePlugin(quickli.Plugin):
@property
def name(self) -> str:
return "database"
@property
def description(self) -> str:
return "Bietet Datenbankmigrations- und Seeding-Befehle."
def register(self, application: quickli.Application) -> None:
@application.command(
name="db-migrate",
help_text="Datenbankschemamigrationen ausführen.",
)
def migrate() -> str:
return "migrations applied"
@application.command(
name="db-seed",
help_text="Datenbank mit Beispieldaten befüllen.",
)
def seed() -> str:
return "database seeded"
Laden von Plugins (Application.load_plugin)
Um ein Plugin zu registrieren, übergib eine Instanz deiner Plugin-Klasse an Application.load_plugin():
app = quickli.Application(name="mycli")
# Datenbank-Plugin laden:
app.load_plugin(DatabasePlugin())
# Vom Plugin bereitgestellte Befehle ausführen:
print(app.run(["db-migrate"])) # migrations applied
print(app.run(["db-seed"])) # database seeded
Geladene Plugins anzeigen (app.plugins)
Du kannst alle geladenen Plugins über app.plugins abfragen:
for plugin in app.plugins:
print(f"Plugin: {plugin.name} — {plugin.description}")
Fehlerbehandlung (PluginLoadError)
quickli erzwingt die Gültigkeit von Plugins und eindeutige Namen bei der Registrierung. Das Laden löst einen PluginLoadError aus, wenn:
- Leerer Name: Die
name-Property gibt einen leeren String zurück. - Doppelter Name: Ein Plugin mit demselben
nameist bereits an derApplicationregistriert. - Registrierungsausnahme: Die
register(application)-Methode des Plugins löst eine unbehandelte Ausnahme aus.
from quickli import Application, PluginLoadError
app = Application(name="demo")
db_plugin = DatabasePlugin()
app.load_plugin(db_plugin)
try:
# Das zweimalige Laden desselben Plugins löst PluginLoadError aus:
app.load_plugin(db_plugin)
except PluginLoadError as err:
print(f"Failed to load plugin: {err}")
Jedes Plugin muss einen eindeutigen name-String zurückgeben, um Kollisionen zwischen Plugin-Paketen zu vermeiden.
Reglementierung & Einschränkungen
Ein Plugin kann keinen Befehl ersetzen, der bereits an der Application registriert wurde (weder von der Anwendung selbst noch von einem zuvor geladenen Plugin). Der Versuch, einen doppelten Befehlsnamen zu registrieren, löst einen CommandRegistrationError aus.
Verwende Plugins, um große CLI-Anwendungen in unabhängige, wiederverwendbare Module aufzuteilen. So kann beispielsweise ein gemeinsames auth- oder telemetry-Plugin teamübergreifend verwendet werden.
Aktueller Status & Roadmap
- Aktuell (Alpha): Explizite Plugin-Instanziierung und Laden über
app.load_plugin(PluginInstance()). - Geplant (Zukunft): Automatische Plugin-Erkennung über Python-Paketeigenschaften (
importlib.metadata).
Wie geht es weiter?
- Erfahre mehr über Befehle in Command.
- Erfahre, wie die Befehlsausführung funktioniert in Application.
- Lade dauerhafte Konfigurationen in Plugins mit Config.
