blob: 49ae2745114c2de525bbefcead5322ac81e7f008 [file] [log] [blame]
Joe Gregorio79daca02013-03-29 16:25:52 -04001#!/usr/bin/python
Joe Gregorio20a5aa92011-04-01 17:44:25 -04002#
Craig Citro751b7fb2014-09-23 11:20:38 -07003# Copyright 2014 Google Inc. All Rights Reserved.
Joe Gregorio20a5aa92011-04-01 17:44:25 -04004#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
Joe Gregorio81d92cc2012-07-09 16:46:02 -040017"""Create documentation for generate API surfaces.
18
19Command-line tool that creates documentation for all APIs listed in discovery.
20The documentation is generated from a combination of the discovery document and
21the generated API surface itself.
22"""
Christian Clauss9fdc2b22019-07-22 19:43:21 +020023from __future__ import print_function
Joe Gregorio81d92cc2012-07-09 16:46:02 -040024
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070025__author__ = "jcgregorio@google.com (Joe Gregorio)"
Joe Gregorio20a5aa92011-04-01 17:44:25 -040026
Joe Gregorio79daca02013-03-29 16:25:52 -040027import argparse
Bu Sun Kimc9773042019-07-17 14:03:17 -070028import collections
Craig Citro6ae34d72014-08-18 23:10:09 -070029import json
Anthonios Partheniouaff037a2021-04-21 11:00:09 -040030import pathlib
Joe Gregorioafc45f22011-02-20 16:11:28 -050031import re
Joe Gregorio79daca02013-03-29 16:25:52 -040032import string
Joe Gregorio20a5aa92011-04-01 17:44:25 -040033import sys
Joe Gregorioafc45f22011-02-20 16:11:28 -050034
John Asmuth864311d2014-04-24 15:46:08 -040035from googleapiclient.discovery import DISCOVERY_URI
36from googleapiclient.discovery import build
37from googleapiclient.discovery import build_from_document
Igor Maravić22435292017-01-19 22:28:22 +010038from googleapiclient.http import build_http
Dan O'Mearadd494642020-05-01 07:42:23 -070039
Joe Gregorio81d92cc2012-07-09 16:46:02 -040040import uritemplate
41
Anthonios Partheniouaff037a2021-04-21 11:00:09 -040042DISCOVERY_DOC_DIR = (
arfy slowyd35c9122021-07-15 00:16:31 +070043 pathlib.Path(__file__).parent.resolve()
44 / "googleapiclient"
45 / "discovery_cache"
46 / "documents"
Anthonios Partheniouaff037a2021-04-21 11:00:09 -040047)
48
Joe Gregorio81d92cc2012-07-09 16:46:02 -040049CSS = """<style>
50
51body, h1, h2, h3, div, span, p, pre, a {
52 margin: 0;
53 padding: 0;
54 border: 0;
55 font-weight: inherit;
56 font-style: inherit;
57 font-size: 100%;
58 font-family: inherit;
59 vertical-align: baseline;
60}
61
62body {
63 font-size: 13px;
64 padding: 1em;
65}
66
67h1 {
68 font-size: 26px;
69 margin-bottom: 1em;
70}
71
72h2 {
73 font-size: 24px;
74 margin-bottom: 1em;
75}
76
77h3 {
78 font-size: 20px;
79 margin-bottom: 1em;
80 margin-top: 1em;
81}
82
83pre, code {
84 line-height: 1.5;
85 font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace;
86}
87
88pre {
89 margin-top: 0.5em;
90}
91
92h1, h2, h3, p {
93 font-family: Arial, sans serif;
94}
95
96h1, h2, h3 {
97 border-bottom: solid #CCC 1px;
98}
99
100.toc_element {
101 margin-top: 0.5em;
102}
103
104.firstline {
105 margin-left: 2 em;
106}
107
108.method {
109 margin-top: 1em;
110 border: solid 1px #CCC;
111 padding: 1em;
112 background: #EEE;
113}
114
115.details {
116 font-weight: bold;
117 font-size: 14px;
118}
119
120</style>
121"""
122
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400123METHOD_TEMPLATE = """<div class="method">
124 <code class="details" id="$name">$name($params)</code>
125 <pre>$doc</pre>
126</div>
127"""
128
129COLLECTION_LINK = """<p class="toc_element">
130 <code><a href="$href">$name()</a></code>
131</p>
132<p class="firstline">Returns the $name Resource.</p>
133"""
134
135METHOD_LINK = """<p class="toc_element">
136 <code><a href="#$name">$name($params)</a></code></p>
137<p class="firstline">$firstline</p>"""
138
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400139BASE = pathlib.Path(__file__).parent.resolve() / "docs" / "dyn"
Joe Gregoriobb964352013-03-03 20:45:29 -0500140
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700141DIRECTORY_URI = "https://www.googleapis.com/discovery/v1/apis"
Joe Gregoriobb964352013-03-03 20:45:29 -0500142
Joe Gregorio79daca02013-03-29 16:25:52 -0400143parser = argparse.ArgumentParser(description=__doc__)
Joe Gregoriobb964352013-03-03 20:45:29 -0500144
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700145parser.add_argument(
146 "--discovery_uri_template",
147 default=DISCOVERY_URI,
148 help="URI Template for discovery.",
149)
Joe Gregoriobb964352013-03-03 20:45:29 -0500150
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700151parser.add_argument(
152 "--discovery_uri",
153 default="",
154 help=(
155 "URI of discovery document. If supplied then only "
156 "this API will be documented."
157 ),
158)
Joe Gregoriobb964352013-03-03 20:45:29 -0500159
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700160parser.add_argument(
161 "--directory_uri",
162 default=DIRECTORY_URI,
163 help=("URI of directory document. Unused if --discovery_uri" " is supplied."),
164)
Joe Gregoriobb964352013-03-03 20:45:29 -0500165
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700166parser.add_argument(
167 "--dest", default=BASE, help="Directory name to write documents into."
168)
Joe Gregoriobb964352013-03-03 20:45:29 -0500169
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400170
171def safe_version(version):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700172 """Create a safe version of the verion string.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400173
arfy slowyd35c9122021-07-15 00:16:31 +0700174 Needed so that we can distinguish between versions
175 and sub-collections in URIs. I.e. we don't want
176 adsense_v1.1 to refer to the '1' collection in the v1
177 version of the adsense api.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400178
arfy slowyd35c9122021-07-15 00:16:31 +0700179 Args:
180 version: string, The version string.
181 Returns:
182 The string with '.' replaced with '_'.
183 """
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400184
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700185 return version.replace(".", "_")
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400186
187
188def unsafe_version(version):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700189 """Undoes what safe_version() does.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400190
arfy slowyd35c9122021-07-15 00:16:31 +0700191 See safe_version() for the details.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400192
193
arfy slowyd35c9122021-07-15 00:16:31 +0700194 Args:
195 version: string, The safe version string.
196 Returns:
197 The string with '_' replaced with '.'.
198 """
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400199
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700200 return version.replace("_", ".")
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400201
202
203def method_params(doc):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700204 """Document the parameters of a method.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400205
arfy slowyd35c9122021-07-15 00:16:31 +0700206 Args:
207 doc: string, The method's docstring.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400208
arfy slowyd35c9122021-07-15 00:16:31 +0700209 Returns:
210 The method signature as a string.
211 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700212 doclines = doc.splitlines()
213 if "Args:" in doclines:
214 begin = doclines.index("Args:")
215 if "Returns:" in doclines[begin + 1 :]:
216 end = doclines.index("Returns:", begin)
217 args = doclines[begin + 1 : end]
218 else:
219 args = doclines[begin + 1 :]
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400220
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700221 parameters = []
Anthonios Partheniou4249a7b2020-12-15 20:32:05 -0500222 sorted_parameters = []
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700223 pname = None
224 desc = ""
225
226 def add_param(pname, desc):
227 if pname is None:
228 return
229 if "(required)" not in desc:
230 pname = pname + "=None"
Anthonios Partheniou4249a7b2020-12-15 20:32:05 -0500231 parameters.append(pname)
232 else:
233 # required params should be put straight into sorted_parameters
234 # to maintain order for positional args
235 sorted_parameters.append(pname)
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700236
237 for line in args:
Karthikeyan Singaravelan0f60eda2020-08-03 22:12:03 +0530238 m = re.search(r"^\s+([a-zA-Z0-9_]+): (.*)", line)
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700239 if m is None:
240 desc += line
241 continue
242 add_param(pname, desc)
243 pname = m.group(1)
244 desc = m.group(2)
245 add_param(pname, desc)
Anthonios Partheniou4249a7b2020-12-15 20:32:05 -0500246 sorted_parameters.extend(sorted(parameters))
247 sorted_parameters = ", ".join(sorted_parameters)
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700248 else:
Anthonios Partheniou4249a7b2020-12-15 20:32:05 -0500249 sorted_parameters = ""
250 return sorted_parameters
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400251
252
253def method(name, doc):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700254 """Documents an individual method.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400255
arfy slowyd35c9122021-07-15 00:16:31 +0700256 Args:
257 name: string, Name of the method.
258 doc: string, The methods docstring.
259 """
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400260 import html
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400261
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700262 params = method_params(doc)
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400263 doc = html.escape(doc)
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700264 return string.Template(METHOD_TEMPLATE).substitute(
265 name=name, params=params, doc=doc
266 )
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400267
268
269def breadcrumbs(path, root_discovery):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700270 """Create the breadcrumb trail to this page of documentation.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400271
arfy slowyd35c9122021-07-15 00:16:31 +0700272 Args:
273 path: string, Dot separated name of the resource.
274 root_discovery: Deserialized discovery document.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400275
arfy slowyd35c9122021-07-15 00:16:31 +0700276 Returns:
277 HTML with links to each of the parent resources of this resource.
278 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700279 parts = path.split(".")
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400280
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700281 crumbs = []
282 accumulated = []
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400283
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700284 for i, p in enumerate(parts):
285 prefix = ".".join(accumulated)
286 # The first time through prefix will be [], so we avoid adding in a
287 # superfluous '.' to prefix.
288 if prefix:
289 prefix += "."
290 display = p
291 if i == 0:
292 display = root_discovery.get("title", display)
Karthikeyan Singaravelan0f60eda2020-08-03 22:12:03 +0530293 crumbs.append('<a href="{}.html">{}</a>'.format(prefix + p, display))
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700294 accumulated.append(p)
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400295
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700296 return " . ".join(crumbs)
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400297
298
299def document_collection(resource, path, root_discovery, discovery, css=CSS):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700300 """Document a single collection in an API.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400301
arfy slowyd35c9122021-07-15 00:16:31 +0700302 Args:
303 resource: Collection or service being documented.
304 path: string, Dot separated name of the resource.
305 root_discovery: Deserialized discovery document.
306 discovery: Deserialized discovery document, but just the portion that
307 describes the resource.
308 css: string, The CSS to include in the generated file.
309 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700310 collections = []
311 methods = []
312 resource_name = path.split(".")[-2]
313 html = [
314 "<html><body>",
315 css,
316 "<h1>%s</h1>" % breadcrumbs(path[:-1], root_discovery),
317 "<h2>Instance Methods</h2>",
318 ]
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400319
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700320 # Which methods are for collections.
321 for name in dir(resource):
322 if not name.startswith("_") and callable(getattr(resource, name)):
323 if hasattr(getattr(resource, name), "__is_resource__"):
324 collections.append(name)
325 else:
326 methods.append(name)
Joe Gregorioafc45f22011-02-20 16:11:28 -0500327
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700328 # TOC
329 if collections:
330 for name in collections:
331 if not name.startswith("_") and callable(getattr(resource, name)):
332 href = path + name + ".html"
333 html.append(
334 string.Template(COLLECTION_LINK).substitute(href=href, name=name)
335 )
Joe Gregorioafc45f22011-02-20 16:11:28 -0500336
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700337 if methods:
338 for name in methods:
339 if not name.startswith("_") and callable(getattr(resource, name)):
340 doc = getattr(resource, name).__doc__
341 params = method_params(doc)
342 firstline = doc.splitlines()[0]
343 html.append(
344 string.Template(METHOD_LINK).substitute(
345 name=name, params=params, firstline=firstline
346 )
347 )
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400348
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700349 if methods:
350 html.append("<h3>Method Details</h3>")
351 for name in methods:
352 dname = name.rsplit("_")[0]
353 html.append(method(name, getattr(resource, name).__doc__))
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400354
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700355 html.append("</body></html>")
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400356
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700357 return "\n".join(html)
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400358
359
arfy slowyd35c9122021-07-15 00:16:31 +0700360def document_collection_recursive(
361 resource, path, root_discovery, discovery, doc_destination_dir
362):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700363 html = document_collection(resource, path, root_discovery, discovery)
Joe Gregorioafc45f22011-02-20 16:11:28 -0500364
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400365 f = open(pathlib.Path(doc_destination_dir).joinpath(path + "html"), "w")
Billy SU84d45612020-04-21 06:15:56 +0800366
367 f.write(html)
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700368 f.close()
Joe Gregorioafc45f22011-02-20 16:11:28 -0500369
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700370 for name in dir(resource):
371 if (
372 not name.startswith("_")
373 and callable(getattr(resource, name))
374 and hasattr(getattr(resource, name), "__is_resource__")
375 and discovery != {}
376 ):
377 dname = name.rsplit("_")[0]
378 collection = getattr(resource, name)()
379 document_collection_recursive(
380 collection,
381 path + name + ".",
382 root_discovery,
383 discovery["resources"].get(dname, {}),
arfy slowyd35c9122021-07-15 00:16:31 +0700384 doc_destination_dir,
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700385 )
386
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400387
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400388def document_api(name, version, uri, doc_destination_dir):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700389 """Document the given API.
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400390
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400391 Args:
392 name (str): Name of the API.
393 version (str): Version of the API.
394 uri (str): URI of the API's discovery document
395 doc_destination_dir (str): relative path where the reference
396 documentation should be saved.
arfy slowyd35c9122021-07-15 00:16:31 +0700397 """
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400398 http = build_http()
399 resp, content = http.request(
arfy slowyd35c9122021-07-15 00:16:31 +0700400 uri
401 or uritemplate.expand(
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400402 FLAGS.discovery_uri_template, {"api": name, "apiVersion": version}
403 )
404 )
Jon Wayne Parrottfd2f99c2016-02-19 16:02:04 -0800405
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400406 if resp.status == 200:
407 discovery = json.loads(content)
408 service = build_from_document(discovery)
Anthonios Partheniou31bbe512021-05-27 16:49:17 -0400409 doc_name = "{}.{}.json".format(name, version)
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400410 discovery_file_path = DISCOVERY_DOC_DIR / doc_name
411 revision = None
412
413 pathlib.Path(discovery_file_path).touch(exist_ok=True)
414
415 # Write discovery artifact to disk if revision equal or newer
416 with open(discovery_file_path, "r+") as f:
417 try:
418 json_data = json.load(f)
arfy slowyd35c9122021-07-15 00:16:31 +0700419 revision = json_data["revision"]
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400420 except json.JSONDecodeError:
421 revision = None
422
arfy slowyd35c9122021-07-15 00:16:31 +0700423 if revision is None or discovery["revision"] >= revision:
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400424 # Reset position to the beginning
425 f.seek(0)
426 # Write the changes to disk
427 json.dump(discovery, f, indent=2, sort_keys=True)
428 # Truncate anything left as it's not needed
429 f.truncate()
430
431 elif resp.status == 404:
arfy slowyd35c9122021-07-15 00:16:31 +0700432 print(
433 "Warning: {} {} not found. HTTP Code: {}".format(name, version, resp.status)
434 )
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400435 return
436 else:
arfy slowyd35c9122021-07-15 00:16:31 +0700437 print(
438 "Warning: {} {} could not be built. HTTP Code: {}".format(
439 name, version, resp.status
440 )
441 )
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400442 return
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400443
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700444 document_collection_recursive(
arfy slowyd35c9122021-07-15 00:16:31 +0700445 service,
446 "{}_{}.".format(name, safe_version(version)),
447 discovery,
448 discovery,
449 doc_destination_dir,
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700450 )
Joe Gregorio81d92cc2012-07-09 16:46:02 -0400451
Joe Gregorioafc45f22011-02-20 16:11:28 -0500452
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400453def document_api_from_discovery_document(discovery_url, doc_destination_dir):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700454 """Document the given API.
Joe Gregoriobb964352013-03-03 20:45:29 -0500455
arfy slowyd35c9122021-07-15 00:16:31 +0700456 Args:
457 discovery_url (str): URI of discovery document.
458 doc_destination_dir (str): relative path where the reference
459 documentation should be saved.
460 """
Igor Maravić22435292017-01-19 22:28:22 +0100461 http = build_http()
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400462 response, content = http.request(discovery_url)
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700463 discovery = json.loads(content)
Bu Sun Kimc9773042019-07-17 14:03:17 -0700464
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700465 service = build_from_document(discovery)
Bu Sun Kimc9773042019-07-17 14:03:17 -0700466
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700467 name = discovery["version"]
468 version = safe_version(discovery["version"])
Bu Sun Kimc9773042019-07-17 14:03:17 -0700469
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700470 document_collection_recursive(
arfy slowyd35c9122021-07-15 00:16:31 +0700471 service,
472 "{}_{}.".format(name, version),
473 discovery,
474 discovery,
475 doc_destination_dir,
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700476 )
477
arfy slowyd35c9122021-07-15 00:16:31 +0700478
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400479def generate_all_api_documents(directory_uri=DIRECTORY_URI, doc_destination_dir=BASE):
arfy slowyd35c9122021-07-15 00:16:31 +0700480 """Retrieve discovery artifacts and fetch reference documentations
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400481 for all apis listed in the public discovery directory.
482 args:
483 directory_uri (str): uri of the public discovery directory.
484 doc_destination_dir (str): relative path where the reference
485 documentation should be saved.
486 """
487 api_directory = collections.defaultdict(list)
488 http = build_http()
489 resp, content = http.request(directory_uri)
490 if resp.status == 200:
491 directory = json.loads(content)["items"]
492 for api in directory:
arfy slowyd35c9122021-07-15 00:16:31 +0700493 document_api(
494 api["name"],
495 api["version"],
496 api["discoveryRestUrl"],
497 doc_destination_dir,
498 )
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400499 api_directory[api["name"]].append(api["version"])
500
501 # sort by api name and version number
502 for api in api_directory:
503 api_directory[api] = sorted(api_directory[api])
arfy slowyd35c9122021-07-15 00:16:31 +0700504 api_directory = collections.OrderedDict(
Anthonios Partheniouaff037a2021-04-21 11:00:09 -0400505 sorted(api_directory.items(), key=lambda x: x[0])
506 )
507
508 markdown = []
509 for api, versions in api_directory.items():
510 markdown.append("## %s" % api)
511 for version in versions:
512 markdown.append(
513 "* [%s](http://googleapis.github.io/google-api-python-client/docs/dyn/%s_%s.html)"
514 % (version, api, safe_version(version))
515 )
516 markdown.append("\n")
517
518 with open(BASE / "index.md", "w") as f:
519 markdown = "\n".join(markdown)
520 f.write(markdown)
521
522 else:
523 sys.exit("Failed to load the discovery document.")
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700524
arfy slowyd35c9122021-07-15 00:16:31 +0700525
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700526if __name__ == "__main__":
527 FLAGS = parser.parse_args(sys.argv[1:])
528 if FLAGS.discovery_uri:
arfy slowyd35c9122021-07-15 00:16:31 +0700529 document_api_from_discovery_document(
530 discovery_url=FLAGS.discovery_uri, doc_destination_dir=FLAGS.dest
531 )
Joe Gregoriobb964352013-03-03 20:45:29 -0500532 else:
arfy slowyd35c9122021-07-15 00:16:31 +0700533 generate_all_api_documents(
534 directory_uri=FLAGS.directory_uri, doc_destination_dir=FLAGS.dest
535 )