kopia lustrzana https://github.com/OpenDroneMap/WebODM
Plugins skeleton, abstract class, public URL mounting
rodzic
69f888ada2
commit
d0b4a058bf
|
@ -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()
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
from .plugin_base import PluginBase
|
||||
from .functions import *
|
|
@ -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"))
|
|
@ -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())
|
|
@ -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()
|
|
@ -0,0 +1 @@
|
|||
from .plugin import *
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
from app.plugins import PluginBase
|
||||
|
||||
class Plugin(PluginBase):
|
||||
|
||||
def register(self):
|
||||
print("I'm registering!!!")
|
|
@ -0,0 +1 @@
|
|||
console.log("HI!!");
|
Ładowanie…
Reference in New Issue