openapi: Add markdown extension for response descriptions.

As a goal of a common template, there
is a need for a tool to auto-generate
general description for all responses
directly from OpenAPI data.

This description is to be stored in
x-response-description field, and this
commit adds a markdown extesion to process the same.
This commit is contained in:
Suyash Vardhan Mathur 2021-06-22 01:26:18 +05:30 committed by Tim Abbott
parent 226ac4bd3b
commit dbcffebf2c
2 changed files with 51 additions and 0 deletions

View File

@ -24,6 +24,7 @@ from zerver.openapi.openapi import (
get_curl_include_exclude,
get_openapi_description,
get_openapi_summary,
get_responses_description,
openapi_spec,
)
@ -34,6 +35,7 @@ PYTHON_EXAMPLE_REGEX = re.compile(r"\# \{code_example\|\s*(.+?)\s*\}")
JS_EXAMPLE_REGEX = re.compile(r"\/\/ \{code_example\|\s*(.+?)\s*\}")
MACRO_REGEXP_DESC = re.compile(r"\{generate_api_description(\(\s*(.+?)\s*\))}")
MACRO_REGEXP_TITLE = re.compile(r"\{generate_api_title(\(\s*(.+?)\s*\))}")
MACRO_REGEXP_RESPONSE_DESC = re.compile(r"\{generate_response_description(\(\s*(.+?)\s*\))}")
PYTHON_CLIENT_CONFIG = """
#!/usr/bin/env python3
@ -407,6 +409,11 @@ class APIMarkdownExtension(Extension):
md.preprocessors.register(
APITitlePreprocessor(md, self.getConfigs()), "generate_api_title", 531
)
md.preprocessors.register(
ResponseDescriptionPreprocessor(md, self.getConfigs()),
"generate_response_description",
531,
)
class APICodeExamplesPreprocessor(Preprocessor):
@ -541,5 +548,42 @@ class APITitlePreprocessor(Preprocessor):
return title
class ResponseDescriptionPreprocessor(Preprocessor):
def __init__(self, md: markdown.Markdown, config: Mapping[str, Any]) -> None:
super().__init__(md)
self.api_url = config["api_url"]
def run(self, lines: List[str]) -> List[str]:
done = False
while not done:
for line in lines:
loc = lines.index(line)
match = MACRO_REGEXP_RESPONSE_DESC.search(line)
if match:
function = match.group(2)
text = self.render_responses_description(function)
# The line that contains the directive to include the macro
# may be preceded or followed by text or tags, in that case
# we need to make sure that any preceding or following text
# stays the same.
line_split = MACRO_REGEXP_RESPONSE_DESC.split(line, maxsplit=0)
preceding = line_split[0]
following = line_split[-1]
text = [preceding, *text, following]
lines = lines[:loc] + text + lines[loc + 1 :]
break
else:
done = True
return lines
def render_responses_description(self, function: str) -> List[str]:
description: List[str] = []
path, method = function.rsplit(":", 1)
raw_description = get_responses_description(path, method)
description.extend(raw_description.splitlines())
return description
def makeExtension(*args: Any, **kwargs: str) -> APIMarkdownExtension:
return APIMarkdownExtension(*args, **kwargs)

View File

@ -233,6 +233,13 @@ def check_requires_administrator(endpoint: str, method: str) -> bool:
)
def get_responses_description(endpoint: str, method: str) -> str:
"""Fetch responses description of an endpoint."""
return openapi_spec.openapi()["paths"][endpoint][method.lower()].get(
"x-response-description", ""
)
def generate_openapi_fixture(endpoint: str, method: str, status_code: str = "200") -> List[str]:
"""Generate fixture to be rendered"""
fixture = []