mirror of
https://github.com/ChristianLight/tutor.git
synced 2024-06-01 22:00:48 +00:00
3ab0dcb9e6
Templated hooks we almost completely useless, so we get rid of them. This allows us to get rid entirely of hook names and hook indexes, which makes the whole implementation much simpler. Hook removal (with `clear_all`) is achieved thanks to weak references.
78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
import importlib.util
|
|
import os
|
|
from glob import glob
|
|
|
|
import pkg_resources
|
|
|
|
from tutor import hooks
|
|
|
|
from .base import PLUGINS_ROOT
|
|
|
|
|
|
@hooks.Actions.CORE_READY.add()
|
|
def _discover_module_plugins() -> None:
|
|
"""
|
|
Discover .py files in the plugins root folder.
|
|
"""
|
|
with hooks.Contexts.PLUGINS.enter():
|
|
for path in glob(os.path.join(PLUGINS_ROOT, "*.py")):
|
|
discover_module(path)
|
|
|
|
|
|
@hooks.Actions.CORE_READY.add()
|
|
def _discover_entrypoint_plugins() -> None:
|
|
"""
|
|
Discover all plugins that declare a "tutor.plugin.v1" entrypoint.
|
|
"""
|
|
with hooks.Contexts.PLUGINS.enter():
|
|
if "TUTOR_IGNORE_ENTRYPOINT_PLUGINS" not in os.environ:
|
|
for entrypoint in pkg_resources.iter_entry_points("tutor.plugin.v1"):
|
|
discover_package(entrypoint)
|
|
|
|
|
|
def discover_module(path: str) -> None:
|
|
"""
|
|
Install a plugin written as a single file module.
|
|
"""
|
|
name = os.path.splitext(os.path.basename(path))[0]
|
|
|
|
# Add plugin to the list of installed plugins
|
|
hooks.Filters.PLUGINS_INSTALLED.add_item(name)
|
|
|
|
# Add plugin information
|
|
hooks.Filters.PLUGINS_INFO.add_item((name, path))
|
|
|
|
# Import module on enable
|
|
@hooks.Actions.PLUGIN_LOADED.add()
|
|
def load(plugin_name: str) -> None:
|
|
if name == plugin_name:
|
|
# https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
|
|
spec = importlib.util.spec_from_file_location(
|
|
"tutor.plugin.v1.{name}", path
|
|
)
|
|
if spec is None or spec.loader is None:
|
|
raise ValueError("Plugin could not be found: {path}")
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
|
|
|
|
def discover_package(entrypoint: pkg_resources.EntryPoint) -> None:
|
|
"""
|
|
Install a plugin from a python package.
|
|
"""
|
|
name = entrypoint.name
|
|
|
|
# Add plugin to the list of installed plugins
|
|
hooks.Filters.PLUGINS_INSTALLED.add_item(name)
|
|
|
|
# Add plugin information
|
|
if entrypoint.dist is None:
|
|
raise ValueError(f"Could not read plugin version: {name}")
|
|
hooks.Filters.PLUGINS_INFO.add_item((name, entrypoint.dist.version))
|
|
|
|
# Import module on enable
|
|
@hooks.Actions.PLUGIN_LOADED.add()
|
|
def load(plugin_name: str) -> None:
|
|
if name == plugin_name:
|
|
entrypoint.load()
|