from openflexure_microscope.api.v1.views import MicroscopeViewPlugin from flask import Blueprint, jsonify from openflexure_microscope.api.v1.views import MicroscopeView import logging import warnings class PluginFormAPI(MicroscopeView): def get(self): """ Return the current plugin forms .. :quickref: Plugin; Get forms Returns an array of present plugin forms (describing plugin user interfaces.) Please note, this is *not* a list of all enabled plugins, only those with associated user interface forms. A complete list of enabled plugins can be found in the microscope state. """ out = self.microscope.plugin.forms return jsonify(out) def construct_blueprint(microscope_obj): blueprint = Blueprint("plugin_blueprint", __name__) # Create a base route to return plugin API forms, if any exist blueprint.add_url_rule( "/", view_func=PluginFormAPI.as_view("plugin_api_form", microscope=microscope_obj), ) all_routes = [] # For each plugin attached to the microscope object for plugin_name, plugin_obj in microscope_obj.plugin.plugins: # 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 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, 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_route_id, microscope=microscope_obj, plugin=plugin_obj, ), ) else: warnings.warn( "An endpoint /{} has already been loaded. Skipping {}.".format( full_view_route, view_class ) ) # If plugin includes an API form if hasattr(plugin_obj, "api_form") and isinstance( plugin_obj.api_form, dict ): api_form_info = plugin_obj.api_form # TODO: Validate form? We need to make sure no single plugin can break all plugins. api_form_info["id"] = plugin_name if "forms" in api_form_info and isinstance( api_form_info["forms"], list ): for form in api_form_info["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 form in Microscope().plugin.form microscope_obj.plugin.forms.append(api_form_info) print(microscope_obj.plugin.forms) else: warnings.warn( "No valid 'api_views' dictionary found in {}".format(plugin_obj) ) return blueprint