Loading docs/source/plugins/example/plugin.py +1 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ from openflexure_microscope.plugins import MicroscopePlugin from openflexure_microscope.api.views import MicroscopeViewPlugin from openflexure_microscope.api.utilities import JsonResponse from openflexure_microscope.common.tasks import taskify from openflexure_microscope.common.labthings_core.tasks import taskify import os import time Loading openflexure_microscope/api/app.py +10 −18 Original line number Diff line number Diff line Loading @@ -3,29 +3,24 @@ import time import atexit import logging import sys import os from flask import Flask, jsonify, send_file, url_for from flask import Flask, jsonify, send_file from serial import SerialException from datetime import datetime from flask_cors import CORS from openflexure_microscope.api.exceptions import JSONExceptionHandler from openflexure_microscope.api.utilities import list_routes from openflexure_microscope.api.utilities import list_routes, init_default_plugins from openflexure_microscope.config import ( settings_file_path, JSONEncoder, USER_PLUGINS_PATH, ) from openflexure_microscope.api import v2 from openflexure_microscope.common.labthings.labthing import LabThing from openflexure_microscope.common.labthings.find import registered_plugins from openflexure_microscope.common.labthings.plugins import find_plugins from openflexure_microscope.common.flask_labthings.labthing import LabThing from openflexure_microscope.common.flask_labthings.plugins import find_plugins from openflexure_microscope.api.microscope import default_microscope as api_microscope Loading @@ -36,14 +31,13 @@ is_gunicorn = "gunicorn" in os.environ.get("SERVER_SOFTWARE", "") DEFAULT_LOGFILE = settings_file_path("openflexure_microscope.log") logger = logging.getLogger() if (__name__ == "__main__") or (not is_gunicorn): # If imported, but not by gunicorn print("Letting sys handle logs") logger = logging.getLogger() logger.setLevel(logging.DEBUG) else: # Direct standard Python logging to file and console root = logging.getLogger() error_formatter = logging.Formatter( "[%(asctime)s] [%(threadName)s] [%(levelname)s] %(message)s" ) Loading @@ -56,9 +50,9 @@ else: for handler in error_handlers: handler.setFormatter(error_formatter) root.addHandler(handler) logger.addHandler(handler) root.setLevel(logging.getLogger("gunicorn.error").level) logger.setLevel(logging.getLogger("gunicorn.error").level) # Create flask app Loading @@ -71,9 +65,6 @@ app.json_encoder = JSONEncoder # Enable CORS everywhere CORS(app, resources=r"*") # Make errors more API friendly handler = JSONExceptionHandler(app) # Build a labthing labthing = LabThing(app, prefix="/api/v2") labthing.description = "Test LabThing-based API for OpenFlexure Microscope" Loading @@ -83,6 +74,8 @@ labthing.title = f"OpenFlexure Microscope {api_microscope.name}" labthing.register_device(api_microscope, "openflexure_microscope") # Attach plugins if not os.path.isfile(USER_PLUGINS_PATH): init_default_plugins(USER_PLUGINS_PATH) for plugin in find_plugins(USER_PLUGINS_PATH): labthing.register_plugin(plugin) Loading Loading @@ -120,7 +113,7 @@ labthing.register_property(views.SnapshotStream) for name, action in views.enabled_root_actions().items(): view_class = action["view_class"] rule = action["rule"] labthing.add_resource(view_class, "/actions{rule}") labthing.add_resource(view_class, f"/actions{rule}") labthing.register_action(view_class) Loading Loading @@ -159,7 +152,6 @@ def err_log(): # Automatically clean up microscope at exit def cleanup(): global api_microscope logging.debug("App teardown started...") logging.debug("Settling...") time.sleep(0.5) Loading openflexure_microscope/api/microscope.py +1 −5 Original line number Diff line number Diff line Loading @@ -28,11 +28,7 @@ except Exception as e: # Initialise stage logging.debug("Creating stage object...") try: api_stage = SangaStage() except Exception as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() # Attach devices to microscope Loading openflexure_microscope/api/utilities.py +30 −0 Original line number Diff line number Diff line import logging import os import errno from werkzeug.exceptions import BadRequest from flask import url_for, Blueprint Loading Loading @@ -95,3 +97,31 @@ def list_routes(app): output[url] = line return output def create_file(config_path): if not os.path.exists(os.path.dirname(config_path)): try: os.makedirs(os.path.dirname(config_path)) except OSError as exc: # Guard against race condition if exc.errno != errno.EEXIST: raise def init_default_plugins(plugin_path): global _DEFAULT_PLUGIN_INIT os.makedirs(os.path.dirname(plugin_path), exist_ok=True) if not os.path.exists(plugin_path): # If user plugins file doesn't exist logging.warning("No plugin file found at {}. Creating...".format(plugin_path)) create_file(plugin_path) logging.info("Populating {}...".format(plugin_path)) with open(plugin_path, "w") as outfile: outfile.write(_DEFAULT_PLUGIN_INIT) _DEFAULT_PLUGIN_INIT = """from openflexure_microscope.plugins.v2.autofocus import autofocus_plugin_v2 from openflexure_microscope.plugins.v2.scan import scan_plugin_v2 __plugins__ = [autofocus_plugin_v2, scan_plugin_v2]""" No newline at end of file openflexure_microscope/api/v2/views/actions/__init__.py +0 −5 Original line number Diff line number Diff line Loading @@ -2,11 +2,6 @@ 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 . import camera, stage, system _actions = { Loading Loading
docs/source/plugins/example/plugin.py +1 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ from openflexure_microscope.plugins import MicroscopePlugin from openflexure_microscope.api.views import MicroscopeViewPlugin from openflexure_microscope.api.utilities import JsonResponse from openflexure_microscope.common.tasks import taskify from openflexure_microscope.common.labthings_core.tasks import taskify import os import time Loading
openflexure_microscope/api/app.py +10 −18 Original line number Diff line number Diff line Loading @@ -3,29 +3,24 @@ import time import atexit import logging import sys import os from flask import Flask, jsonify, send_file, url_for from flask import Flask, jsonify, send_file from serial import SerialException from datetime import datetime from flask_cors import CORS from openflexure_microscope.api.exceptions import JSONExceptionHandler from openflexure_microscope.api.utilities import list_routes from openflexure_microscope.api.utilities import list_routes, init_default_plugins from openflexure_microscope.config import ( settings_file_path, JSONEncoder, USER_PLUGINS_PATH, ) from openflexure_microscope.api import v2 from openflexure_microscope.common.labthings.labthing import LabThing from openflexure_microscope.common.labthings.find import registered_plugins from openflexure_microscope.common.labthings.plugins import find_plugins from openflexure_microscope.common.flask_labthings.labthing import LabThing from openflexure_microscope.common.flask_labthings.plugins import find_plugins from openflexure_microscope.api.microscope import default_microscope as api_microscope Loading @@ -36,14 +31,13 @@ is_gunicorn = "gunicorn" in os.environ.get("SERVER_SOFTWARE", "") DEFAULT_LOGFILE = settings_file_path("openflexure_microscope.log") logger = logging.getLogger() if (__name__ == "__main__") or (not is_gunicorn): # If imported, but not by gunicorn print("Letting sys handle logs") logger = logging.getLogger() logger.setLevel(logging.DEBUG) else: # Direct standard Python logging to file and console root = logging.getLogger() error_formatter = logging.Formatter( "[%(asctime)s] [%(threadName)s] [%(levelname)s] %(message)s" ) Loading @@ -56,9 +50,9 @@ else: for handler in error_handlers: handler.setFormatter(error_formatter) root.addHandler(handler) logger.addHandler(handler) root.setLevel(logging.getLogger("gunicorn.error").level) logger.setLevel(logging.getLogger("gunicorn.error").level) # Create flask app Loading @@ -71,9 +65,6 @@ app.json_encoder = JSONEncoder # Enable CORS everywhere CORS(app, resources=r"*") # Make errors more API friendly handler = JSONExceptionHandler(app) # Build a labthing labthing = LabThing(app, prefix="/api/v2") labthing.description = "Test LabThing-based API for OpenFlexure Microscope" Loading @@ -83,6 +74,8 @@ labthing.title = f"OpenFlexure Microscope {api_microscope.name}" labthing.register_device(api_microscope, "openflexure_microscope") # Attach plugins if not os.path.isfile(USER_PLUGINS_PATH): init_default_plugins(USER_PLUGINS_PATH) for plugin in find_plugins(USER_PLUGINS_PATH): labthing.register_plugin(plugin) Loading Loading @@ -120,7 +113,7 @@ labthing.register_property(views.SnapshotStream) for name, action in views.enabled_root_actions().items(): view_class = action["view_class"] rule = action["rule"] labthing.add_resource(view_class, "/actions{rule}") labthing.add_resource(view_class, f"/actions{rule}") labthing.register_action(view_class) Loading Loading @@ -159,7 +152,6 @@ def err_log(): # Automatically clean up microscope at exit def cleanup(): global api_microscope logging.debug("App teardown started...") logging.debug("Settling...") time.sleep(0.5) Loading
openflexure_microscope/api/microscope.py +1 −5 Original line number Diff line number Diff line Loading @@ -28,11 +28,7 @@ except Exception as e: # Initialise stage logging.debug("Creating stage object...") try: api_stage = SangaStage() except Exception as e: logging.error(e) logging.warning("No valid stage hardware found. Falling back to mock stage!") api_stage = MockStage() # Attach devices to microscope Loading
openflexure_microscope/api/utilities.py +30 −0 Original line number Diff line number Diff line import logging import os import errno from werkzeug.exceptions import BadRequest from flask import url_for, Blueprint Loading Loading @@ -95,3 +97,31 @@ def list_routes(app): output[url] = line return output def create_file(config_path): if not os.path.exists(os.path.dirname(config_path)): try: os.makedirs(os.path.dirname(config_path)) except OSError as exc: # Guard against race condition if exc.errno != errno.EEXIST: raise def init_default_plugins(plugin_path): global _DEFAULT_PLUGIN_INIT os.makedirs(os.path.dirname(plugin_path), exist_ok=True) if not os.path.exists(plugin_path): # If user plugins file doesn't exist logging.warning("No plugin file found at {}. Creating...".format(plugin_path)) create_file(plugin_path) logging.info("Populating {}...".format(plugin_path)) with open(plugin_path, "w") as outfile: outfile.write(_DEFAULT_PLUGIN_INIT) _DEFAULT_PLUGIN_INIT = """from openflexure_microscope.plugins.v2.autofocus import autofocus_plugin_v2 from openflexure_microscope.plugins.v2.scan import scan_plugin_v2 __plugins__ = [autofocus_plugin_v2, scan_plugin_v2]""" No newline at end of file
openflexure_microscope/api/v2/views/actions/__init__.py +0 −5 Original line number Diff line number Diff line Loading @@ -2,11 +2,6 @@ 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 . import camera, stage, system _actions = { Loading