Plugins skeleton, abstract class, public URL mounting

pull/384/head
Piero Toffanin 2018-01-30 11:48:16 -05:00
rodzic 69f888ada2
commit d0b4a058bf
9 zmienionych plików z 128 dodań i 0 usunięć

Wyświetl plik

@ -9,6 +9,7 @@ from guardian.shortcuts import assign_perm
from app.models import Preset
from app.models import Theme
from app.plugins import register_plugins
from nodeodm.models import ProcessingNode
# noinspection PyUnresolvedReferences
from webodm.settings import MEDIA_ROOT
@ -87,6 +88,9 @@ def boot():
# Unlock any Task that might have been locked
Task.objects.filter(processing_lock=True).update(processing_lock=False)
# Register plugins
register_plugins()
if not settings.TESTING:
# Setup and start scheduler
scheduler.setup()

Wyświetl plik

@ -0,0 +1,2 @@
from .plugin_base import PluginBase
from .functions import *

Wyświetl plik

@ -0,0 +1,65 @@
import os
import logging
import importlib
import django
from django.conf.urls import url
logger = logging.getLogger('app.logger')
def register_plugins():
for plugin in get_active_plugins():
plugin.register()
logger.info("Registered {}".format(plugin))
def get_url_patterns():
"""
@return the patterns to expose the /public directory of each plugin (if needed)
"""
url_patterns = []
for plugin in get_active_plugins():
if plugin.has_public_path():
url_patterns.append(url('^plugins/{}/(.*)'.format(plugin.get_name()),
django.views.static.serve,
{'document_root': plugin.get_path("public")}))
return url_patterns
plugins = None
def get_active_plugins():
# Cache plugins search
global plugins
if plugins != None: return plugins
plugins = []
plugins_path = get_plugins_path()
for dir in [d for d in os.listdir(plugins_path) if os.path.isdir(plugins_path)]:
# Each plugin must have a manifest.json and a plugin.py
plugin_path = os.path.join(plugins_path, dir)
manifest_path = os.path.join(plugin_path, "manifest.json")
pluginpy_path = os.path.join(plugin_path, "plugin.py")
disabled_path = os.path.join(plugin_path, "disabled")
if not os.path.isfile(manifest_path) or not os.path.isfile(pluginpy_path):
logger.warning("Found invalid plugin in {}".format(plugin_path))
continue
# Plugins that have a "disabled" file are disabled
if os.path.isfile(disabled_path):
continue
# Instantiate the plugin
try:
module = importlib.import_module("plugins.{}".format(dir))
cls = getattr(module, "Plugin")
plugins.append(cls())
except Exception as e:
logger.warning("Failed to instantiate plugin {}: {}".format(dir, e))
return plugins
def get_plugins_path():
current_path = os.path.dirname(os.path.realpath(__file__))
return os.path.abspath(os.path.join(current_path, "..", "..", "plugins"))

Wyświetl plik

@ -0,0 +1,31 @@
import logging, os, sys
from abc import ABC, abstractmethod
logger = logging.getLogger('app.logger')
class PluginBase(ABC):
def __init__(self):
self.name = self.get_module_name().split(".")[-2]
@abstractmethod
def register(self):
pass
def get_path(self, *paths):
"""
Gets the path of the directory of the plugin, optionally chained with paths
:return: path
"""
return os.path.join(os.path.dirname(sys.modules[self.get_module_name()].__file__), *paths)
def get_name(self):
return self.name
def get_module_name(self):
return self.__class__.__module__
def has_public_path(self):
return os.path.isdir(self.get_path("public"))
def __str__(self):
return "[{}]".format(self.get_module_name())

Wyświetl plik

@ -1,6 +1,7 @@
from django.conf.urls import url, include
from .views import app as app_views, public as public_views
from .plugins import get_url_patterns
from app.boot import boot
from webodm import settings
@ -24,6 +25,10 @@ urlpatterns = [
url(r'^api/', include("app.api.urls")),
]
# TODO: is there a way to place plugins /public directories
# into the static build directories and let nginx serve them?
urlpatterns += get_url_patterns()
# Test cases call boot() independently
if not settings.TESTING:
boot()

Wyświetl plik

@ -0,0 +1 @@
from .plugin import *

Wyświetl plik

@ -0,0 +1,13 @@
{
"name": "Volume Measurements",
"webodmMinVersion": "0.4.2",
"description": "A plugin to compute volume measurements from a DSM",
"version": "0.1.0",
"author": "Piero Toffanin",
"email": "pt@masseranolabs.com",
"repository": "https://github.com/OpenDroneMap/WebODM",
"tags": ["volume", "measurements"],
"homepage": "https://github.com/OpenDroneMap/WebODM",
"experimental": true,
"deprecated": false
}

Wyświetl plik

@ -0,0 +1,6 @@
from app.plugins import PluginBase
class Plugin(PluginBase):
def register(self):
print("I'm registering!!!")

Wyświetl plik

@ -0,0 +1 @@
console.log("HI!!");