Loading openflexure_microscope/api/app.py +31 −29 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import logging import sys import os from flask import Flask, jsonify, send_file from flask import Flask, jsonify, send_file, url_for from serial import SerialException from datetime import datetime Loading Loading @@ -79,7 +79,7 @@ CORS(app, resources=r"*") handler = JSONExceptionHandler(app) # Attach lab devices labthing = LabThing(app, prefix="/api/v2b") labthing = LabThing(app, prefix="/api/v2") labthing.description = "Test LabThing-based API for OpenFlexure Microscope" labthing.register_device(api_microscope, "openflexure_microscope") Loading @@ -88,41 +88,23 @@ for _plugin in find_plugins(USER_PLUGINS_PATH): labthing.register_plugin(_plugin) from openflexure_microscope.api.v2.views.captures import add_captures_to_labthing add_captures_to_labthing(labthing, prefix="") # WEBAPP ROUTES ### V2 # Root routes v2_root_blueprint = v2.blueprints.root.construct_blueprint(api_microscope) app.register_blueprint(v2_root_blueprint, url_prefix=uri("/", "v2")) add_captures_to_labthing(labthing, prefix="") from openflexure_microscope.api.v2.views.state import add_states_to_labthing v2_streams_blueprint = v2.blueprints.streams.construct_blueprint(api_microscope) app.register_blueprint(v2_streams_blueprint, url_prefix=uri("/streams", "v2")) add_states_to_labthing(labthing, prefix="") # Captures routes v2_captures_blueprint = v2.blueprints.captures.construct_blueprint(api_microscope) app.register_blueprint(v2_captures_blueprint, url_prefix=uri("/captures", "v2")) from openflexure_microscope.api.v2.views.tasks import add_tasks_to_labthing # Settings routes v2_settings_blueprint = v2.blueprints.settings.construct_blueprint(api_microscope) app.register_blueprint(v2_settings_blueprint, url_prefix=uri("/settings", "v2")) add_tasks_to_labthing(labthing, prefix="") # Status routes v2_status_blueprint = v2.blueprints.status.construct_blueprint(api_microscope) app.register_blueprint(v2_status_blueprint, url_prefix=uri("/status", "v2")) from openflexure_microscope.api.v2.views.streams import add_streams_to_labthing # Plugins routes # v2_plugin_blueprint = v2.blueprints.plugins.construct_blueprint(api_microscope) # app.register_blueprint(v2_plugin_blueprint, url_prefix=uri("/plugins", "v2")) add_streams_to_labthing(labthing, prefix="") # Tasks routes v2_tasks_blueprint = v2.blueprints.tasks.construct_blueprint(api_microscope) app.register_blueprint(v2_tasks_blueprint, url_prefix=uri("/tasks", "v2")) from openflexure_microscope.api.v2.views.actions import add_actions_to_labthing # Actions routes v2_actions_blueprint = v2.blueprints.actions.construct_blueprint(api_microscope) app.register_blueprint(v2_actions_blueprint, url_prefix=uri("/actions", "v2")) add_actions_to_labthing(labthing) @app.route("/routes") Loading @@ -139,6 +121,26 @@ def routes(): return jsonify(list_routes(app)) @app.route("/props") def props(): p = {} for key, prop in labthing.properties.items(): p[key] = {} p[key]["view"] = prop p[key]["url"] = labthing.url_for(prop, _external=True) return jsonify(p) @app.route("/ac") def actions(): p = {} for key, prop in labthing.actions.items(): p[key] = {} p[key]["view"] = prop p[key]["url"] = labthing.url_for(prop, _external=True) return jsonify(p) @app.route("/log") def err_log(): """ Loading openflexure_microscope/api/v2/blueprints/__init__.py +1 −1 Original line number Diff line number Diff line from . import root, captures, settings, status, tasks, streams, plugins, actions from . import root, captures, settings, status, tasks, streams, actions openflexure_microscope/api/v2/blueprints/plugins.pydeleted 100644 → 0 +0 −114 Original line number Diff line number Diff line """ Top-level representation of attached and enabled plugins """ from openflexure_microscope.api.views import MicroscopeViewPlugin from openflexure_microscope.utilities import get_docstring, description_from_view from openflexure_microscope.api.utilities import blueprint_for_module from openflexure_microscope.common.labthings.plugins import find_plugins from openflexure_microscope.config import USER_PLUGINS_PATH from flask import Blueprint, jsonify, url_for from openflexure_microscope.api.views import MicroscopeView import copy import logging import warnings _plugins = find_plugins(USER_PLUGINS_PATH) print(_plugins) def plugins_representation(plugin_list): """ Generate a dictionary representation of all plugins, including Flask route URLs Args: plugin_loader_object (:py:class:`openflexure_microscope.plugins.PluginLoader`): Microscope plugin loader Returns: dict: Dictionary representation of all plugins """ plugins = {} for plugin in plugin_list: logging.debug(f"Representing plugin {plugin._name}") d = { "python_name": plugin._name_python_safe, "plugin": str(plugin), "views": {}, "gui": plugin.gui, "description": get_docstring(plugin), } for view_id, view_data in plugin.views.items(): logging.debug(f"Representing view {view_id}") uri = url_for(f"v2_plugins_blueprint.plugins") + view_data["rule"][1:] # uri = view_data["rule"] # Make links dictionary if it doesn't yet exist view_d = {"links": {"self": uri}} view_d.update(description_from_view(view_data["view"])) d["views"][view_id] = view_d plugins[plugin._name] = d return plugins 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. """ global _plugins return jsonify(plugins_representation(_plugins)) def construct_blueprint(microscope_obj): blueprint = blueprint_for_module(__name__) for plugin_obj in _plugins: for plugin_view_id, plugin_view in plugin_obj.views.items(): # Add route to the plugins blueprint blueprint.add_url_rule( plugin_view["rule"], view_func=plugin_view["view"].as_view( f"{plugin_obj._name_python_safe}_{plugin_view_id}" ), **plugin_view["kwargs"], ) # Create a base route to return plugin API forms, if any exist blueprint.add_url_rule( "/", view_func=PluginFormAPI.as_view("plugins", microscope=microscope_obj) ) # For each plugin attached to the microscope object for plugin in microscope_obj.plugins.active: for plugin_view_id, plugin_view in plugin.views.items(): # Add route to the plugins blueprint blueprint.add_url_rule( plugin_view["rule"], view_func=plugin_view["view"].as_view( f"{plugin._name_python_safe}_{plugin_view_id}", microscope=microscope_obj, plugin=plugin, ), **plugin_view["kwargs"], ) return blueprint openflexure_microscope/api/v2/blueprints/root.py +0 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ from openflexure_microscope.api.utilities import blueprint_name_for_module from openflexure_microscope.api.v2.blueprints import ( settings, status, plugins, captures, actions, streams, Loading openflexure_microscope/api/v2/views/actions/__init__.py 0 → 100644 +65 −0 Original line number Diff line number Diff line """ Top-level representation of enabled actions """ from flask import Blueprint, url_for, jsonify from openflexure_microscope.api.utilities import blueprint_for_module from openflexure_microscope.utilities import get_docstring, description_from_view from openflexure_microscope.api.views import MicroscopeView from . import camera, stage, system _actions = { "capture": { "rule": "/camera/capture/", "view_class": camera.CaptureAPI, "conditions": True, }, "previewStart": { "rule": "/camera/preview/start", "view_class": camera.GPUPreviewStartAPI, "conditions": True, }, "previewStop": { "rule": "/camera/preview/stop", "view_class": camera.GPUPreviewStopAPI, "conditions": True, }, "move": { "rule": "/stage/move/", "view_class": stage.MoveStageAPI, "conditions": True, }, "zeroStage": { "rule": "/stage/zero/", "view_class": stage.ZeroStageAPI, "conditions": True, }, "shutdown": { "rule": "/system/shutdown/", "view_class": system.ShutdownAPI, "conditions": system.is_raspberrypi(), }, "reboot": { "rule": "/system/reboot/", "view_class": system.RebootAPI, "conditions": system.is_raspberrypi(), }, } def enabled_actions(): global _actions return {k: v for k, v in _actions.items() if v["conditions"]} def add_actions_to_labthing(labthing, prefix=""): """ Add all capture resources to a labthing """ for name, action in enabled_actions().items(): view_class = action["view_class"] rule = action["rule"] labthing.add_resource(view_class, f"{prefix}/actions{rule}") labthing.register_action(view_class) Loading
openflexure_microscope/api/app.py +31 −29 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import logging import sys import os from flask import Flask, jsonify, send_file from flask import Flask, jsonify, send_file, url_for from serial import SerialException from datetime import datetime Loading Loading @@ -79,7 +79,7 @@ CORS(app, resources=r"*") handler = JSONExceptionHandler(app) # Attach lab devices labthing = LabThing(app, prefix="/api/v2b") labthing = LabThing(app, prefix="/api/v2") labthing.description = "Test LabThing-based API for OpenFlexure Microscope" labthing.register_device(api_microscope, "openflexure_microscope") Loading @@ -88,41 +88,23 @@ for _plugin in find_plugins(USER_PLUGINS_PATH): labthing.register_plugin(_plugin) from openflexure_microscope.api.v2.views.captures import add_captures_to_labthing add_captures_to_labthing(labthing, prefix="") # WEBAPP ROUTES ### V2 # Root routes v2_root_blueprint = v2.blueprints.root.construct_blueprint(api_microscope) app.register_blueprint(v2_root_blueprint, url_prefix=uri("/", "v2")) add_captures_to_labthing(labthing, prefix="") from openflexure_microscope.api.v2.views.state import add_states_to_labthing v2_streams_blueprint = v2.blueprints.streams.construct_blueprint(api_microscope) app.register_blueprint(v2_streams_blueprint, url_prefix=uri("/streams", "v2")) add_states_to_labthing(labthing, prefix="") # Captures routes v2_captures_blueprint = v2.blueprints.captures.construct_blueprint(api_microscope) app.register_blueprint(v2_captures_blueprint, url_prefix=uri("/captures", "v2")) from openflexure_microscope.api.v2.views.tasks import add_tasks_to_labthing # Settings routes v2_settings_blueprint = v2.blueprints.settings.construct_blueprint(api_microscope) app.register_blueprint(v2_settings_blueprint, url_prefix=uri("/settings", "v2")) add_tasks_to_labthing(labthing, prefix="") # Status routes v2_status_blueprint = v2.blueprints.status.construct_blueprint(api_microscope) app.register_blueprint(v2_status_blueprint, url_prefix=uri("/status", "v2")) from openflexure_microscope.api.v2.views.streams import add_streams_to_labthing # Plugins routes # v2_plugin_blueprint = v2.blueprints.plugins.construct_blueprint(api_microscope) # app.register_blueprint(v2_plugin_blueprint, url_prefix=uri("/plugins", "v2")) add_streams_to_labthing(labthing, prefix="") # Tasks routes v2_tasks_blueprint = v2.blueprints.tasks.construct_blueprint(api_microscope) app.register_blueprint(v2_tasks_blueprint, url_prefix=uri("/tasks", "v2")) from openflexure_microscope.api.v2.views.actions import add_actions_to_labthing # Actions routes v2_actions_blueprint = v2.blueprints.actions.construct_blueprint(api_microscope) app.register_blueprint(v2_actions_blueprint, url_prefix=uri("/actions", "v2")) add_actions_to_labthing(labthing) @app.route("/routes") Loading @@ -139,6 +121,26 @@ def routes(): return jsonify(list_routes(app)) @app.route("/props") def props(): p = {} for key, prop in labthing.properties.items(): p[key] = {} p[key]["view"] = prop p[key]["url"] = labthing.url_for(prop, _external=True) return jsonify(p) @app.route("/ac") def actions(): p = {} for key, prop in labthing.actions.items(): p[key] = {} p[key]["view"] = prop p[key]["url"] = labthing.url_for(prop, _external=True) return jsonify(p) @app.route("/log") def err_log(): """ Loading
openflexure_microscope/api/v2/blueprints/__init__.py +1 −1 Original line number Diff line number Diff line from . import root, captures, settings, status, tasks, streams, plugins, actions from . import root, captures, settings, status, tasks, streams, actions
openflexure_microscope/api/v2/blueprints/plugins.pydeleted 100644 → 0 +0 −114 Original line number Diff line number Diff line """ Top-level representation of attached and enabled plugins """ from openflexure_microscope.api.views import MicroscopeViewPlugin from openflexure_microscope.utilities import get_docstring, description_from_view from openflexure_microscope.api.utilities import blueprint_for_module from openflexure_microscope.common.labthings.plugins import find_plugins from openflexure_microscope.config import USER_PLUGINS_PATH from flask import Blueprint, jsonify, url_for from openflexure_microscope.api.views import MicroscopeView import copy import logging import warnings _plugins = find_plugins(USER_PLUGINS_PATH) print(_plugins) def plugins_representation(plugin_list): """ Generate a dictionary representation of all plugins, including Flask route URLs Args: plugin_loader_object (:py:class:`openflexure_microscope.plugins.PluginLoader`): Microscope plugin loader Returns: dict: Dictionary representation of all plugins """ plugins = {} for plugin in plugin_list: logging.debug(f"Representing plugin {plugin._name}") d = { "python_name": plugin._name_python_safe, "plugin": str(plugin), "views": {}, "gui": plugin.gui, "description": get_docstring(plugin), } for view_id, view_data in plugin.views.items(): logging.debug(f"Representing view {view_id}") uri = url_for(f"v2_plugins_blueprint.plugins") + view_data["rule"][1:] # uri = view_data["rule"] # Make links dictionary if it doesn't yet exist view_d = {"links": {"self": uri}} view_d.update(description_from_view(view_data["view"])) d["views"][view_id] = view_d plugins[plugin._name] = d return plugins 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. """ global _plugins return jsonify(plugins_representation(_plugins)) def construct_blueprint(microscope_obj): blueprint = blueprint_for_module(__name__) for plugin_obj in _plugins: for plugin_view_id, plugin_view in plugin_obj.views.items(): # Add route to the plugins blueprint blueprint.add_url_rule( plugin_view["rule"], view_func=plugin_view["view"].as_view( f"{plugin_obj._name_python_safe}_{plugin_view_id}" ), **plugin_view["kwargs"], ) # Create a base route to return plugin API forms, if any exist blueprint.add_url_rule( "/", view_func=PluginFormAPI.as_view("plugins", microscope=microscope_obj) ) # For each plugin attached to the microscope object for plugin in microscope_obj.plugins.active: for plugin_view_id, plugin_view in plugin.views.items(): # Add route to the plugins blueprint blueprint.add_url_rule( plugin_view["rule"], view_func=plugin_view["view"].as_view( f"{plugin._name_python_safe}_{plugin_view_id}", microscope=microscope_obj, plugin=plugin, ), **plugin_view["kwargs"], ) return blueprint
openflexure_microscope/api/v2/blueprints/root.py +0 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ from openflexure_microscope.api.utilities import blueprint_name_for_module from openflexure_microscope.api.v2.blueprints import ( settings, status, plugins, captures, actions, streams, Loading
openflexure_microscope/api/v2/views/actions/__init__.py 0 → 100644 +65 −0 Original line number Diff line number Diff line """ Top-level representation of enabled actions """ from flask import Blueprint, url_for, jsonify from openflexure_microscope.api.utilities import blueprint_for_module from openflexure_microscope.utilities import get_docstring, description_from_view from openflexure_microscope.api.views import MicroscopeView from . import camera, stage, system _actions = { "capture": { "rule": "/camera/capture/", "view_class": camera.CaptureAPI, "conditions": True, }, "previewStart": { "rule": "/camera/preview/start", "view_class": camera.GPUPreviewStartAPI, "conditions": True, }, "previewStop": { "rule": "/camera/preview/stop", "view_class": camera.GPUPreviewStopAPI, "conditions": True, }, "move": { "rule": "/stage/move/", "view_class": stage.MoveStageAPI, "conditions": True, }, "zeroStage": { "rule": "/stage/zero/", "view_class": stage.ZeroStageAPI, "conditions": True, }, "shutdown": { "rule": "/system/shutdown/", "view_class": system.ShutdownAPI, "conditions": system.is_raspberrypi(), }, "reboot": { "rule": "/system/reboot/", "view_class": system.RebootAPI, "conditions": system.is_raspberrypi(), }, } def enabled_actions(): global _actions return {k: v for k, v in _actions.items() if v["conditions"]} def add_actions_to_labthing(labthing, prefix=""): """ Add all capture resources to a labthing """ for name, action in enabled_actions().items(): view_class = action["view_class"] rule = action["rule"] labthing.add_resource(view_class, f"{prefix}/actions{rule}") labthing.register_action(view_class)