Merge branch 'master' into 3112-report-bug
[arvados.git] / doc / gen_api_method_docs.py
1 #! /usr/bin/env python
2
3 # gen_api_method_docs.py
4 #
5 # Generate docs for Arvados methods.
6 #
7 # This script will retrieve the discovery document at
8 # https://localhost:9900/discovery/v1/apis/arvados/v1/rest
9 # and will generate Textile documentation files in the current
10 # directory.
11
12 import argparse
13 import pprint
14 import re
15 import requests
16 import os
17 import sys #debugging
18
19 p = argparse.ArgumentParser(description='Generate Arvados API method documentation.')
20
21 p.add_argument('--host',
22                type=str,
23                default='localhost',
24                help="The hostname or IP address of the API server")
25
26 p.add_argument('--port',
27                type=int,
28                default=9900,
29                help="The port of the API server")
30
31 p.add_argument('--output-dir',
32                type=str,
33                default='.',
34                help="Directory in which to write output files.")
35
36 args = p.parse_args()
37
38 api_url = 'https://{host}:{port}/discovery/v1/apis/arvados/v1/rest'.format(**vars(args))
39
40 r = requests.get(api_url, verify=False)
41 if r.status_code != 200:
42     raise Exception('Bad status code %d: %s' % (r.status_code, r.text))
43
44 if 'application/json' not in r.headers.get('content-type', ''):
45     raise Exception('Unexpected content type: %s: %s' %
46                     (r.headers.get('content-type', ''), r.text))
47
48 api = r.json()
49
50 resource_num = 0
51 for resource in sorted(api[u'resources']):
52     resource_num = resource_num + 1
53     out_fname = os.path.join(args.output_dir, resource + '.textile')
54     if os.path.exists(out_fname):
55         backup_name = out_fname + '.old'
56         try:
57             os.rename(out_fname, backup_name)
58         except OSError as e:
59             print "WARNING: could not back up {1} as {2}: {3}".format(
60                 out_fname, backup_name, e)
61     outf = open(out_fname, 'w')
62     outf.write(
63 """---
64 navsection: api
65 navmenu: API Methods
66 title: "{resource}"
67 navorder: {resource_num}
68 ---
69
70 h1. {resource}
71
72 Required arguments are displayed in %{{background:#ccffcc}}green%.
73
74 """.format(resource_num=resource_num, resource=resource))
75
76     methods = api['resources'][resource]['methods']
77     for method in sorted(methods.keys()):
78         methodinfo = methods[method]
79         outf.write(
80 """
81 h2. {method}
82
83 {description}
84
85 Arguments:
86
87 table(table table-bordered table-condensed).
88 |_. Argument |_. Type |_. Description |_. Location |_. Example |
89 """.format(
90     method=method, description=methodinfo['description']))
91
92         required = []
93         notrequired = []
94         for param, paraminfo in methodinfo['parameters'].iteritems():
95             paraminfo.setdefault(u'description', '')
96             paraminfo.setdefault(u'location', '')
97             limit = ''
98             if paraminfo.get('minimum', '') or paraminfo.get('maximum', ''):
99                 limit = "range {0}-{1}".format(
100                     paraminfo.get('minimum', ''),
101                     paraminfo.get('maximum', 'unlimited'))
102             if paraminfo.get('default', ''):
103                 if limit:
104                     limit = limit + '; '
105                 limit = limit + 'default %d' % paraminfo['default']
106             if limit:
107                 paraminfo['type'] = '{0} ({1})'.format(
108                     paraminfo['type'], limit)
109
110             row = "|{param}|{type}|{description}|{location}||\n".format(
111                 param=param, **paraminfo)
112             if paraminfo.get('required', False):
113                 required.append(row)
114             else:
115                 notrequired.append(row)
116
117         for row in sorted(required):
118             outf.write("{background:#ccffcc}." + row)
119         for row in sorted(notrequired):
120             outf.write(row)
121
122         # pprint.pprint(methodinfo)
123
124     outf.close()
125     print "wrote ", out_fname
126
127