Files
zulip/tools/create-test-api-docs
Anders Kaseorg 365fe0b3d5 python: Sort imports with isort.
Fixes #2665.

Regenerated by tabbott with `lint --fix` after a rebase and change in
parameters.

Note from tabbott: In a few cases, this converts technical debt in the
form of unsorted imports into different technical debt in the form of
our largest files having very long, ugly import sequences at the
start.  I expect this change will increase pressure for us to split
those files, which isn't a bad thing.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
2020-06-11 16:45:32 -07:00

151 lines
4.0 KiB
Python
Executable File

#!/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 ujson
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 = ujson.loads(info)
result = '(stringified)\n'
except Exception:
pass
result += html.escape(pprint.pformat(info, indent=4))
return '<pre>' + result + '</pre>'
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('''
<style>
.test {
margin: 20px;
}
</style>
''')
f.write(f'<h3>{html.escape(pattern)}</h3>\n')
calls.sort(key=lambda call: call['status_code'])
for call in calls:
f.write('<hr>')
f.write('\n{}'.format(fix_test_name(call['test_name'])))
f.write('<div class="test">')
try:
f.write(call['url'])
except Exception:
f.write(call['url'].encode('utf8'))
f.write('<br>\n')
f.write(call['method'] + '<br>\n')
f.write('status code: {}<br>\n'.format(call['status_code']))
f.write('<br>')
f.write('</div>')
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('''
<style>
li {
list-style-type: none;
}
a {
text-decoration: none;
}
</style>
''')
calls = []
for line in open(fn):
calls.append(ujson.loads(line))
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('<ul>\n')
for pattern in sorted(groups[name]):
href = pattern.replace('/', '-') + '.html'
link = f'<a href="{href}">{html.escape(pattern)}</a>'
f.write('<li>' + link + '</li>\n')
create_single_page(pattern, out_dir, href, pattern_dict[pattern])
f.write('</ul>')
f.write('\n')
print(f'open {main_page}')
if __name__ == '__main__':
create_user_docs()