#!/usr/bin/env python3 # check for the venv from lib import sanity_check sanity_check.check_venv(__file__) import html import os import pprint from collections import defaultdict from typing import Any, Dict, List, Set 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()