mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-30 19:43:47 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			158 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python
 | |
| from __future__ import print_function
 | |
| 
 | |
| from collections import defaultdict
 | |
| from typing import Any, Dict, Iterable, Set
 | |
| 
 | |
| import cgi
 | |
| import os
 | |
| import pprint
 | |
| import re
 | |
| import ujson
 | |
| 
 | |
| Call = Dict[str, Any]
 | |
| 
 | |
| def clean_up_pattern(s):
 | |
|     # type: (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):
 | |
|     # type: (Any) -> str
 | |
|     try:
 | |
|         result = ''
 | |
|         try:
 | |
|             info = ujson.loads(info)
 | |
|             result = '(stringified)\n'
 | |
|         except:
 | |
|             pass
 | |
|         result +=  cgi.escape(pprint.pformat(info, indent=4))
 | |
|         return '<pre>' + result + '</pre>'
 | |
|     except:
 | |
|         pass
 | |
|     try:
 | |
|         return cgi.escape(str(info))
 | |
|     except:
 | |
|         pass
 | |
|     return 'NOT ENCODABLE'
 | |
| 
 | |
| def fix_test_name(s):
 | |
|     # type: (str) -> str
 | |
|     return s.replace('zerver.tests.', '')
 | |
| 
 | |
| def create_single_page(pattern, out_dir, href, calls):
 | |
|     # type: (str, str, str, List[Any]) -> None
 | |
|     fn = out_dir + '/' + href
 | |
|     with open(fn, 'w') as f:
 | |
|         f.write('''
 | |
|             <style>
 | |
|             .test {
 | |
|                 margin: 20px;
 | |
|             }
 | |
|             </style>
 | |
|             ''')
 | |
|         f.write('<h3>%s</h3>\n' % (cgi.escape(pattern),))
 | |
|         calls.sort(key=lambda call: call['status_code'])
 | |
|         for call in calls:
 | |
|             f.write('<hr>')
 | |
|             f.write('\n%s' % (fix_test_name(call['test_name']),))
 | |
|             f.write('<div class="test">')
 | |
|             try:
 | |
|                 f.write(call['url'])
 | |
|             except:
 | |
|                 f.write(call['url'].encode('utf8'))
 | |
|             f.write('<br>\n')
 | |
|             f.write(call['method'] + '<br>\n')
 | |
|             f.write('status code: %s<br>\n' % (call['status_code'],))
 | |
|             f.write('<br>')
 | |
|             if call['info']:
 | |
|                 f.write('info: %s<br>\n' % (encode_info(call['info']),))
 | |
|             if call['kwargs']:
 | |
|                 f.write('kwargs: %s<br>\n' % (encode_info(call['kwargs']),))
 | |
|             f.write('</div>')
 | |
| 
 | |
| def create_user_docs():
 | |
|     # type: () -> 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 = defaultdict(list) # type: Dict[str, List[Call]]
 | |
|         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() # type: 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('<ul>\n')
 | |
|             for pattern in sorted(groups[name]):
 | |
|                 href = pattern.replace('/', '-') + '.html'
 | |
|                 link = '<a href="%s">%s</a>' % (href, cgi.escape(pattern))
 | |
|                 f.write('<li>' + link + '</li>\n')
 | |
|                 create_single_page(pattern, out_dir, href, pattern_dict[pattern])
 | |
|             f.write('</ul>')
 | |
|             f.write('\n')
 | |
| 
 | |
|     print('open %s' % (main_page,))
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     create_user_docs()
 |