#!/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 Exception:
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('')
try:
f.write(call['url'])
except Exception:
f.write(call['url'].encode('utf8'))
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]] = dict()
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('\n')
for pattern in sorted(groups[name]):
href = pattern.replace('/', '-') + '.html'
link = f'{html.escape(pattern)}'
f.write('- ' + link + '
\n')
create_single_page(pattern, out_dir, href, pattern_dict[pattern])
f.write('
')
f.write('\n')
print(f'open {main_page}')
if __name__ == '__main__':
create_user_docs()