Loading openflexure_microscope/api/v2/views/actions/camera.py +4 −2 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ from openflexure_microscope.common.flask_labthings.decorators import ( use_args, marshal_with, doc, tag, ltaction, doc_response, ) Loading @@ -17,7 +19,7 @@ import logging from flask import jsonify, request, abort, url_for, redirect, send_file @doc(tags=["actions"]) @ltaction class CaptureAPI(Resource): """ Create a new image capture. Loading @@ -42,7 +44,7 @@ class CaptureAPI(Resource): ) @marshal_with(capture_schema) @doc_response(200, description="Capture successful") @doc(tags=["foo"]) @tag("foo") def post(self, args): """ Create a new capture Loading openflexure_microscope/common/flask_labthings/decorators.py +27 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,18 @@ def marshal_task(f): return wrapper def ltaction(f): # Pass params to call function attribute for external access update_spec(f, {"tags": ["actions"]}) update_spec(f, {"_groups": ["actions"]}) return f def ltproperty(f): # Pass params to call function attribute for external access update_spec(f, {"tags": ["properties"]}) update_spec(f, {"_groups": ["properties"]}) return f class use_args(object): def __init__(self, schema, **kwargs): """ Loading Loading @@ -106,6 +118,21 @@ class doc(object): return f class tag(object): def __init__(self, tags): if isinstance(tags, str): self.tags = [tags] elif isinstance(tags, list) and all([isinstance(e, str) for e in tags]): self.tags = tags else: raise TypeError("Tags must be a string or list of strings") def __call__(self, f): # Pass params to call function attribute for external access update_spec(f, {"tags": self.tags}) return f class doc_response(object): def __init__(self, code, description=None, **kwargs): self.code = code Loading openflexure_microscope/common/flask_labthings/labthing.py +13 −24 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 from .spec import view2path, get_spec from .views.extensions import ExtensionList from .views.tasks import TaskList, TaskResource Loading Loading @@ -159,20 +159,12 @@ class LabThing(object): return "".join([part for part in parts if part]) def register_property(self, resource): if hasattr(resource, "endpoint"): self.properties[resource.endpoint] = resource else: raise RuntimeError( f"Resource {resource} has not yet been added. Cannot set as a property." ) logging.warning("register_property is deprecated. Use the @ltproperty class decorator instead.") pass def register_action(self, resource): if hasattr(resource, "endpoint"): self.actions[resource.endpoint] = resource else: raise RuntimeError( f"Resource {resource} has not yet been added. Cannot set as an action." ) logging.warning("register_action is deprecated. Use the @ltaction class decorator instead.") pass def add_resource(self, resource, *urls, endpoint=None, **kwargs): """Adds a resource to the api. Loading Loading @@ -208,17 +200,6 @@ class LabThing(object): self.resources.append((resource, urls, endpoint, kwargs)) def resource(self, *urls, **kwargs): """Wraps a :class:`~flask_restful.Resource` class, adding it to the api. Parameters are the same as :meth:`~flask_restful.Api.add_resource`. Example:: app = Flask(__name__) api = restful.Api(app) @api.resource('/foo') class Foo(Resource): def get(self): return 'Hello, World!' """ def decorator(cls): self.add_resource(cls, *urls, **kwargs) return cls Loading Loading @@ -255,6 +236,14 @@ class LabThing(object): # Add the resource to our API spec self.spec.path(**view2path(rule, resource, self.spec)) # Handle resource groups listed in API spec view_spec = get_spec(resource) view_groups = view_spec.get("_groups", {}) if "actions" in view_groups: self.actions[resource.endpoint] = resource if "properties" in view_groups: self.properties[resource.endpoint] = resource ### Utilities def url_for(self, resource, **values): Loading openflexure_microscope/common/flask_labthings/spec.py +3 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ def update_spec(obj, spec): rupdate(obj.__apispec__, spec) return obj.__apispec__ def get_spec(obj): obj.__apispec__ = obj.__dict__.get("__apispec__", {}) return obj.__apispec__ def view2path(rule: str, view: Resource, spec: APISpec): params = { Loading Loading
openflexure_microscope/api/v2/views/actions/camera.py +4 −2 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ from openflexure_microscope.common.flask_labthings.decorators import ( use_args, marshal_with, doc, tag, ltaction, doc_response, ) Loading @@ -17,7 +19,7 @@ import logging from flask import jsonify, request, abort, url_for, redirect, send_file @doc(tags=["actions"]) @ltaction class CaptureAPI(Resource): """ Create a new image capture. Loading @@ -42,7 +44,7 @@ class CaptureAPI(Resource): ) @marshal_with(capture_schema) @doc_response(200, description="Capture successful") @doc(tags=["foo"]) @tag("foo") def post(self, args): """ Create a new capture Loading
openflexure_microscope/common/flask_labthings/decorators.py +27 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,18 @@ def marshal_task(f): return wrapper def ltaction(f): # Pass params to call function attribute for external access update_spec(f, {"tags": ["actions"]}) update_spec(f, {"_groups": ["actions"]}) return f def ltproperty(f): # Pass params to call function attribute for external access update_spec(f, {"tags": ["properties"]}) update_spec(f, {"_groups": ["properties"]}) return f class use_args(object): def __init__(self, schema, **kwargs): """ Loading Loading @@ -106,6 +118,21 @@ class doc(object): return f class tag(object): def __init__(self, tags): if isinstance(tags, str): self.tags = [tags] elif isinstance(tags, list) and all([isinstance(e, str) for e in tags]): self.tags = tags else: raise TypeError("Tags must be a string or list of strings") def __call__(self, f): # Pass params to call function attribute for external access update_spec(f, {"tags": self.tags}) return f class doc_response(object): def __init__(self, code, description=None, **kwargs): self.code = code Loading
openflexure_microscope/common/flask_labthings/labthing.py +13 −24 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 from .spec import view2path, get_spec from .views.extensions import ExtensionList from .views.tasks import TaskList, TaskResource Loading Loading @@ -159,20 +159,12 @@ class LabThing(object): return "".join([part for part in parts if part]) def register_property(self, resource): if hasattr(resource, "endpoint"): self.properties[resource.endpoint] = resource else: raise RuntimeError( f"Resource {resource} has not yet been added. Cannot set as a property." ) logging.warning("register_property is deprecated. Use the @ltproperty class decorator instead.") pass def register_action(self, resource): if hasattr(resource, "endpoint"): self.actions[resource.endpoint] = resource else: raise RuntimeError( f"Resource {resource} has not yet been added. Cannot set as an action." ) logging.warning("register_action is deprecated. Use the @ltaction class decorator instead.") pass def add_resource(self, resource, *urls, endpoint=None, **kwargs): """Adds a resource to the api. Loading Loading @@ -208,17 +200,6 @@ class LabThing(object): self.resources.append((resource, urls, endpoint, kwargs)) def resource(self, *urls, **kwargs): """Wraps a :class:`~flask_restful.Resource` class, adding it to the api. Parameters are the same as :meth:`~flask_restful.Api.add_resource`. Example:: app = Flask(__name__) api = restful.Api(app) @api.resource('/foo') class Foo(Resource): def get(self): return 'Hello, World!' """ def decorator(cls): self.add_resource(cls, *urls, **kwargs) return cls Loading Loading @@ -255,6 +236,14 @@ class LabThing(object): # Add the resource to our API spec self.spec.path(**view2path(rule, resource, self.spec)) # Handle resource groups listed in API spec view_spec = get_spec(resource) view_groups = view_spec.get("_groups", {}) if "actions" in view_groups: self.actions[resource.endpoint] = resource if "properties" in view_groups: self.properties[resource.endpoint] = resource ### Utilities def url_for(self, resource, **values): Loading
openflexure_microscope/common/flask_labthings/spec.py +3 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,9 @@ def update_spec(obj, spec): rupdate(obj.__apispec__, spec) return obj.__apispec__ def get_spec(obj): obj.__apispec__ = obj.__dict__.get("__apispec__", {}) return obj.__apispec__ def view2path(rule: str, view: Resource, spec: APISpec): params = { Loading