#!/usr/bin/env python3 import html import os import pprint import sys from collections import defaultdict from typing import Any, Dict, List, Set sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) # check for the venv from tools.lib import sanity_check sanity_check.check_venv(__file__) import orjson Call = Dict[str, Any] def clean_up_pattern(s: str) -> str: paren_level = 0 in_braces = False result = "" prior_char = None for c in s: if c == "(": paren_level += 1 if c == "<" and prior_char == "P": in_braces = True if in_braces or (paren_level == 0): if c != "?": result += c if c == ")": paren_level -= 1 if c == ">": in_braces = False prior_char = c return result def encode_info(info: Any) -> str: try: result = "" try: info = orjson.loads(info) result = "(stringified)\n" except orjson.JSONDecodeError: pass result += html.escape(pprint.pformat(info, indent=4)) return "
" + result + "
" except Exception: pass try: return html.escape(str(info)) except Exception: pass return "NOT ENCODABLE" def fix_test_name(s: str) -> str: return s.replace("zerver.tests.", "") def create_single_page(pattern: str, out_dir: str, href: str, calls: List[Call]) -> None: fn = out_dir + "/" + href with open(fn, "w") as f: f.write( """ """ ) f.write(f"

{html.escape(pattern)}

\n") calls.sort(key=lambda call: call["status_code"]) for call in calls: f.write("
") f.write("\n{}".format(fix_test_name(call["test_name"]))) f.write('
') f.write(call["url"]) f.write("
\n") f.write(call["method"] + "
\n") f.write("status code: {}
\n".format(call["status_code"])) f.write("
") f.write("
") def create_user_docs() -> None: fn = "var/url_coverage.txt" # TODO: make path more robust, maybe use json suffix out_dir = "var/api_docs" try: os.mkdir(out_dir) except OSError: pass main_page = out_dir + "/index.html" with open(main_page, "w") as f: f.write( """ """ ) with open(fn, "rb") as coverage: calls = [orjson.loads(line) for line in coverage] pattern_dict: Dict[str, List[Call]] = defaultdict(list) for call in calls: if "pattern" in call: pattern = clean_up_pattern(call["pattern"]) if pattern: pattern_dict[pattern].append(call) patterns = set(pattern_dict.keys()) tups = [ ("api/v1/external", "webhooks"), ("api/v1", "api"), ("json", "legacy"), ] groups: Dict[str, Set[str]] = {} for prefix, name in tups: groups[name] = {p for p in patterns if p.startswith(prefix)} patterns -= groups[name] groups["other"] = patterns for name in ["api", "legacy", "webhooks", "other"]: f.write(name + " endpoints:\n\n") f.write("") f.write("\n") print(f"open {main_page}") if __name__ == "__main__": create_user_docs()