From e55c097a324395ae2e4b46f6c47455d79ab59bd3 Mon Sep 17 00:00:00 2001 From: Joel Collins Date: Fri, 14 Jun 2019 17:18:13 +0100 Subject: [PATCH] Added API route for returning API schemas --- .../api/v1/blueprints/plugins.py | 54 ++++++++++++++++--- openflexure_microscope/api/v1/views.py | 1 + openflexure_microscope/plugins/loader.py | 3 +- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/openflexure_microscope/api/v1/blueprints/plugins.py b/openflexure_microscope/api/v1/blueprints/plugins.py index 9aca0f80..9cc98587 100644 --- a/openflexure_microscope/api/v1/blueprints/plugins.py +++ b/openflexure_microscope/api/v1/blueprints/plugins.py @@ -1,15 +1,33 @@ from openflexure_microscope.api.v1.views import MicroscopeViewPlugin -from flask import Blueprint +from flask import Blueprint, jsonify +from openflexure_microscope.api.v1.views import MicroscopeView import logging import warnings +class PluginSchemaAPI(MicroscopeView): + def get(self): + """ + Return the current plugin schemas + + .. :quickref: Plugin; Get schemas + + """ + out = self.microscope.plugin.schemas + return jsonify(out) + def construct_blueprint(microscope_obj): blueprint = Blueprint('plugin_blueprint', __name__) + # Create a base route to return plugin API schemas, if any exist + blueprint.add_url_rule( + '/', + view_func=PluginSchemaAPI.as_view('plugin_api_schema', microscope=microscope_obj) + ) + all_routes = [] # For each plugin attached to the microscope object @@ -18,27 +36,37 @@ def construct_blueprint(microscope_obj): # If plugin contains valid endpoints if hasattr(plugin_obj, 'api_views') and isinstance(plugin_obj.api_views, dict): + # We'll keep a record of how each route was expanded + expanded_routes = {} + # For each defined endpoint for view_route, view_class in plugin_obj.api_views.items(): # Remove all leading slashes from view route - while view_route[0] == '/': - view_route = view_route[1:] + cleaned_route = view_route + while cleaned_route[0] == '/': + cleaned_route = cleaned_route[1:] # Construct a full view route from the plugin name - full_view_route = "/{}/{}".format(plugin_name, view_route) + full_view_route = "/{}/{}".format(plugin_name, cleaned_route) logging.debug(full_view_route) + # Record how the view_route got expanded + expanded_routes[view_route] = full_view_route + # Check if endpoint name clashes if full_view_route not in all_routes and issubclass(view_class, MicroscopeViewPlugin): # Add route to main route dictionary all_routes.append(full_view_route) + # Create a Python-safe name for the route + plugin_route_id = 'plugin{}'.format(full_view_route).replace('/', '_') + # Add route to the plugins blueprint blueprint.add_url_rule( full_view_route, view_func=view_class.as_view( - 'plugin_{}'.format(full_view_route).replace('/', '_'), + plugin_route_id, microscope=microscope_obj, plugin=plugin_obj ) @@ -52,9 +80,23 @@ def construct_blueprint(microscope_obj): ) ) + # If plugin includes an API schema + if hasattr(plugin_obj, 'api_schema') and isinstance(plugin_obj.api_schema, dict): + schema = plugin_obj.api_schema + # TODO: Validate schema? + schema['id'] = plugin_name + if 'forms' in schema and isinstance(schema['forms'], list): + for form in schema['forms']: + if 'route' in form and form['route'] in expanded_routes.keys(): + form['route'] = expanded_routes[form['route']] + else: + logging.warn("No valid expandable route found for {}".format(form['route'])) + + # Store the complete schema in Microscope().plugin.schema + microscope_obj.plugin.schemas.append(schema) + else: warnings.warn( "No valid 'api_views' dictionary found in {}".format(plugin_obj) ) - return blueprint diff --git a/openflexure_microscope/api/v1/views.py b/openflexure_microscope/api/v1/views.py index 3c32ad44..10c88888 100644 --- a/openflexure_microscope/api/v1/views.py +++ b/openflexure_microscope/api/v1/views.py @@ -22,5 +22,6 @@ class MicroscopeViewPlugin(MicroscopeView): def __init__(self, microscope, plugin=None, **kwargs): self.plugin = plugin + self.route = None MicroscopeView.__init__(self, microscope=microscope, **kwargs) diff --git a/openflexure_microscope/plugins/loader.py b/openflexure_microscope/plugins/loader.py index 35bb00f9..74b40a70 100644 --- a/openflexure_microscope/plugins/loader.py +++ b/openflexure_microscope/plugins/loader.py @@ -126,7 +126,8 @@ class PluginMount(object): """ def __init__(self, parent): self.parent = parent - self.plugins = [] + self.plugins = [] # List of plugin objects + self.schemas = [] # List of plugin schemas logging.info("Creating plugin mount") @property