Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: third_party/google_api_python_client/describe.py

Issue 963953003: OAuth2 support in depot_tools (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: restore git_cl Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 #
3 # Copyright 2014 Google Inc. All Rights Reserved.
4 #
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
17 """Create documentation for generate API surfaces.
18
19 Command-line tool that creates documentation for all APIs listed in discovery.
20 The documentation is generated from a combination of the discovery document and
21 the generated API surface itself.
22 """
23
24 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
25
26 import argparse
27 import json
28 import os
29 import re
30 import string
31 import sys
32
33 from googleapiclient.discovery import DISCOVERY_URI
34 from googleapiclient.discovery import build
35 from googleapiclient.discovery import build_from_document
36 import httplib2
37 import uritemplate
38
39 CSS = """<style>
40
41 body, h1, h2, h3, div, span, p, pre, a {
42 margin: 0;
43 padding: 0;
44 border: 0;
45 font-weight: inherit;
46 font-style: inherit;
47 font-size: 100%;
48 font-family: inherit;
49 vertical-align: baseline;
50 }
51
52 body {
53 font-size: 13px;
54 padding: 1em;
55 }
56
57 h1 {
58 font-size: 26px;
59 margin-bottom: 1em;
60 }
61
62 h2 {
63 font-size: 24px;
64 margin-bottom: 1em;
65 }
66
67 h3 {
68 font-size: 20px;
69 margin-bottom: 1em;
70 margin-top: 1em;
71 }
72
73 pre, code {
74 line-height: 1.5;
75 font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida C onsole', monospace;
76 }
77
78 pre {
79 margin-top: 0.5em;
80 }
81
82 h1, h2, h3, p {
83 font-family: Arial, sans serif;
84 }
85
86 h1, h2, h3 {
87 border-bottom: solid #CCC 1px;
88 }
89
90 .toc_element {
91 margin-top: 0.5em;
92 }
93
94 .firstline {
95 margin-left: 2 em;
96 }
97
98 .method {
99 margin-top: 1em;
100 border: solid 1px #CCC;
101 padding: 1em;
102 background: #EEE;
103 }
104
105 .details {
106 font-weight: bold;
107 font-size: 14px;
108 }
109
110 </style>
111 """
112
113 METHOD_TEMPLATE = """<div class="method">
114 <code class="details" id="$name">$name($params)</code>
115 <pre>$doc</pre>
116 </div>
117 """
118
119 COLLECTION_LINK = """<p class="toc_element">
120 <code><a href="$href">$name()</a></code>
121 </p>
122 <p class="firstline">Returns the $name Resource.</p>
123 """
124
125 METHOD_LINK = """<p class="toc_element">
126 <code><a href="#$name">$name($params)</a></code></p>
127 <p class="firstline">$firstline</p>"""
128
129 BASE = 'docs/dyn'
130
131 DIRECTORY_URI = 'https://www.googleapis.com/discovery/v1/apis?preferred=true'
132
133 parser = argparse.ArgumentParser(description=__doc__)
134
135 parser.add_argument('--discovery_uri_template', default=DISCOVERY_URI,
136 help='URI Template for discovery.')
137
138 parser.add_argument('--discovery_uri', default='',
139 help=('URI of discovery document. If supplied then only '
140 'this API will be documented.'))
141
142 parser.add_argument('--directory_uri', default=DIRECTORY_URI,
143 help=('URI of directory document. Unused if --discovery_uri'
144 ' is supplied.'))
145
146 parser.add_argument('--dest', default=BASE,
147 help='Directory name to write documents into.')
148
149
150
151 def safe_version(version):
152 """Create a safe version of the verion string.
153
154 Needed so that we can distinguish between versions
155 and sub-collections in URIs. I.e. we don't want
156 adsense_v1.1 to refer to the '1' collection in the v1
157 version of the adsense api.
158
159 Args:
160 version: string, The version string.
161 Returns:
162 The string with '.' replaced with '_'.
163 """
164
165 return version.replace('.', '_')
166
167
168 def unsafe_version(version):
169 """Undoes what safe_version() does.
170
171 See safe_version() for the details.
172
173
174 Args:
175 version: string, The safe version string.
176 Returns:
177 The string with '_' replaced with '.'.
178 """
179
180 return version.replace('_', '.')
181
182
183 def method_params(doc):
184 """Document the parameters of a method.
185
186 Args:
187 doc: string, The method's docstring.
188
189 Returns:
190 The method signature as a string.
191 """
192 doclines = doc.splitlines()
193 if 'Args:' in doclines:
194 begin = doclines.index('Args:')
195 if 'Returns:' in doclines[begin+1:]:
196 end = doclines.index('Returns:', begin)
197 args = doclines[begin+1: end]
198 else:
199 args = doclines[begin+1:]
200
201 parameters = []
202 for line in args:
203 m = re.search('^\s+([a-zA-Z0-9_]+): (.*)', line)
204 if m is None:
205 continue
206 pname = m.group(1)
207 desc = m.group(2)
208 if '(required)' not in desc:
209 pname = pname + '=None'
210 parameters.append(pname)
211 parameters = ', '.join(parameters)
212 else:
213 parameters = ''
214 return parameters
215
216
217 def method(name, doc):
218 """Documents an individual method.
219
220 Args:
221 name: string, Name of the method.
222 doc: string, The methods docstring.
223 """
224
225 params = method_params(doc)
226 return string.Template(METHOD_TEMPLATE).substitute(
227 name=name, params=params, doc=doc)
228
229
230 def breadcrumbs(path, root_discovery):
231 """Create the breadcrumb trail to this page of documentation.
232
233 Args:
234 path: string, Dot separated name of the resource.
235 root_discovery: Deserialized discovery document.
236
237 Returns:
238 HTML with links to each of the parent resources of this resource.
239 """
240 parts = path.split('.')
241
242 crumbs = []
243 accumulated = []
244
245 for i, p in enumerate(parts):
246 prefix = '.'.join(accumulated)
247 # The first time through prefix will be [], so we avoid adding in a
248 # superfluous '.' to prefix.
249 if prefix:
250 prefix += '.'
251 display = p
252 if i == 0:
253 display = root_discovery.get('title', display)
254 crumbs.append('<a href="%s.html">%s</a>' % (prefix + p, display))
255 accumulated.append(p)
256
257 return ' . '.join(crumbs)
258
259
260 def document_collection(resource, path, root_discovery, discovery, css=CSS):
261 """Document a single collection in an API.
262
263 Args:
264 resource: Collection or service being documented.
265 path: string, Dot separated name of the resource.
266 root_discovery: Deserialized discovery document.
267 discovery: Deserialized discovery document, but just the portion that
268 describes the resource.
269 css: string, The CSS to include in the generated file.
270 """
271 collections = []
272 methods = []
273 resource_name = path.split('.')[-2]
274 html = [
275 '<html><body>',
276 css,
277 '<h1>%s</h1>' % breadcrumbs(path[:-1], root_discovery),
278 '<h2>Instance Methods</h2>'
279 ]
280
281 # Which methods are for collections.
282 for name in dir(resource):
283 if not name.startswith('_') and callable(getattr(resource, name)):
284 if hasattr(getattr(resource, name), '__is_resource__'):
285 collections.append(name)
286 else:
287 methods.append(name)
288
289
290 # TOC
291 if collections:
292 for name in collections:
293 if not name.startswith('_') and callable(getattr(resource, name)):
294 href = path + name + '.html'
295 html.append(string.Template(COLLECTION_LINK).substitute(
296 href=href, name=name))
297
298 if methods:
299 for name in methods:
300 if not name.startswith('_') and callable(getattr(resource, name)):
301 doc = getattr(resource, name).__doc__
302 params = method_params(doc)
303 firstline = doc.splitlines()[0]
304 html.append(string.Template(METHOD_LINK).substitute(
305 name=name, params=params, firstline=firstline))
306
307 if methods:
308 html.append('<h3>Method Details</h3>')
309 for name in methods:
310 dname = name.rsplit('_')[0]
311 html.append(method(name, getattr(resource, name).__doc__))
312
313 html.append('</body></html>')
314
315 return '\n'.join(html)
316
317
318 def document_collection_recursive(resource, path, root_discovery, discovery):
319
320 html = document_collection(resource, path, root_discovery, discovery)
321
322 f = open(os.path.join(FLAGS.dest, path + 'html'), 'w')
323 f.write(html.encode('utf-8'))
324 f.close()
325
326 for name in dir(resource):
327 if (not name.startswith('_')
328 and callable(getattr(resource, name))
329 and hasattr(getattr(resource, name), '__is_resource__')):
330 dname = name.rsplit('_')[0]
331 collection = getattr(resource, name)()
332 document_collection_recursive(collection, path + name + '.', root_discover y,
333 discovery['resources'].get(dname, {}))
334
335 def document_api(name, version):
336 """Document the given API.
337
338 Args:
339 name: string, Name of the API.
340 version: string, Version of the API.
341 """
342 service = build(name, version)
343 response, content = http.request(
344 uritemplate.expand(
345 FLAGS.discovery_uri_template, {
346 'api': name,
347 'apiVersion': version})
348 )
349 discovery = json.loads(content)
350
351 version = safe_version(version)
352
353 document_collection_recursive(
354 service, '%s_%s.' % (name, version), discovery, discovery)
355
356
357 def document_api_from_discovery_document(uri):
358 """Document the given API.
359
360 Args:
361 uri: string, URI of discovery document.
362 """
363 http = httplib2.Http()
364 response, content = http.request(FLAGS.discovery_uri)
365 discovery = json.loads(content)
366
367 service = build_from_document(discovery)
368
369 name = discovery['version']
370 version = safe_version(discovery['version'])
371
372 document_collection_recursive(
373 service, '%s_%s.' % (name, version), discovery, discovery)
374
375
376 if __name__ == '__main__':
377 FLAGS = parser.parse_args(sys.argv[1:])
378 if FLAGS.discovery_uri:
379 document_api_from_discovery_document(FLAGS.discovery_uri)
380 else:
381 http = httplib2.Http()
382 resp, content = http.request(
383 FLAGS.directory_uri,
384 headers={'X-User-IP': '0.0.0.0'})
385 if resp.status == 200:
386 directory = json.loads(content)['items']
387 for api in directory:
388 document_api(api['name'], api['version'])
389 else:
390 sys.exit("Failed to load the discovery document.")
OLDNEW
« no previous file with comments | « third_party/google_api_python_client/apiclient/__init__.py ('k') | third_party/google_api_python_client/expandsymlinks.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698