pronoun-o-matic/plugin.py
2022-06-04 22:30:29 +02:00

56 lines
1.6 KiB
Python

from abc import abstractclassmethod, abstractmethod
from pronoun_update import PronounUpdate
from typing import Any, Callable, List
from importlib.metadata import entry_points
from functools import cache
class Plugin:
@classmethod
@abstractmethod
def name(cls) -> str:
pass
@abstractmethod
def __init__(self, config: dict[str, str]):
pass
@abstractmethod
async def update_bio(self, update_pronouns: PronounUpdate) -> None:
pass
@cache
def load_plugins() -> dict[str, type[Plugin]]:
plugins: dict[str, type[Plugin]] = {}
# Ignore the following two lines due to incorrect type definition for entry_points
# See: https://github.com/python/typeshed/pull/7331
for plugin in entry_points(group="pronounomatic.plugins"): # type: ignore
pl = plugin.load() # type: ignore
assert issubclass(pl, Plugin)
plugins[pl.name()] = pl
return plugins
class InvalidPluginDefinitionException(Exception):
pass
def load_plugins_for_config(config: list[dict[str, Any]]) -> List[Plugin]:
plugins = []
plugin_classes = load_plugins()
for plugin_def in config:
if not plugin_def["name"]:
raise InvalidPluginDefinitionException("Missing plugin_name field")
plugin_name = plugin_def["name"]
if not plugin_name in load_plugins():
raise InvalidPluginDefinitionException(
f"No plugin with name {plugin_name} loaded"
)
plugin_cls = plugin_classes[plugin_name]
plugin = plugin_cls(plugin_def)
plugins.append(plugin)
return plugins