Commit 3cbd0416 authored by Joel Collins's avatar Joel Collins
Browse files

Created @ltaction and @ltproperty decorators

parent d12fd3e0
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ from openflexure_microscope.common.flask_labthings.decorators import (
    use_args,
    marshal_with,
    doc,
    tag,
    ltaction,
    doc_response,
)

@@ -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. 
@@ -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
+27 −0
Original line number Diff line number Diff line
@@ -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):
        """
@@ -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
+13 −24
Original line number Diff line number Diff line
@@ -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
@@ -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.
@@ -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
@@ -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):
+3 −0
Original line number Diff line number Diff line
@@ -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 = {