# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
import logging
-from typing import Any, Dict, List, Union
+from typing import Any, Dict, List, Optional, Union
import cherrypy
-from .. import DEFAULT_VERSION, mgr
+from .. import mgr
from ..api.doc import Schema, SchemaInput, SchemaType
-from . import ENDPOINT_MAP, BaseController, Controller, Endpoint
+from . import ENDPOINT_MAP, BaseController, Endpoint, Router
+from ._version import APIVersion
NO_DESCRIPTION_AVAILABLE = "*No description available*"
logger = logging.getLogger('controllers.docs')
-@Controller('/docs', secure=False)
+@Router('/docs', secure=False)
class Docs(BaseController):
@classmethod
list_of_ctrl.add(endpoint.ctrl)
tag_map: Dict[str, str] = {}
- for ctrl in list_of_ctrl:
+ for ctrl in sorted(list_of_ctrl, key=lambda ctrl: ctrl.__name__):
tag_name = ctrl.__name__
tag_descr = ""
if hasattr(ctrl, 'doc_info'):
return schema.as_dict()
@classmethod
- def _gen_responses(cls, method, resp_object=None, version=None):
+ def _gen_responses(cls, method, resp_object=None,
+ version: Optional[APIVersion] = None):
resp: Dict[str, Dict[str, Union[str, Any]]] = {
'400': {
"description": "Operation exception. Please check the "
}
if not version:
- version = DEFAULT_VERSION
+ version = APIVersion.DEFAULT
if method.lower() == 'get':
resp['200'] = {'description': "OK",
- 'content': {'application/vnd.ceph.api.v{}+json'.format(version):
+ 'content': {version.to_mime_type():
{'type': 'object'}}}
if method.lower() == 'post':
resp['201'] = {'description': "Resource created.",
- 'content': {'application/vnd.ceph.api.v{}+json'.format(version):
+ 'content': {version.to_mime_type():
{'type': 'object'}}}
if method.lower() == 'put':
resp['200'] = {'description': "Resource updated.",
- 'content': {'application/vnd.ceph.api.v{}+json'.format(version):
+ 'content': {version.to_mime_type():
{'type': 'object'}}}
if method.lower() == 'delete':
resp['204'] = {'description': "Resource deleted.",
- 'content': {'application/vnd.ceph.api.v{}+json'.format(version):
+ 'content': {version.to_mime_type():
{'type': 'object'}}}
if method.lower() in ['post', 'put', 'delete']:
resp['202'] = {'description': "Operation is still executing."
" Please check the task queue.",
- 'content': {'application/vnd.ceph.api.v{}+json'.format(version):
+ 'content': {version.to_mime_type():
{'type': 'object'}}}
if resp_object:
for status_code, response_body in resp_object.items():
if status_code in resp:
- resp[status_code].update({
- 'content': {
- 'application/vnd.ceph.api.v{}+json'.format(version): {
- 'schema': cls._gen_schema_for_content(response_body)}}})
+ resp[status_code].update(
+ {'content':
+ {version.to_mime_type():
+ {'schema': cls._gen_schema_for_content(response_body)}
+ }})
return resp
func = endpoint.func
summary = ''
- version = ''
+ version = None
resp = {}
p_info = []
return spec
- @Endpoint(path="api.json", version=None)
- def api_json(self):
+ @Endpoint(path="openapi.json", version=None)
+ def open_api_json(self):
return self._gen_spec(False, "/")
@Endpoint(path="api-all.json", version=None)
def api_all_json(self):
return self._gen_spec(True, "/")
- def _swagger_ui_page(self, all_endpoints=False):
- base = cherrypy.request.base
- if all_endpoints:
- spec_url = "{}/docs/api-all.json".format(base)
- else:
- spec_url = "{}/docs/api.json".format(base)
-
- page = """
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <meta name="referrer" content="no-referrer" />
- <link rel="stylesheet" type="text/css"
- href="/swagger-ui.css" >
- <style>
- html
- {{
- box-sizing: border-box;
- overflow: -moz-scrollbars-vertical;
- overflow-y: scroll;
- }}
- *,
- *:before,
- *:after
- {{
- box-sizing: inherit;
- }}
- body {{
- margin:0;
- background: #fafafa;
- }}
- </style>
- </head>
- <body>
- <div id="swagger-ui"></div>
- <script src="/swagger-ui-bundle.js">
- </script>
- <script>
- window.onload = function() {{
- const ui = SwaggerUIBundle({{
- url: '{}',
- dom_id: '#swagger-ui',
- presets: [
- SwaggerUIBundle.presets.apis
- ],
- layout: "BaseLayout"
- }})
- window.ui = ui
- }}
- </script>
- </body>
- </html>
- """.format(spec_url)
-
- return page
-
- @Endpoint(json_response=False, version=None)
- def __call__(self, all_endpoints=False):
- return self._swagger_ui_page(all_endpoints)
-
if __name__ == "__main__":
import sys
import yaml
- from . import generate_routes
-
def fix_null_descr(obj):
"""
A hot fix for errors caused by null description values when generating
return {k: fix_null_descr(v) for k, v in obj.items() if v is not None} \
if isinstance(obj, dict) else obj
- generate_routes("/api")
+ Router.generate_routes("/api")
try:
with open(sys.argv[1], 'w') as f:
# pylint: disable=protected-access