Loading openflexure_microscope/api/v2/views/captures.py +36 −25 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ from openflexure_microscope.common.flask_labthings.resource import Resource from openflexure_microscope.common.flask_labthings.utilities import ( description_from_view, ) from openflexure_microscope.common.flask_labthings.decorators import marshal_with from openflexure_microscope.common.flask_labthings.decorators import marshal_with, doc_response, Tag, ThingProperty from openflexure_microscope.common.flask_labthings.find import find_component Loading Loading @@ -64,25 +64,26 @@ capture_schema = CaptureSchema() capture_list_schema = CaptureSchema(many=True) @ThingProperty @Tag("captures") class CaptureList(Resource): @marshal_with(CaptureSchema(many=True)) def get(self): """ List all image captures """ @marshal_with(CaptureSchema(many=True)) def get(self): microscope = find_component("org.openflexure.microscope") image_list = microscope.camera.images return image_list @Tag("captures") class CaptureResource(Resource): @marshal_with(CaptureSchema()) def get(self, id): """ Description of a single image capture """ @marshal_with(CaptureSchema()) def get(self, id): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -92,6 +93,9 @@ class CaptureResource(Resource): return capture_obj def delete(self, id): """ Delete a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -103,13 +107,13 @@ class CaptureResource(Resource): return "", 204 @Tag("captures") class CaptureDownload(Resource): @doc_response(200, mimetype="image/jpeg") def get(self, id, filename): """ Image data for a single image capture """ def get(self, id, filename): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading Loading @@ -139,13 +143,12 @@ class CaptureDownload(Resource): return send_file(img, mimetype="image/jpeg") @Tag("captures") class CaptureTags(Resource): def get(self, id): """ Tags associated with a single image capture Get tags associated with a single image capture """ def get(self, id): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -155,13 +158,16 @@ class CaptureTags(Resource): return jsonify(capture_obj.tags) def put(self, id): """ Add tags to a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) if not capture_obj: return abort(404) # 404 Not Found # TODO: Replace with normal Flask request JSON thing data_dict = JsonResponse(request).json if type(data_dict) != list: Loading @@ -172,7 +178,9 @@ class CaptureTags(Resource): return jsonify(capture_obj.tags) def delete(self, capture_id): """ Delete tags from a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -190,12 +198,12 @@ class CaptureTags(Resource): return jsonify(capture_obj.tags) @Tag("captures") class CaptureMetadata(Resource): def get(self, id): """ All metadata associated with a single image capture Get metadata associated with a single image capture """ def get(self, id): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -205,6 +213,9 @@ class CaptureMetadata(Resource): return jsonify(capture_obj.metadata) def put(self, id): """ Update metadata for a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading openflexure_microscope/api/v2/views/state.py +12 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ from openflexure_microscope.common.labthings_core.utilities import ( from openflexure_microscope.common.flask_labthings.find import find_component from openflexure_microscope.common.flask_labthings.resource import Resource from openflexure_microscope.common.flask_labthings.decorators import ThingProperty, marshal_with from openflexure_microscope.common.flask_labthings.decorators import ThingProperty, Tag from flask import jsonify, request, abort import logging Loading Loading @@ -40,8 +40,12 @@ class SettingsProperty(Resource): return self.get() @Tag("properties") class NestedSettingsProperty(Resource): def get(self, route): """ Show a nested section of the current microscope settings """ microscope = find_component("org.openflexure.microscope") keys = route.split("/") Loading @@ -53,6 +57,9 @@ class NestedSettingsProperty(Resource): return jsonify(value) def put(self, route): """ Update a nested section of the current microscope settings """ microscope = find_component("org.openflexure.microscope") keys = route.split("/") payload = JsonResponse(request) Loading @@ -76,8 +83,12 @@ class StatusProperty(Resource): return jsonify(microscope.status) @Tag("properties") class NestedStatusProperty(Resource): def get(self, route): """ Show a nested section of the current microscope state """ microscope = find_component("org.openflexure.microscope") keys = route.split("/") Loading openflexure_microscope/api/v2/views/streams.py +1 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ from openflexure_microscope.common.flask_labthings.decorators import doc_respons from flask import Response @ThingProperty class MjpegStream(Resource): """ Loading openflexure_microscope/common/flask_labthings/labthing.py +15 −10 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ from . import EXTENSION_NAME # TODO: Move into .names from .names import TASK_ENDPOINT, TASK_LIST_ENDPOINT, EXTENSION_LIST_ENDPOINT from .extensions import BaseExtension from .utilities import description_from_view from .spec import view2path, get_spec from .spec import rule2path, get_spec from .views.extensions import ExtensionList from .views.tasks import TaskList, TaskResource Loading Loading @@ -188,8 +188,8 @@ class LabThing(object): return decorator def _register_view(self, app, resource, *urls, endpoint=None, **kwargs): endpoint = endpoint or resource.__name__.lower() def _register_view(self, app, view, *urls, endpoint=None, **kwargs): endpoint = endpoint or view.__name__.lower() self.endpoints.add(endpoint) resource_class_args = kwargs.pop("resource_class_args", ()) resource_class_kwargs = kwargs.pop("resource_class_kwargs", {}) Loading @@ -199,14 +199,14 @@ class LabThing(object): previous_view_class = app.view_functions[endpoint].__dict__["view_class"] # if you override the endpoint with a different class, avoid the collision by raising an exception if previous_view_class != resource: if previous_view_class != view: raise ValueError( "This endpoint (%s) is already set to the class %s." % (endpoint, previous_view_class.__name__) ) resource.endpoint = endpoint resource_func = resource.as_view( view.endpoint = endpoint resource_func = view.as_view( endpoint, *resource_class_args, **resource_class_kwargs ) Loading @@ -216,15 +216,20 @@ class LabThing(object): # Add the url to the application or blueprint app.add_url_rule(rule, view_func=resource_func, **kwargs) # Add the resource to our API spec self.spec.path(**view2path(rule, resource, self.spec)) #self.spec.path(**view2path(rule, view, self.spec)) # TEST: Getting Flask rule objects flask_rules = app.url_map._rules_by_endpoint.get(endpoint) for flask_rule in flask_rules: self.spec.path(**rule2path(flask_rule, view, self.spec)) # Handle resource groups listed in API spec view_spec = get_spec(resource) view_spec = get_spec(view) view_groups = view_spec.get("_groups", {}) if "actions" in view_groups: self.actions[resource.endpoint] = resource self.actions[view.endpoint] = view if "properties" in view_groups: self.properties[resource.endpoint] = resource self.properties[view.endpoint] = view ### Utilities Loading openflexure_microscope/common/flask_labthings/spec.py→openflexure_microscope/common/flask_labthings/spec/__init__.py +15 −4 Original line number Diff line number Diff line from .resource import Resource from ..resource import Resource from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin Loading @@ -8,9 +8,12 @@ from openflexure_microscope.common.labthings_core.utilities import ( rupdate, ) from .fields import Field from ..fields import Field from marshmallow import Schema as BaseSchema from .paths import rule_to_path, rule_to_params from werkzeug.routing import Rule from collections import Mapping from http import HTTPStatus Loading @@ -26,14 +29,22 @@ def get_spec(obj): return obj.__apispec__ def view2path(rule: str, view: Resource, spec: APISpec): def rule2path(rule: Rule, view: Resource, spec: APISpec): params = { "path": rule, # TODO: Validate this slightly (leading / etc) "path": rule_to_path(rule), "operations": view2operations(view, spec), "description": get_docstring(view), "summary": get_summary(view), } # Add URL arguments if rule.arguments: for op in params.get("operations").keys(): params["operations"][op].update({ "parameters": rule_to_params(rule) }) # Add extra parameters if hasattr(view, "__apispec__"): # Recursively update params rupdate(params, view.__apispec__) Loading Loading
openflexure_microscope/api/v2/views/captures.py +36 −25 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ from openflexure_microscope.common.flask_labthings.resource import Resource from openflexure_microscope.common.flask_labthings.utilities import ( description_from_view, ) from openflexure_microscope.common.flask_labthings.decorators import marshal_with from openflexure_microscope.common.flask_labthings.decorators import marshal_with, doc_response, Tag, ThingProperty from openflexure_microscope.common.flask_labthings.find import find_component Loading Loading @@ -64,25 +64,26 @@ capture_schema = CaptureSchema() capture_list_schema = CaptureSchema(many=True) @ThingProperty @Tag("captures") class CaptureList(Resource): @marshal_with(CaptureSchema(many=True)) def get(self): """ List all image captures """ @marshal_with(CaptureSchema(many=True)) def get(self): microscope = find_component("org.openflexure.microscope") image_list = microscope.camera.images return image_list @Tag("captures") class CaptureResource(Resource): @marshal_with(CaptureSchema()) def get(self, id): """ Description of a single image capture """ @marshal_with(CaptureSchema()) def get(self, id): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -92,6 +93,9 @@ class CaptureResource(Resource): return capture_obj def delete(self, id): """ Delete a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -103,13 +107,13 @@ class CaptureResource(Resource): return "", 204 @Tag("captures") class CaptureDownload(Resource): @doc_response(200, mimetype="image/jpeg") def get(self, id, filename): """ Image data for a single image capture """ def get(self, id, filename): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading Loading @@ -139,13 +143,12 @@ class CaptureDownload(Resource): return send_file(img, mimetype="image/jpeg") @Tag("captures") class CaptureTags(Resource): def get(self, id): """ Tags associated with a single image capture Get tags associated with a single image capture """ def get(self, id): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -155,13 +158,16 @@ class CaptureTags(Resource): return jsonify(capture_obj.tags) def put(self, id): """ Add tags to a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) if not capture_obj: return abort(404) # 404 Not Found # TODO: Replace with normal Flask request JSON thing data_dict = JsonResponse(request).json if type(data_dict) != list: Loading @@ -172,7 +178,9 @@ class CaptureTags(Resource): return jsonify(capture_obj.tags) def delete(self, capture_id): """ Delete tags from a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -190,12 +198,12 @@ class CaptureTags(Resource): return jsonify(capture_obj.tags) @Tag("captures") class CaptureMetadata(Resource): def get(self, id): """ All metadata associated with a single image capture Get metadata associated with a single image capture """ def get(self, id): microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading @@ -205,6 +213,9 @@ class CaptureMetadata(Resource): return jsonify(capture_obj.metadata) def put(self, id): """ Update metadata for a single image capture """ microscope = find_component("org.openflexure.microscope") capture_obj = microscope.camera.image_from_id(id) Loading
openflexure_microscope/api/v2/views/state.py +12 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ from openflexure_microscope.common.labthings_core.utilities import ( from openflexure_microscope.common.flask_labthings.find import find_component from openflexure_microscope.common.flask_labthings.resource import Resource from openflexure_microscope.common.flask_labthings.decorators import ThingProperty, marshal_with from openflexure_microscope.common.flask_labthings.decorators import ThingProperty, Tag from flask import jsonify, request, abort import logging Loading Loading @@ -40,8 +40,12 @@ class SettingsProperty(Resource): return self.get() @Tag("properties") class NestedSettingsProperty(Resource): def get(self, route): """ Show a nested section of the current microscope settings """ microscope = find_component("org.openflexure.microscope") keys = route.split("/") Loading @@ -53,6 +57,9 @@ class NestedSettingsProperty(Resource): return jsonify(value) def put(self, route): """ Update a nested section of the current microscope settings """ microscope = find_component("org.openflexure.microscope") keys = route.split("/") payload = JsonResponse(request) Loading @@ -76,8 +83,12 @@ class StatusProperty(Resource): return jsonify(microscope.status) @Tag("properties") class NestedStatusProperty(Resource): def get(self, route): """ Show a nested section of the current microscope state """ microscope = find_component("org.openflexure.microscope") keys = route.split("/") Loading
openflexure_microscope/api/v2/views/streams.py +1 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,7 @@ from openflexure_microscope.common.flask_labthings.decorators import doc_respons from flask import Response @ThingProperty class MjpegStream(Resource): """ Loading
openflexure_microscope/common/flask_labthings/labthing.py +15 −10 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ from . import EXTENSION_NAME # TODO: Move into .names from .names import TASK_ENDPOINT, TASK_LIST_ENDPOINT, EXTENSION_LIST_ENDPOINT from .extensions import BaseExtension from .utilities import description_from_view from .spec import view2path, get_spec from .spec import rule2path, get_spec from .views.extensions import ExtensionList from .views.tasks import TaskList, TaskResource Loading Loading @@ -188,8 +188,8 @@ class LabThing(object): return decorator def _register_view(self, app, resource, *urls, endpoint=None, **kwargs): endpoint = endpoint or resource.__name__.lower() def _register_view(self, app, view, *urls, endpoint=None, **kwargs): endpoint = endpoint or view.__name__.lower() self.endpoints.add(endpoint) resource_class_args = kwargs.pop("resource_class_args", ()) resource_class_kwargs = kwargs.pop("resource_class_kwargs", {}) Loading @@ -199,14 +199,14 @@ class LabThing(object): previous_view_class = app.view_functions[endpoint].__dict__["view_class"] # if you override the endpoint with a different class, avoid the collision by raising an exception if previous_view_class != resource: if previous_view_class != view: raise ValueError( "This endpoint (%s) is already set to the class %s." % (endpoint, previous_view_class.__name__) ) resource.endpoint = endpoint resource_func = resource.as_view( view.endpoint = endpoint resource_func = view.as_view( endpoint, *resource_class_args, **resource_class_kwargs ) Loading @@ -216,15 +216,20 @@ class LabThing(object): # Add the url to the application or blueprint app.add_url_rule(rule, view_func=resource_func, **kwargs) # Add the resource to our API spec self.spec.path(**view2path(rule, resource, self.spec)) #self.spec.path(**view2path(rule, view, self.spec)) # TEST: Getting Flask rule objects flask_rules = app.url_map._rules_by_endpoint.get(endpoint) for flask_rule in flask_rules: self.spec.path(**rule2path(flask_rule, view, self.spec)) # Handle resource groups listed in API spec view_spec = get_spec(resource) view_spec = get_spec(view) view_groups = view_spec.get("_groups", {}) if "actions" in view_groups: self.actions[resource.endpoint] = resource self.actions[view.endpoint] = view if "properties" in view_groups: self.properties[resource.endpoint] = resource self.properties[view.endpoint] = view ### Utilities Loading
openflexure_microscope/common/flask_labthings/spec.py→openflexure_microscope/common/flask_labthings/spec/__init__.py +15 −4 Original line number Diff line number Diff line from .resource import Resource from ..resource import Resource from apispec import APISpec from apispec.ext.marshmallow import MarshmallowPlugin Loading @@ -8,9 +8,12 @@ from openflexure_microscope.common.labthings_core.utilities import ( rupdate, ) from .fields import Field from ..fields import Field from marshmallow import Schema as BaseSchema from .paths import rule_to_path, rule_to_params from werkzeug.routing import Rule from collections import Mapping from http import HTTPStatus Loading @@ -26,14 +29,22 @@ def get_spec(obj): return obj.__apispec__ def view2path(rule: str, view: Resource, spec: APISpec): def rule2path(rule: Rule, view: Resource, spec: APISpec): params = { "path": rule, # TODO: Validate this slightly (leading / etc) "path": rule_to_path(rule), "operations": view2operations(view, spec), "description": get_docstring(view), "summary": get_summary(view), } # Add URL arguments if rule.arguments: for op in params.get("operations").keys(): params["operations"][op].update({ "parameters": rule_to_params(rule) }) # Add extra parameters if hasattr(view, "__apispec__"): # Recursively update params rupdate(params, view.__apispec__) Loading