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