Fixed automatic Swagger from docstrings
This commit is contained in:
parent
4918215ea7
commit
5bdb6764be
5 changed files with 42 additions and 22 deletions
|
|
@ -30,6 +30,9 @@ class CaptureAPI(Resource):
|
||||||
@marshal_with(capture_schema)
|
@marshal_with(capture_schema)
|
||||||
@doc_response(200, "Capture successful")
|
@doc_response(200, "Capture successful")
|
||||||
def post(self, args):
|
def post(self, args):
|
||||||
|
"""
|
||||||
|
Create a new capture
|
||||||
|
"""
|
||||||
microscope = find_device("openflexure_microscope")
|
microscope = find_device("openflexure_microscope")
|
||||||
|
|
||||||
resize = args.get("resize", None)
|
resize = args.get("resize", None)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class MjpegStream(Resource):
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
"""
|
"""
|
||||||
Real-time MJPEG stream from the microscope camera
|
MJPEG stream from the microscope camera
|
||||||
"""
|
"""
|
||||||
microscope = find_device("openflexure_microscope")
|
microscope = find_device("openflexure_microscope")
|
||||||
# Restart stream worker thread
|
# Restart stream worker thread
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from .utilities import rupdate
|
||||||
from apispec import APISpec
|
from apispec import APISpec
|
||||||
from apispec.ext.marshmallow import MarshmallowPlugin
|
from apispec.ext.marshmallow import MarshmallowPlugin
|
||||||
|
|
||||||
from openflexure_microscope.common.labthings_core.utilities import get_docstring
|
from openflexure_microscope.common.labthings_core.utilities import get_docstring, get_summary
|
||||||
|
|
||||||
from .fields import Field
|
from .fields import Field
|
||||||
from marshmallow import Schema as BaseSchema
|
from marshmallow import Schema as BaseSchema
|
||||||
|
|
@ -16,7 +16,7 @@ def view2path(rule: str, view: Resource, spec: APISpec):
|
||||||
"path": rule, # TODO: Validate this slightly (leading / etc)
|
"path": rule, # TODO: Validate this slightly (leading / etc)
|
||||||
"operations": view2operations(view, spec),
|
"operations": view2operations(view, spec),
|
||||||
"description": get_docstring(view),
|
"description": get_docstring(view),
|
||||||
"summary": get_docstring(view).partition("\n")[0].strip()
|
"summary": get_summary(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasattr(view, "__apispec__"):
|
if hasattr(view, "__apispec__"):
|
||||||
|
|
@ -29,20 +29,28 @@ def view2operations(view: Resource, spec: APISpec, populate_default: bool = True
|
||||||
ops = {}
|
ops = {}
|
||||||
for method in Resource.methods:
|
for method in Resource.methods:
|
||||||
if hasattr(view, method):
|
if hasattr(view, method):
|
||||||
|
# Populate with default responses
|
||||||
if populate_default:
|
if populate_default:
|
||||||
ops[method] = {
|
ops[method] = {
|
||||||
"responses": {
|
"responses": {
|
||||||
200: {
|
200: {
|
||||||
"description": "success"
|
"description": get_summary(getattr(view, method)) or "Success"
|
||||||
|
},
|
||||||
|
404: {
|
||||||
|
"description": "Resource not found"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
ops[method] = {}
|
ops[method] = {}
|
||||||
|
|
||||||
|
rupdate(ops[method], {
|
||||||
|
"description": get_docstring(getattr(view, method)),
|
||||||
|
"summary": get_summary(getattr(view, method))
|
||||||
|
})
|
||||||
|
|
||||||
if hasattr(getattr(view, method), "__apispec__"):
|
if hasattr(getattr(view, method), "__apispec__"):
|
||||||
ops[method] = doc2operation(getattr(view, method).__apispec__, spec)
|
rupdate(ops[method], doc2operation(getattr(view, method).__apispec__, spec))
|
||||||
|
|
||||||
return ops
|
return ops
|
||||||
|
|
||||||
|
|
@ -50,25 +58,29 @@ def view2operations(view: Resource, spec: APISpec, populate_default: bool = True
|
||||||
def doc2operation(apispec: dict, spec: APISpec):
|
def doc2operation(apispec: dict, spec: APISpec):
|
||||||
op = {}
|
op = {}
|
||||||
if "_params" in apispec:
|
if "_params" in apispec:
|
||||||
op["requestBody"] = {
|
rupdate(op, {
|
||||||
"content": {
|
"requestBody": {
|
||||||
"application/json": {
|
|
||||||
"schema": convert_schema(apispec.get("_params"), spec)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if "_schema" in apispec:
|
|
||||||
op["responses"] = {
|
|
||||||
200: {
|
|
||||||
"description": "success",
|
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": convert_schema(apispec.get("_schema"), spec)
|
"schema": convert_schema(apispec.get("_params"), spec)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
|
if "_schema" in apispec:
|
||||||
|
rupdate(op,
|
||||||
|
{
|
||||||
|
"responses": {
|
||||||
|
200: {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": convert_schema(apispec.get("_schema"), spec)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
for key, val in apispec.items():
|
for key, val in apispec.items():
|
||||||
if not key in ["_params", "_schema"]:
|
if not key in ["_params", "_schema"]:
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ def description_from_view(view_class):
|
||||||
def rupdate(d, u):
|
def rupdate(d, u):
|
||||||
for k, v in u.items():
|
for k, v in u.items():
|
||||||
if isinstance(v, collections.abc.Mapping):
|
if isinstance(v, collections.abc.Mapping):
|
||||||
|
if not k in d:
|
||||||
|
d[k] = {}
|
||||||
d[k] = rupdate(d.get(k, {}), v)
|
d[k] = rupdate(d.get(k, {}), v)
|
||||||
else:
|
else:
|
||||||
d[k] = v
|
d[k] = v
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,6 @@ def get_docstring(obj):
|
||||||
return ds.strip()
|
return ds.strip()
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def get_summary(obj):
|
||||||
|
return get_docstring(obj).partition("\n")[0].strip()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue