Use more docstrings as descriptions
This commit is contained in:
parent
d3f2807bb9
commit
9b387985e3
12 changed files with 88 additions and 59 deletions
|
|
@ -1,7 +1,13 @@
|
||||||
import logging
|
import logging
|
||||||
from werkzeug.exceptions import BadRequest
|
from werkzeug.exceptions import BadRequest
|
||||||
from flask import url_for
|
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)
|
||||||
|
|
||||||
|
def blueprint_name_for_module(module_name, api_ver=2, suffix=""):
|
||||||
|
bp_name = module_name.split('.')[-1]
|
||||||
|
return f"v{api_ver}_{bp_name}_blueprint{suffix}"
|
||||||
|
|
||||||
class JsonResponse:
|
class JsonResponse:
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
|
"""
|
||||||
|
Top-level representation of enabled actions
|
||||||
|
"""
|
||||||
|
|
||||||
from flask import Blueprint, url_for, jsonify
|
from flask import Blueprint, url_for, jsonify
|
||||||
from sys import platform
|
from sys import platform
|
||||||
|
|
||||||
from openflexure_microscope.utilities import get_docstring
|
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 openflexure_microscope.api.views import MicroscopeView
|
||||||
|
|
||||||
from . import camera, stage, system
|
from . import camera, stage, system
|
||||||
|
|
||||||
# TODO: Could allowed methods be calculated automatically by looking at what methods exist?
|
|
||||||
_actions = {
|
_actions = {
|
||||||
"capture": {
|
"capture": {
|
||||||
"rule": "/camera/capture/",
|
"rule": "/camera/capture/",
|
||||||
|
|
@ -53,11 +57,12 @@ def actions_representation():
|
||||||
for name, action in enabled_actions().items():
|
for name, action in enabled_actions().items():
|
||||||
d = {
|
d = {
|
||||||
"links": {"self": url_for(f".{name}")},
|
"links": {"self": url_for(f".{name}")},
|
||||||
"description": get_docstring(action["view_class"]),
|
|
||||||
"rule": action["rule"],
|
"rule": action["rule"],
|
||||||
"view_class": str(action["view_class"]),
|
"view_class": str(action["view_class"]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.update(description_from_view(action["view_class"]))
|
||||||
|
|
||||||
actions[name] = d
|
actions[name] = d
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
|
|
@ -69,7 +74,7 @@ class ActionsAPI(MicroscopeView):
|
||||||
def construct_blueprint(microscope_obj):
|
def construct_blueprint(microscope_obj):
|
||||||
global _actions
|
global _actions
|
||||||
|
|
||||||
blueprint = Blueprint("v2_actions_blueprint", __name__)
|
blueprint = blueprint_for_module(__name__)
|
||||||
|
|
||||||
# For each enabled action route defined in our dictionary above
|
# For each enabled action route defined in our dictionary above
|
||||||
for name, action in enabled_actions().items():
|
for name, action in enabled_actions().items():
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,6 @@ from flask import jsonify, request, abort, url_for, redirect, send_file
|
||||||
class CaptureAPI(MicroscopeView):
|
class CaptureAPI(MicroscopeView):
|
||||||
"""
|
"""
|
||||||
Create a new image capture.
|
Create a new image capture.
|
||||||
|
|
||||||
Allowed methods:
|
|
||||||
POST
|
|
||||||
"""
|
"""
|
||||||
def post(self):
|
def post(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -109,9 +106,6 @@ class CaptureAPI(MicroscopeView):
|
||||||
class GPUPreviewStartAPI(MicroscopeView):
|
class GPUPreviewStartAPI(MicroscopeView):
|
||||||
"""
|
"""
|
||||||
Start the onboard GPU preview.
|
Start the onboard GPU preview.
|
||||||
|
|
||||||
Allowed methods:
|
|
||||||
POST
|
|
||||||
"""
|
"""
|
||||||
def post(self, operation):
|
def post(self, operation):
|
||||||
"""
|
"""
|
||||||
|
|
@ -157,9 +151,6 @@ class GPUPreviewStartAPI(MicroscopeView):
|
||||||
class GPUPreviewStopAPI(MicroscopeView):
|
class GPUPreviewStopAPI(MicroscopeView):
|
||||||
"""
|
"""
|
||||||
Stop the onboard GPU preview.
|
Stop the onboard GPU preview.
|
||||||
|
|
||||||
Allowed methods:
|
|
||||||
POST
|
|
||||||
"""
|
"""
|
||||||
def post(self, operation):
|
def post(self, operation):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,6 @@ import logging
|
||||||
class MoveStageAPI(MicroscopeView):
|
class MoveStageAPI(MicroscopeView):
|
||||||
"""
|
"""
|
||||||
Handle stage movements.
|
Handle stage movements.
|
||||||
|
|
||||||
Allowed methods:
|
|
||||||
POST
|
|
||||||
"""
|
"""
|
||||||
def post(self):
|
def post(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,6 @@ import subprocess
|
||||||
class ShutdownAPI(MicroscopeView):
|
class ShutdownAPI(MicroscopeView):
|
||||||
"""
|
"""
|
||||||
Attempt to shutdown the device
|
Attempt to shutdown the device
|
||||||
|
|
||||||
Allowed methods:
|
|
||||||
POST
|
|
||||||
"""
|
"""
|
||||||
def post(self):
|
def post(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -25,9 +22,6 @@ class ShutdownAPI(MicroscopeView):
|
||||||
class RebootAPI(MicroscopeView):
|
class RebootAPI(MicroscopeView):
|
||||||
"""
|
"""
|
||||||
Attempt to reboot the device
|
Attempt to reboot the device
|
||||||
|
|
||||||
Allowed methods:
|
|
||||||
POST
|
|
||||||
"""
|
"""
|
||||||
def post(self):
|
def post(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
|
"""
|
||||||
|
Top-level representation of all acquired captures
|
||||||
|
"""
|
||||||
|
|
||||||
from openflexure_microscope.api.utilities import get_bool, JsonResponse
|
from openflexure_microscope.api.utilities import get_bool, JsonResponse
|
||||||
from openflexure_microscope.api.views import MicroscopeView
|
from openflexure_microscope.api.views import MicroscopeView
|
||||||
from openflexure_microscope.utilities import filter_dict
|
from openflexure_microscope.utilities import filter_dict
|
||||||
|
from openflexure_microscope.api.utilities import blueprint_for_module
|
||||||
|
|
||||||
from flask import jsonify, request, abort, url_for, redirect, send_file, Blueprint
|
from flask import jsonify, request, abort, url_for, redirect, send_file, Blueprint
|
||||||
|
|
||||||
|
|
@ -378,7 +383,8 @@ class TagsAPI(MicroscopeView):
|
||||||
|
|
||||||
|
|
||||||
def construct_blueprint(microscope_obj):
|
def construct_blueprint(microscope_obj):
|
||||||
blueprint = Blueprint("v2_captures_blueprint", __name__)
|
|
||||||
|
blueprint = blueprint_for_module(__name__)
|
||||||
|
|
||||||
# Tag routes
|
# Tag routes
|
||||||
blueprint.add_url_rule(
|
blueprint.add_url_rule(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
|
"""
|
||||||
|
Top-level representation of attached and enabled plugins
|
||||||
|
"""
|
||||||
|
|
||||||
from openflexure_microscope.plugins import PluginLoader, MicroscopePlugin
|
from openflexure_microscope.plugins import PluginLoader, MicroscopePlugin
|
||||||
from openflexure_microscope.api.views import MicroscopeViewPlugin
|
from openflexure_microscope.api.views import MicroscopeViewPlugin
|
||||||
from openflexure_microscope.utilities import get_docstring
|
from openflexure_microscope.utilities import get_docstring, description_from_view
|
||||||
|
from openflexure_microscope.api.utilities import blueprint_for_module
|
||||||
|
|
||||||
from flask import Blueprint, jsonify, url_for
|
from flask import Blueprint, jsonify, url_for
|
||||||
from openflexure_microscope.api.views import MicroscopeView
|
from openflexure_microscope.api.views import MicroscopeView
|
||||||
|
|
@ -9,7 +14,6 @@ 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
|
||||||
|
|
@ -28,7 +32,7 @@ def plugins_representation(plugin_loader_object: PluginLoader):
|
||||||
"python_name": plugin._name_python_safe,
|
"python_name": plugin._name_python_safe,
|
||||||
"plugin": str(plugin),
|
"plugin": str(plugin),
|
||||||
"views": {},
|
"views": {},
|
||||||
"form": plugin.form,
|
"gui": plugin.gui,
|
||||||
"description": get_docstring(plugin)
|
"description": get_docstring(plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -37,10 +41,11 @@ def plugins_representation(plugin_loader_object: PluginLoader):
|
||||||
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 = {
|
||||||
"description": get_docstring(view_data["view"]),
|
|
||||||
"links": {"self": uri}
|
"links": {"self": uri}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view_d.update(description_from_view(view_data["view"]))
|
||||||
|
|
||||||
d["views"][view_id] = view_d
|
d["views"][view_id] = view_d
|
||||||
|
|
||||||
plugins[plugin._name] = d
|
plugins[plugin._name] = d
|
||||||
|
|
@ -67,15 +72,13 @@ class PluginFormAPI(MicroscopeView):
|
||||||
|
|
||||||
def construct_blueprint(microscope_obj):
|
def construct_blueprint(microscope_obj):
|
||||||
|
|
||||||
blueprint = Blueprint("v2_plugins_blueprint", __name__)
|
blueprint = blueprint_for_module(__name__)
|
||||||
|
|
||||||
# Create a base route to return plugin API forms, if any exist
|
# Create a base route to return plugin API forms, if any exist
|
||||||
blueprint.add_url_rule(
|
blueprint.add_url_rule(
|
||||||
"/", view_func=PluginFormAPI.as_view("plugins", microscope=microscope_obj)
|
"/", view_func=PluginFormAPI.as_view("plugins", microscope=microscope_obj)
|
||||||
)
|
)
|
||||||
|
|
||||||
all_routes = []
|
|
||||||
|
|
||||||
# For each plugin attached to the microscope object
|
# For each plugin attached to the microscope object
|
||||||
for plugin in microscope_obj.plugins.active:
|
for plugin in microscope_obj.plugins.active:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,29 +2,29 @@ from flask import Blueprint, jsonify, url_for
|
||||||
from openflexure_microscope import Microscope
|
from openflexure_microscope import Microscope
|
||||||
from openflexure_microscope.api.views import MicroscopeView
|
from openflexure_microscope.api.views import MicroscopeView
|
||||||
|
|
||||||
def root_representation(microscope_obj: Microscope):
|
from openflexure_microscope.utilities import get_docstring, bottom_level_name
|
||||||
d = {
|
from openflexure_microscope.api.utilities import blueprint_name_for_module
|
||||||
"settings": {
|
from openflexure_microscope.api.v2.blueprints import settings, status, plugins, captures, actions, stream
|
||||||
"description": "Writeable settings for the microscope, and attached hardware",
|
|
||||||
"links": {"self": url_for("v2_settings_blueprint.settings")}
|
# List of submodules containing create_blueprint methods using standard blueprint_for_module naming
|
||||||
},
|
_root_blueprint_modules = [settings, status, plugins, captures, actions, stream]
|
||||||
"status": {
|
|
||||||
"description": "Read-only status of the microscope, and attached hardware info",
|
def root_representation():
|
||||||
"links": {"self": url_for("v2_status_blueprint.status")}
|
"""
|
||||||
},
|
Generate a dictionar representation of all top-level blueprint rules
|
||||||
"plugins": {
|
"""
|
||||||
"description": "Top-level representation of attached and enabled plugins",
|
global _root_blueprint_modules
|
||||||
"links": {"self": url_for("v2_plugins_blueprint.plugins")}
|
d = {}
|
||||||
},
|
|
||||||
"captures": {
|
for blueprint_module in _root_blueprint_modules:
|
||||||
"description": "Top-level representation of all acquired captures",
|
module_short_name = bottom_level_name(blueprint_module)
|
||||||
"links": {"self": url_for("v2_captures_blueprint.captures")}
|
blueprint_name = blueprint_name_for_module(blueprint_module.__name__)
|
||||||
},
|
|
||||||
"actions": {
|
d[module_short_name] = {
|
||||||
"description": "Top-level representation of enabled actions",
|
"name": blueprint_module.__name__,
|
||||||
"links": {"self": url_for("v2_actions_blueprint.actions")}
|
"description": get_docstring(blueprint_module),
|
||||||
},
|
"links": {"self": url_for(f"{blueprint_name}.{module_short_name}")}
|
||||||
}
|
}
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
|
@ -32,7 +32,7 @@ def root_representation(microscope_obj: Microscope):
|
||||||
class RootAPI(MicroscopeView):
|
class RootAPI(MicroscopeView):
|
||||||
def get(self):
|
def get(self):
|
||||||
|
|
||||||
return jsonify(root_representation(self.microscope))
|
return jsonify(root_representation())
|
||||||
|
|
||||||
|
|
||||||
def construct_blueprint(microscope_obj):
|
def construct_blueprint(microscope_obj):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
|
"""
|
||||||
|
Writeable settings for the microscope, and attached hardware
|
||||||
|
"""
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
from flask import Blueprint, jsonify, request
|
from flask import Blueprint, jsonify, request
|
||||||
import logging
|
import logging
|
||||||
|
|
@ -144,7 +149,7 @@ class SettingsAPI(MicroscopeView):
|
||||||
|
|
||||||
def construct_blueprint(microscope_obj):
|
def construct_blueprint(microscope_obj):
|
||||||
|
|
||||||
blueprint = Blueprint("v2_settings_blueprint", __name__)
|
blueprint = blueprint_for_module(__name__)
|
||||||
|
|
||||||
blueprint.add_url_rule(
|
blueprint.add_url_rule(
|
||||||
"/", view_func=SettingsAPI.as_view("settings", microscope=microscope_obj)
|
"/", view_func=SettingsAPI.as_view("settings", microscope=microscope_obj)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
|
"""
|
||||||
|
Read-only status of the microscope, and attached hardware info
|
||||||
|
"""
|
||||||
|
|
||||||
from openflexure_microscope.api.views import MicroscopeView
|
from openflexure_microscope.api.views import MicroscopeView
|
||||||
|
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):
|
||||||
"""
|
"""
|
||||||
|
|
@ -55,7 +59,7 @@ class StatusAPI(MicroscopeView):
|
||||||
|
|
||||||
def construct_blueprint(microscope_obj):
|
def construct_blueprint(microscope_obj):
|
||||||
|
|
||||||
blueprint = Blueprint("v2_status_blueprint", __name__)
|
blueprint = blueprint_for_module(__name__)
|
||||||
|
|
||||||
blueprint.add_url_rule(
|
blueprint.add_url_rule(
|
||||||
"/", view_func=StatusAPI.as_view("status", microscope=microscope_obj)
|
"/", view_func=StatusAPI.as_view("status", microscope=microscope_obj)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
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
|
||||||
|
|
||||||
from flask import Response, Blueprint, jsonify, request
|
from flask import Response, Blueprint, jsonify, request
|
||||||
|
|
||||||
|
|
@ -43,7 +44,7 @@ class SnapshotAPI(MicroscopeView):
|
||||||
|
|
||||||
def construct_blueprint(microscope_obj):
|
def construct_blueprint(microscope_obj):
|
||||||
|
|
||||||
blueprint = Blueprint("v2_stream_blueprint", __name__)
|
blueprint = blueprint_for_module(__name__)
|
||||||
|
|
||||||
blueprint.add_url_rule(
|
blueprint.add_url_rule(
|
||||||
"/stream", view_func=StreamAPI.as_view("stream", microscope=microscope_obj)
|
"/stream", view_func=StreamAPI.as_view("stream", microscope=microscope_obj)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +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):
|
||||||
|
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()
|
||||||
|
|
||||||
|
d = {
|
||||||
|
"methods": methods,
|
||||||
|
"description": brief_description
|
||||||
|
}
|
||||||
|
|
||||||
|
return d
|
||||||
|
|
||||||
def get_docstring(obj):
|
def get_docstring(obj):
|
||||||
ds = obj.__doc__
|
ds = obj.__doc__
|
||||||
if ds:
|
if ds:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue