Skip to content

Commit

Permalink
api_docs: Fix missing content from API documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vector73 committed Jun 20, 2024
1 parent ee2852e commit 46331db
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 24 deletions.
60 changes: 53 additions & 7 deletions zerver/lib/markdown/api_arguments_table_generator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import re
from typing import Any, List, Mapping, Sequence
from typing import Any, Dict, List, Mapping, Sequence

import markdown
from django.utils.html import escape as escape_html
Expand Down Expand Up @@ -36,6 +36,13 @@
</ul>
""".strip()

ONEOF_OBJECT_DETAILS_TEMPLATE = """
<p>An object with the following fields:</p>
<ul>
{values}
</ul>
""".strip()

OBJECT_LIST_ITEM_TEMPLATE = """
<li>
<code>{value}</code>: <span class=api-field-type>{data_type}</span> {required} {description}{object_details}
Expand All @@ -49,6 +56,17 @@

OBJECT_CODE_TEMPLATE = "<code>{value}</code>".strip()

ONEOF_DETAILS_TEMPLATE = """
<p>This parameter must be one of the following:</p>
<ol>
{values}
</ol>
""".strip()

ONEOF_LIST_ITEM_TEMPLATE = """
<li>{item}</li>
""".strip()


class MarkdownArgumentsTableGenerator(Extension):
@override
Expand Down Expand Up @@ -100,6 +118,24 @@ def run(self, lines: List[str]) -> List[str]:
done = True
return lines

def render_oneof_block(self, object_schema: Dict[str, Any], name: str) -> str:
md_engine = markdown.Markdown(extensions=[])
content = ""
for element in object_schema["oneOf"]:
if "items" in element and "properties" in element["items"]:
content += ONEOF_LIST_ITEM_TEMPLATE.format(
item=self.render_object_details(element["items"], str(name), True)
)
elif "properties" in element:
content += ONEOF_LIST_ITEM_TEMPLATE.format(
item=self.render_object_details(element, str(name), True)
)
elif "description" in element:
content += ONEOF_LIST_ITEM_TEMPLATE.format(
item=md_engine.convert(element["description"])
)
return ONEOF_DETAILS_TEMPLATE.format(values=content)

def render_parameters(self, parameters: Sequence[Parameter]) -> List[str]:
lines = []

Expand Down Expand Up @@ -159,6 +195,8 @@ def render_parameters(self, parameters: Sequence[Parameter]) -> List[str]:
object_block = self.render_object_details(object_schema["items"], str(name))
elif "properties" in object_schema:
object_block = self.render_object_details(object_schema, str(name))
elif "oneOf" in object_schema:
object_block = self.render_oneof_block(object_schema, str(name))

lines.append(
API_PARAMETER_TEMPLATE.format(
Expand All @@ -174,7 +212,9 @@ def render_parameters(self, parameters: Sequence[Parameter]) -> List[str]:

return lines

def render_object_details(self, schema: Mapping[str, Any], name: str) -> str:
def render_object_details(
self, schema: Mapping[str, Any], name: str, oneof: bool = False
) -> str:
md_engine = markdown.Markdown(extensions=[])
li_elements = []

Expand Down Expand Up @@ -227,6 +267,8 @@ def render_object_details(self, schema: Mapping[str, Any], name: str) -> str:
details = ""
if "object" in data_type and "properties" in object_values[value]:
details += self.render_object_details(object_values[value], str(value))
elif "oneOf" in object_values[value]:
details += self.render_oneof_block(object_values[value], str(value))

li = OBJECT_LIST_ITEM_TEMPLATE.format(
value=value,
Expand All @@ -237,11 +279,15 @@ def render_object_details(self, schema: Mapping[str, Any], name: str) -> str:
)

li_elements.append(li)

object_details = OBJECT_DETAILS_TEMPLATE.format(
argument=name,
values="\n".join(li_elements),
)
if oneof:
object_details = ONEOF_OBJECT_DETAILS_TEMPLATE.format(
values="\n".join(li_elements),
)
else:
object_details = OBJECT_DETAILS_TEMPLATE.format(
argument=name,
values="\n".join(li_elements),
)
return object_details


Expand Down
64 changes: 47 additions & 17 deletions zerver/lib/markdown/api_return_values_table_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,39 @@ def render_desc(
+ description
)

def render_oneof_block(self, object_schema: Dict[str, Any], spacing: int) -> List[str]:
ans = []
block_spacing = spacing
for element in object_schema["oneOf"]:
spacing = block_spacing
if "description" not in element:
# If the description is not present, we still need to render the rest
# of the documentation of the element shifted towards left of the page.
spacing -= 4
else:
# Add the specialized description of the oneOf element.
data_type = generate_data_type(element)
ans.append(self.render_desc(element["description"], spacing, data_type))
# If the oneOf element is an object schema then render the documentation
# of its keys.
if "properties" in element:
ans += self.render_table(element["properties"], spacing + 4)
if element.get("additionalProperties", False):
additional_properties = element["additionalProperties"]
if "description" in additional_properties:
data_type = generate_data_type(additional_properties)
ans.append(
self.render_desc(
additional_properties["description"], spacing + 4, data_type
)
)
if "properties" in additional_properties:
ans += self.render_table(
additional_properties["properties"],
spacing + 8,
)
return ans

def render_table(self, return_values: Dict[str, Any], spacing: int) -> List[str]:
IGNORE = ["result", "msg", "ignored_parameters_unsupported"]
ans = []
Expand All @@ -165,16 +198,7 @@ def render_table(self, return_values: Dict[str, Any], spacing: int) -> List[str]
return_values[return_value]["description"], spacing, data_type, return_value
)
)
for element in return_values[return_value]["oneOf"]:
if "description" not in element:
continue
# Add the specialized description of the oneOf element.
data_type = generate_data_type(element)
ans.append(self.render_desc(element["description"], spacing + 4, data_type))
# If the oneOf element is an object schema then render the documentation
# of its keys.
if "properties" in element:
ans += self.render_table(element["properties"], spacing + 8)
ans += self.render_oneof_block(return_values[return_value], spacing + 4)
continue
description = return_values[return_value]["description"]
data_type = generate_data_type(return_values[return_value])
Expand All @@ -198,6 +222,10 @@ def render_table(self, return_values: Dict[str, Any], spacing: int) -> List[str]
return_values[return_value]["additionalProperties"]["properties"],
spacing + 8,
)
elif "oneOf" in return_values[return_value]["additionalProperties"]:
ans += self.render_oneof_block(
return_values[return_value]["additionalProperties"], spacing + 8
)
elif return_values[return_value]["additionalProperties"].get(
"additionalProperties", False
):
Expand All @@ -220,13 +248,15 @@ def render_table(self, return_values: Dict[str, Any], spacing: int) -> List[str]
],
spacing + 12,
)
if (
"items" in return_values[return_value]
and "properties" in return_values[return_value]["items"]
):
ans += self.render_table(
return_values[return_value]["items"]["properties"], spacing + 4
)
if "items" in return_values[return_value]:
if "properties" in return_values[return_value]["items"]:
ans += self.render_table(
return_values[return_value]["items"]["properties"], spacing + 4
)
elif "oneOf" in return_values[return_value]["items"]:
ans += self.render_oneof_block(
return_values[return_value]["items"], spacing + 4
)
return ans

def generate_event_strings(self, event_data: EventData) -> List[str]:
Expand Down

0 comments on commit 46331db

Please sign in to comment.