Blackened

This commit is contained in:
Joel Collins 2019-11-20 14:13:01 +00:00
parent 36f195d6e7
commit b430a2d34a
15 changed files with 72 additions and 54 deletions

View file

@ -2,13 +2,19 @@ import logging
from werkzeug.exceptions import BadRequest from werkzeug.exceptions import BadRequest
from flask import url_for, Blueprint from flask import url_for, Blueprint
def blueprint_for_module(module_name, api_ver=2, suffix=""): 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=""): 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}" return f"v{api_ver}_{bp_name}_blueprint{suffix}"
class JsonResponse: class JsonResponse:
def __init__(self, request): def __init__(self, request):
""" """

View file

@ -11,6 +11,7 @@ from openflexure_microscope.api.views import MicroscopeView
from . import camera, stage, system from . import camera, stage, system
class ActionsAPI(MicroscopeView): class ActionsAPI(MicroscopeView):
def get(self): def get(self):
return jsonify(actions_representation()) return jsonify(actions_representation())

View file

@ -10,6 +10,7 @@ class CaptureAPI(MicroscopeView):
""" """
Create a new image capture. Create a new image capture.
""" """
def post(self): def post(self):
""" """
Create a new image capture. Create a new image capture.
@ -107,6 +108,7 @@ class GPUPreviewStartAPI(MicroscopeView):
""" """
Start the onboard GPU preview. Start the onboard GPU preview.
""" """
def post(self, operation): def post(self, operation):
""" """
Start the onboard GPU preview. Start the onboard GPU preview.
@ -152,6 +154,7 @@ class GPUPreviewStopAPI(MicroscopeView):
""" """
Stop the onboard GPU preview. Stop the onboard GPU preview.
""" """
def post(self, operation): def post(self, operation):
""" """
Stop the onboard GPU preview. Stop the onboard GPU preview.

View file

@ -11,6 +11,7 @@ class MoveStageAPI(MicroscopeView):
""" """
Handle stage movements. Handle stage movements.
""" """
def post(self): def post(self):
""" """
Set x, y and z positions of the stage. Set x, y and z positions of the stage.

View file

@ -7,6 +7,7 @@ class ShutdownAPI(MicroscopeView):
""" """
Attempt to shutdown the device Attempt to shutdown the device
""" """
def post(self): def post(self):
""" """
Attempt to shutdown the device Attempt to shutdown the device
@ -23,6 +24,7 @@ class RebootAPI(MicroscopeView):
""" """
Attempt to reboot the device Attempt to reboot the device
""" """
def post(self): def post(self):
""" """
Attempt to shutdown the device Attempt to shutdown the device

View file

@ -14,6 +14,7 @@ import copy
import logging import logging
import warnings import warnings
def plugins_representation(plugin_loader_object: PluginLoader): def plugins_representation(plugin_loader_object: PluginLoader):
""" """
Generate a dictionary representation of all plugins, including Flask route URLs 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), "plugin": str(plugin),
"views": {}, "views": {},
"gui": plugin.gui, "gui": plugin.gui,
"description": get_docstring(plugin) "description": get_docstring(plugin),
} }
for view_id, view_data in plugin.views.items(): for view_id, view_data in plugin.views.items():
logging.debug(f"Representing view {view_id}") logging.debug(f"Representing view {view_id}")
uri = url_for(f"v2_plugins_blueprint.{view_id}") uri = url_for(f"v2_plugins_blueprint.{view_id}")
# Make links dictionary if it doesn't yet exist # Make links dictionary if it doesn't yet exist
view_d = { view_d = {"links": {"self": uri}}
"links": {"self": uri}
}
view_d.update(description_from_view(view_data["view"])) view_d.update(description_from_view(view_data["view"]))
@ -87,9 +86,7 @@ def construct_blueprint(microscope_obj):
blueprint.add_url_rule( blueprint.add_url_rule(
plugin_view["rule"], plugin_view["rule"],
view_func=plugin_view["view"].as_view( view_func=plugin_view["view"].as_view(
plugin_view_id, plugin_view_id, microscope=microscope_obj, plugin=plugin
microscope=microscope_obj,
plugin=plugin,
), ),
) )

View file

@ -4,11 +4,19 @@ from openflexure_microscope.api.views import MicroscopeView
from openflexure_microscope.utilities import get_docstring, bottom_level_name from openflexure_microscope.utilities import get_docstring, bottom_level_name
from openflexure_microscope.api.utilities import blueprint_name_for_module 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 # List of submodules containing create_blueprint methods using standard blueprint_for_module naming
_root_blueprint_modules = [settings, status, plugins, captures, actions, streams] _root_blueprint_modules = [settings, status, plugins, captures, actions, streams]
def root_representation(): def root_representation():
""" """
Generate a dictionar representation of all top-level blueprint rules Generate a dictionar representation of all top-level blueprint rules
@ -23,7 +31,7 @@ def root_representation():
d[module_short_name] = { d[module_short_name] = {
"name": blueprint_module.__name__, "name": blueprint_module.__name__,
"description": get_docstring(blueprint_module), "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 return d

View file

@ -7,6 +7,7 @@ from openflexure_microscope.api.utilities import blueprint_for_module
from flask import Blueprint, jsonify from flask import Blueprint, jsonify
class StatusAPI(MicroscopeView): class StatusAPI(MicroscopeView):
def get(self): def get(self):
""" """

View file

@ -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.utilities import gen, JsonResponse
from openflexure_microscope.api.views import MicroscopeView 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 openflexure_microscope.utilities import description_from_view
from flask import Response, Blueprint, jsonify, request, url_for from flask import Response, Blueprint, jsonify, request, url_for
@ -19,6 +22,7 @@ class MjpegAPI(MicroscopeView):
""" """
Real-time MJPEG stream from the microscope camera Real-time MJPEG stream from the microscope camera
""" """
def get(self): def get(self):
""" """
Real-time MJPEG stream from the microscope camera Real-time MJPEG stream from the microscope camera
@ -42,6 +46,7 @@ class SnapshotAPI(MicroscopeView):
""" """
Single JPEG snapshot from the camera stream Single JPEG snapshot from the camera stream
""" """
def get(self): def get(self):
""" """
Single snapshot from the camera stream Single snapshot from the camera stream
@ -59,16 +64,8 @@ class SnapshotAPI(MicroscopeView):
_streams = { _streams = {
"mjpeg": { "mjpeg": {"rule": "/mjpeg", "view_class": MjpegAPI, "conditions": True},
"rule": "/mjpeg", "snapshot": {"rule": "/snapshot", "view_class": SnapshotAPI, "conditions": True},
"view_class": MjpegAPI,
"conditions": True,
},
"snapshot": {
"rule": "/snapshot",
"view_class": SnapshotAPI,
"conditions": True,
}
} }
@ -82,9 +79,7 @@ def streams_representation():
streams = {} streams = {}
for name, stream in enabled_streams().items(): for name, stream in enabled_streams().items():
d = { d = {"links": {"self": url_for(f".{name}")}}
"links": {"self": url_for(f".{name}")},
}
d.update(description_from_view(stream["view_class"])) d.update(description_from_view(stream["view_class"]))

View file

@ -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. 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. 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) pil_logger.setLevel(logging.INFO)
# MAIN CLASS # MAIN CLASS

View file

@ -21,6 +21,7 @@ class AutofocusAPI(MicroscopeViewPlugin):
""" """
Run a standard autofocus Run a standard autofocus
""" """
def post(self): def post(self):
payload = JsonResponse(request) payload = JsonResponse(request)
@ -42,6 +43,7 @@ class FastAutofocusAPI(MicroscopeViewPlugin):
""" """
Run a fast autofocus Run a fast autofocus
""" """
def post(self): def post(self):
payload = JsonResponse(request) payload = JsonResponse(request)

View file

@ -212,7 +212,9 @@ class PluginLoader(object):
logging.info( logging.info(
ConColors.OKGREEN ConColors.OKGREEN
+ "Plugin {} loaded as {}.".format(plugin_map, plugin_object._name) + "Plugin {} loaded as {}.".format(
plugin_map, plugin_object._name
)
+ ConColors.ENDC + ConColors.ENDC
) )
@ -228,7 +230,9 @@ class BasePlugin:
""" """
def __init__(self): 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._rules = {} # Key: Original rule. Val: View class
self._gui = None self._gui = None
@ -258,10 +262,7 @@ class BasePlugin:
view_id = cleaned_rule.replace("/", "_") view_id = cleaned_rule.replace("/", "_")
# Store route information in a dictionary # Store route information in a dictionary
d = { d = {"rule": full_rule, "view": view_class}
"rule": full_rule,
"view": view_class
}
# Add view to private views dictionary # Add view to private views dictionary
self._views[view_id] = d self._views[view_id] = d
@ -276,17 +277,13 @@ class BasePlugin:
api_gui = copy.deepcopy(self._gui) api_gui = copy.deepcopy(self._gui)
api_gui["id"] = self._name api_gui["id"] = self._name
if "forms" in api_gui and isinstance( if "forms" in api_gui and isinstance(api_gui["forms"], list):
api_gui["forms"], list
):
for form in api_gui["forms"]: for form in api_gui["forms"]:
if "route" in form and form["route"] in self._rules.keys(): if "route" in form and form["route"] in self._rules.keys():
form["route"] = self._rules[form["route"]]["rule"] form["route"] = self._rules[form["route"]]["rule"]
else: else:
logging.warn( logging.warn(
"No valid expandable route found for {}".format( "No valid expandable route found for {}".format(form["route"])
form["route"]
)
) )
return api_gui return api_gui
@ -317,7 +314,7 @@ class BasePlugin:
if module is None or module == str.__class__.__module__: if module is None or module == str.__class__.__module__:
return self.__class__.__name__ # Avoid reporting __builtin__ return self.__class__.__name__ # Avoid reporting __builtin__
else: else:
return module + '.' + self.__class__.__name__ return module + "." + self.__class__.__name__
class MicroscopePlugin(BasePlugin): class MicroscopePlugin(BasePlugin):

View file

@ -213,7 +213,9 @@ class ExtensibleSerialInstrument(object):
return self.read_multiline(termination_line) return self.read_multiline(termination_line)
else: else:
logging.debug("Reading response...") 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}") logging.debug(f"Read finished. Got {line}")
return line return line
@ -223,7 +225,7 @@ class ExtensibleSerialInstrument(object):
response_string=r"%d", response_string=r"%d",
re_flags=0, re_flags=0,
parse_function=None, parse_function=None,
**kwargs **kwargs,
): ):
""" """
Perform a query, returning a parsed form of the response. Perform a query, returning a parsed form of the response.

View file

@ -5,23 +5,23 @@ from collections import abc
from functools import reduce from functools import reduce
from contextlib import contextmanager from contextlib import contextmanager
def bottom_level_name(obj): def bottom_level_name(obj):
return obj.__name__.split('.')[-1] return obj.__name__.split(".")[-1]
def description_from_view(view_class): def description_from_view(view_class):
methods = [] methods = []
for method_key in ["get", "post", "put", "delete"]: for method_key in ["get", "post", "put", "delete"]:
if hasattr(view_class, method_key): if hasattr(view_class, method_key):
methods.append(method_key.upper()) 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 = { d = {"methods": methods, "description": brief_description}
"methods": methods,
"description": brief_description
}
return d return d
def get_docstring(obj): def get_docstring(obj):
ds = obj.__doc__ ds = obj.__doc__
if ds: if ds:
@ -29,13 +29,16 @@ def get_docstring(obj):
else: else:
return "" return ""
def camel_to_snake(name): def camel_to_snake(name):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', 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() return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
def camel_to_spine(name): def camel_to_spine(name):
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1-\2', 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() return re.sub("([a-z0-9])([A-Z])", r"\1-\2", s1).lower()
@contextmanager @contextmanager
def set_properties(obj, **kwargs): def set_properties(obj, **kwargs):