diff --git a/openflexure_microscope/api/utilities.py b/openflexure_microscope/api/utilities.py index ce8c1b1d..32a854e5 100644 --- a/openflexure_microscope/api/utilities.py +++ b/openflexure_microscope/api/utilities.py @@ -2,13 +2,19 @@ import logging from werkzeug.exceptions import BadRequest from flask import url_for, Blueprint + def blueprint_for_module(module_name, api_ver=2, suffix=""): - return Blueprint(blueprint_name_for_module(module_name, api_ver=api_ver, suffix=suffix), module_name) + return Blueprint( + blueprint_name_for_module(module_name, api_ver=api_ver, suffix=suffix), + module_name, + ) + def blueprint_name_for_module(module_name, api_ver=2, suffix=""): - bp_name = module_name.split('.')[-1] + bp_name = module_name.split(".")[-1] return f"v{api_ver}_{bp_name}_blueprint{suffix}" + class JsonResponse: def __init__(self, request): """ diff --git a/openflexure_microscope/api/v2/blueprints/actions/__init__.py b/openflexure_microscope/api/v2/blueprints/actions/__init__.py index e7cd7c67..32f2c061 100644 --- a/openflexure_microscope/api/v2/blueprints/actions/__init__.py +++ b/openflexure_microscope/api/v2/blueprints/actions/__init__.py @@ -11,6 +11,7 @@ from openflexure_microscope.api.views import MicroscopeView from . import camera, stage, system + class ActionsAPI(MicroscopeView): def get(self): return jsonify(actions_representation()) diff --git a/openflexure_microscope/api/v2/blueprints/actions/camera.py b/openflexure_microscope/api/v2/blueprints/actions/camera.py index 5e199eb1..198dc1ba 100644 --- a/openflexure_microscope/api/v2/blueprints/actions/camera.py +++ b/openflexure_microscope/api/v2/blueprints/actions/camera.py @@ -10,6 +10,7 @@ class CaptureAPI(MicroscopeView): """ Create a new image capture. """ + def post(self): """ Create a new image capture. @@ -107,6 +108,7 @@ class GPUPreviewStartAPI(MicroscopeView): """ Start the onboard GPU preview. """ + def post(self, operation): """ Start the onboard GPU preview. @@ -152,6 +154,7 @@ class GPUPreviewStopAPI(MicroscopeView): """ Stop the onboard GPU preview. """ + def post(self, operation): """ Stop the onboard GPU preview. diff --git a/openflexure_microscope/api/v2/blueprints/actions/stage.py b/openflexure_microscope/api/v2/blueprints/actions/stage.py index 3294011d..7e8af1d3 100644 --- a/openflexure_microscope/api/v2/blueprints/actions/stage.py +++ b/openflexure_microscope/api/v2/blueprints/actions/stage.py @@ -11,6 +11,7 @@ class MoveStageAPI(MicroscopeView): """ Handle stage movements. """ + def post(self): """ Set x, y and z positions of the stage. diff --git a/openflexure_microscope/api/v2/blueprints/actions/system.py b/openflexure_microscope/api/v2/blueprints/actions/system.py index 596144d6..1142b700 100644 --- a/openflexure_microscope/api/v2/blueprints/actions/system.py +++ b/openflexure_microscope/api/v2/blueprints/actions/system.py @@ -7,6 +7,7 @@ class ShutdownAPI(MicroscopeView): """ Attempt to shutdown the device """ + def post(self): """ Attempt to shutdown the device @@ -23,6 +24,7 @@ class RebootAPI(MicroscopeView): """ Attempt to reboot the device """ + def post(self): """ Attempt to shutdown the device diff --git a/openflexure_microscope/api/v2/blueprints/captures.py b/openflexure_microscope/api/v2/blueprints/captures.py index e50ce2e2..4fac46f2 100644 --- a/openflexure_microscope/api/v2/blueprints/captures.py +++ b/openflexure_microscope/api/v2/blueprints/captures.py @@ -383,7 +383,7 @@ class TagsAPI(MicroscopeView): def construct_blueprint(microscope_obj): - + blueprint = blueprint_for_module(__name__) # Tag routes diff --git a/openflexure_microscope/api/v2/blueprints/plugins.py b/openflexure_microscope/api/v2/blueprints/plugins.py index 5b5b8ff6..644a33aa 100644 --- a/openflexure_microscope/api/v2/blueprints/plugins.py +++ b/openflexure_microscope/api/v2/blueprints/plugins.py @@ -14,6 +14,7 @@ import copy import logging import warnings + def plugins_representation(plugin_loader_object: PluginLoader): """ Generate a dictionary representation of all plugins, including Flask route URLs @@ -33,16 +34,14 @@ def plugins_representation(plugin_loader_object: PluginLoader): "plugin": str(plugin), "views": {}, "gui": plugin.gui, - "description": get_docstring(plugin) + "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.{view_id}") # Make links dictionary if it doesn't yet exist - view_d = { - "links": {"self": uri} - } + view_d = {"links": {"self": uri}} view_d.update(description_from_view(view_data["view"])) @@ -87,9 +86,7 @@ def construct_blueprint(microscope_obj): blueprint.add_url_rule( plugin_view["rule"], view_func=plugin_view["view"].as_view( - plugin_view_id, - microscope=microscope_obj, - plugin=plugin, + plugin_view_id, microscope=microscope_obj, plugin=plugin ), ) diff --git a/openflexure_microscope/api/v2/blueprints/root.py b/openflexure_microscope/api/v2/blueprints/root.py index e005e7e7..bdaf348b 100644 --- a/openflexure_microscope/api/v2/blueprints/root.py +++ b/openflexure_microscope/api/v2/blueprints/root.py @@ -4,11 +4,19 @@ from openflexure_microscope.api.views import MicroscopeView from openflexure_microscope.utilities import get_docstring, bottom_level_name from openflexure_microscope.api.utilities import blueprint_name_for_module -from openflexure_microscope.api.v2.blueprints import settings, status, plugins, captures, actions, streams +from openflexure_microscope.api.v2.blueprints import ( + settings, + status, + plugins, + captures, + actions, + streams, +) # List of submodules containing create_blueprint methods using standard blueprint_for_module naming _root_blueprint_modules = [settings, status, plugins, captures, actions, streams] + def root_representation(): """ Generate a dictionar representation of all top-level blueprint rules @@ -23,7 +31,7 @@ def root_representation(): d[module_short_name] = { "name": blueprint_module.__name__, "description": get_docstring(blueprint_module), - "links": {"self": url_for(f"{blueprint_name}.{module_short_name}")} + "links": {"self": url_for(f"{blueprint_name}.{module_short_name}")}, } return d diff --git a/openflexure_microscope/api/v2/blueprints/status.py b/openflexure_microscope/api/v2/blueprints/status.py index ac63d35a..6344cb42 100644 --- a/openflexure_microscope/api/v2/blueprints/status.py +++ b/openflexure_microscope/api/v2/blueprints/status.py @@ -7,6 +7,7 @@ from openflexure_microscope.api.utilities import blueprint_for_module from flask import Blueprint, jsonify + class StatusAPI(MicroscopeView): def get(self): """ diff --git a/openflexure_microscope/api/v2/blueprints/streams.py b/openflexure_microscope/api/v2/blueprints/streams.py index e727c6e3..e11bb3df 100644 --- a/openflexure_microscope/api/v2/blueprints/streams.py +++ b/openflexure_microscope/api/v2/blueprints/streams.py @@ -4,7 +4,10 @@ Top-level description of routes related to live camera stream data from openflexure_microscope.api.utilities import gen, JsonResponse from openflexure_microscope.api.views import MicroscopeView -from openflexure_microscope.api.utilities import blueprint_for_module, blueprint_name_for_module +from openflexure_microscope.api.utilities import ( + blueprint_for_module, + blueprint_name_for_module, +) from openflexure_microscope.utilities import description_from_view from flask import Response, Blueprint, jsonify, request, url_for @@ -19,6 +22,7 @@ class MjpegAPI(MicroscopeView): """ Real-time MJPEG stream from the microscope camera """ + def get(self): """ Real-time MJPEG stream from the microscope camera @@ -42,6 +46,7 @@ class SnapshotAPI(MicroscopeView): """ Single JPEG snapshot from the camera stream """ + def get(self): """ Single snapshot from the camera stream @@ -59,16 +64,8 @@ class SnapshotAPI(MicroscopeView): _streams = { - "mjpeg": { - "rule": "/mjpeg", - "view_class": MjpegAPI, - "conditions": True, - }, - "snapshot": { - "rule": "/snapshot", - "view_class": SnapshotAPI, - "conditions": True, - } + "mjpeg": {"rule": "/mjpeg", "view_class": MjpegAPI, "conditions": True}, + "snapshot": {"rule": "/snapshot", "view_class": SnapshotAPI, "conditions": True}, } @@ -82,9 +79,7 @@ def streams_representation(): streams = {} for name, stream in enabled_streams().items(): - d = { - "links": {"self": url_for(f".{name}")}, - } + d = {"links": {"self": url_for(f".{name}")}} d.update(description_from_view(stream["view_class"])) diff --git a/openflexure_microscope/camera/mock.py b/openflexure_microscope/camera/mock.py index 2769f6a6..7aca48d8 100644 --- a/openflexure_microscope/camera/mock.py +++ b/openflexure_microscope/camera/mock.py @@ -23,7 +23,7 @@ from openflexure_microscope.camera.base import BaseCamera PIL spams the logger with debug-level information. This is a pain when debugging api.app. We override the logging settings in api.app by setting a level for PIL here. """ -pil_logger = logging.getLogger('PIL') +pil_logger = logging.getLogger("PIL") pil_logger.setLevel(logging.INFO) # MAIN CLASS diff --git a/openflexure_microscope/plugins/default/autofocus/api.py b/openflexure_microscope/plugins/default/autofocus/api.py index ee28abb1..e04bd529 100644 --- a/openflexure_microscope/plugins/default/autofocus/api.py +++ b/openflexure_microscope/plugins/default/autofocus/api.py @@ -21,6 +21,7 @@ class AutofocusAPI(MicroscopeViewPlugin): """ Run a standard autofocus """ + def post(self): payload = JsonResponse(request) @@ -42,6 +43,7 @@ class FastAutofocusAPI(MicroscopeViewPlugin): """ Run a fast autofocus """ + def post(self): payload = JsonResponse(request) diff --git a/openflexure_microscope/plugins/loader.py b/openflexure_microscope/plugins/loader.py index ad1e4207..0981d822 100644 --- a/openflexure_microscope/plugins/loader.py +++ b/openflexure_microscope/plugins/loader.py @@ -186,7 +186,7 @@ class PluginLoader(object): plugin_object = plugin_class() if hasattr( - self, plugin_name + self, plugin_name ): # If a plugin with the same name is already attached. logging.warning( ConColors.WARNING @@ -197,7 +197,7 @@ class PluginLoader(object): ) elif isinstance( - plugin_object, BasePlugin + plugin_object, BasePlugin ): # If plugin_object is an instance of MicroscopePlugin # Attach plugin_object to the plugin mount setattr(self, plugin_name_python_safe, plugin_object) @@ -212,7 +212,9 @@ class PluginLoader(object): logging.info( ConColors.OKGREEN - + "Plugin {} loaded as {}.".format(plugin_map, plugin_object._name) + + "Plugin {} loaded as {}.".format( + plugin_map, plugin_object._name + ) + ConColors.ENDC ) @@ -228,7 +230,9 @@ class BasePlugin: """ def __init__(self): - self._views = {} # Key: Full, Python-safe ID. Val: Original rule, and view class + self._views = ( + {} + ) # Key: Full, Python-safe ID. Val: Original rule, and view class self._rules = {} # Key: Original rule. Val: View class self._gui = None @@ -258,10 +262,7 @@ class BasePlugin: view_id = cleaned_rule.replace("/", "_") # Store route information in a dictionary - d = { - "rule": full_rule, - "view": view_class - } + d = {"rule": full_rule, "view": view_class} # Add view to private views dictionary self._views[view_id] = d @@ -276,17 +277,13 @@ class BasePlugin: api_gui = copy.deepcopy(self._gui) api_gui["id"] = self._name - if "forms" in api_gui and isinstance( - api_gui["forms"], list - ): + if "forms" in api_gui and isinstance(api_gui["forms"], list): for form in api_gui["forms"]: if "route" in form and form["route"] in self._rules.keys(): form["route"] = self._rules[form["route"]]["rule"] else: logging.warn( - "No valid expandable route found for {}".format( - form["route"] - ) + "No valid expandable route found for {}".format(form["route"]) ) return api_gui @@ -317,7 +314,7 @@ class BasePlugin: if module is None or module == str.__class__.__module__: return self.__class__.__name__ # Avoid reporting __builtin__ else: - return module + '.' + self.__class__.__name__ + return module + "." + self.__class__.__name__ class MicroscopePlugin(BasePlugin): diff --git a/openflexure_microscope/stage/sangaboard/extensible_serial_instrument.py b/openflexure_microscope/stage/sangaboard/extensible_serial_instrument.py index 2427dd06..7524932e 100644 --- a/openflexure_microscope/stage/sangaboard/extensible_serial_instrument.py +++ b/openflexure_microscope/stage/sangaboard/extensible_serial_instrument.py @@ -213,7 +213,9 @@ class ExtensibleSerialInstrument(object): return self.read_multiline(termination_line) else: logging.debug("Reading response...") - line = self.readline().strip() # question: should we strip the final newline? + line = ( + self.readline().strip() + ) # question: should we strip the final newline? logging.debug(f"Read finished. Got {line}") return line @@ -223,7 +225,7 @@ class ExtensibleSerialInstrument(object): response_string=r"%d", re_flags=0, parse_function=None, - **kwargs + **kwargs, ): """ Perform a query, returning a parsed form of the response. diff --git a/openflexure_microscope/utilities.py b/openflexure_microscope/utilities.py index fa194fc1..27e5734d 100644 --- a/openflexure_microscope/utilities.py +++ b/openflexure_microscope/utilities.py @@ -5,23 +5,23 @@ from collections import abc from functools import reduce from contextlib import contextmanager + def bottom_level_name(obj): - return obj.__name__.split('.')[-1] + return obj.__name__.split(".")[-1] + def description_from_view(view_class): methods = [] for method_key in ["get", "post", "put", "delete"]: if hasattr(view_class, method_key): methods.append(method_key.upper()) - brief_description = get_docstring(view_class).partition('\n')[0].strip() + brief_description = get_docstring(view_class).partition("\n")[0].strip() - d = { - "methods": methods, - "description": brief_description - } + d = {"methods": methods, "description": brief_description} return d + def get_docstring(obj): ds = obj.__doc__ if ds: @@ -29,13 +29,16 @@ def get_docstring(obj): else: return "" + def camel_to_snake(name): - s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) - return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() + s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) + return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() + def camel_to_spine(name): - s1 = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', name) - return re.sub('([a-z0-9])([A-Z])', r'\1-\2', s1).lower() + s1 = re.sub("(.)([A-Z][a-z]+)", r"\1-\2", name) + return re.sub("([a-z0-9])([A-Z])", r"\1-\2", s1).lower() + @contextmanager def set_properties(obj, **kwargs):