Created @ltaction and @ltproperty decorators
This commit is contained in:
parent
d12fd3e02c
commit
3cbd0416d0
4 changed files with 47 additions and 26 deletions
|
|
@ -5,6 +5,8 @@ from openflexure_microscope.common.flask_labthings.decorators import (
|
||||||
use_args,
|
use_args,
|
||||||
marshal_with,
|
marshal_with,
|
||||||
doc,
|
doc,
|
||||||
|
tag,
|
||||||
|
ltaction,
|
||||||
doc_response,
|
doc_response,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -17,7 +19,7 @@ import logging
|
||||||
from flask import jsonify, request, abort, url_for, redirect, send_file
|
from flask import jsonify, request, abort, url_for, redirect, send_file
|
||||||
|
|
||||||
|
|
||||||
@doc(tags=["actions"])
|
@ltaction
|
||||||
class CaptureAPI(Resource):
|
class CaptureAPI(Resource):
|
||||||
"""
|
"""
|
||||||
Create a new image capture.
|
Create a new image capture.
|
||||||
|
|
@ -42,7 +44,7 @@ class CaptureAPI(Resource):
|
||||||
)
|
)
|
||||||
@marshal_with(capture_schema)
|
@marshal_with(capture_schema)
|
||||||
@doc_response(200, description="Capture successful")
|
@doc_response(200, description="Capture successful")
|
||||||
@doc(tags=["foo"])
|
@tag("foo")
|
||||||
def post(self, args):
|
def post(self, args):
|
||||||
"""
|
"""
|
||||||
Create a new capture
|
Create a new capture
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,18 @@ def marshal_task(f):
|
||||||
return wrapper
|
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):
|
class use_args(object):
|
||||||
def __init__(self, schema, **kwargs):
|
def __init__(self, schema, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
@ -106,6 +118,21 @@ class doc(object):
|
||||||
return f
|
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):
|
class doc_response(object):
|
||||||
def __init__(self, code, description=None, **kwargs):
|
def __init__(self, code, description=None, **kwargs):
|
||||||
self.code = code
|
self.code = code
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from . import EXTENSION_NAME # TODO: Move into .names
|
||||||
from .names import TASK_ENDPOINT, TASK_LIST_ENDPOINT, EXTENSION_LIST_ENDPOINT
|
from .names import TASK_ENDPOINT, TASK_LIST_ENDPOINT, EXTENSION_LIST_ENDPOINT
|
||||||
from .extensions import BaseExtension
|
from .extensions import BaseExtension
|
||||||
from .utilities import description_from_view
|
from .utilities import description_from_view
|
||||||
from .spec import view2path
|
from .spec import view2path, get_spec
|
||||||
|
|
||||||
from .views.extensions import ExtensionList
|
from .views.extensions import ExtensionList
|
||||||
from .views.tasks import TaskList, TaskResource
|
from .views.tasks import TaskList, TaskResource
|
||||||
|
|
@ -159,20 +159,12 @@ class LabThing(object):
|
||||||
return "".join([part for part in parts if part])
|
return "".join([part for part in parts if part])
|
||||||
|
|
||||||
def register_property(self, resource):
|
def register_property(self, resource):
|
||||||
if hasattr(resource, "endpoint"):
|
logging.warning("register_property is deprecated. Use the @ltproperty class decorator instead.")
|
||||||
self.properties[resource.endpoint] = resource
|
pass
|
||||||
else:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Resource {resource} has not yet been added. Cannot set as a property."
|
|
||||||
)
|
|
||||||
|
|
||||||
def register_action(self, resource):
|
def register_action(self, resource):
|
||||||
if hasattr(resource, "endpoint"):
|
logging.warning("register_action is deprecated. Use the @ltaction class decorator instead.")
|
||||||
self.actions[resource.endpoint] = resource
|
pass
|
||||||
else:
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Resource {resource} has not yet been added. Cannot set as an action."
|
|
||||||
)
|
|
||||||
|
|
||||||
def add_resource(self, resource, *urls, endpoint=None, **kwargs):
|
def add_resource(self, resource, *urls, endpoint=None, **kwargs):
|
||||||
"""Adds a resource to the api.
|
"""Adds a resource to the api.
|
||||||
|
|
@ -208,17 +200,6 @@ class LabThing(object):
|
||||||
self.resources.append((resource, urls, endpoint, kwargs))
|
self.resources.append((resource, urls, endpoint, kwargs))
|
||||||
|
|
||||||
def resource(self, *urls, **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):
|
def decorator(cls):
|
||||||
self.add_resource(cls, *urls, **kwargs)
|
self.add_resource(cls, *urls, **kwargs)
|
||||||
return cls
|
return cls
|
||||||
|
|
@ -255,6 +236,14 @@ class LabThing(object):
|
||||||
# Add the resource to our API spec
|
# Add the resource to our API spec
|
||||||
self.spec.path(**view2path(rule, resource, self.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
|
### Utilities
|
||||||
|
|
||||||
def url_for(self, resource, **values):
|
def url_for(self, resource, **values):
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ def update_spec(obj, spec):
|
||||||
rupdate(obj.__apispec__, spec)
|
rupdate(obj.__apispec__, spec)
|
||||||
return obj.__apispec__
|
return obj.__apispec__
|
||||||
|
|
||||||
|
def get_spec(obj):
|
||||||
|
obj.__apispec__ = obj.__dict__.get("__apispec__", {})
|
||||||
|
return obj.__apispec__
|
||||||
|
|
||||||
def view2path(rule: str, view: Resource, spec: APISpec):
|
def view2path(rule: str, view: Resource, spec: APISpec):
|
||||||
params = {
|
params = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue