blob: 9c28405ffb2bbdf4e2ea6032e70c6e7909b3c642 [file] [log] [blame]
Joe Gregorio9d56b5a2012-03-30 09:21:26 -04001#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
Craig Citro751b7fb2014-09-23 11:20:38 -07004# Copyright 2014 Google Inc. All Rights Reserved.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -04005#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17
18"""Build wiki page with a list of all samples.
19
20The information for the wiki page is built from data found in all the README
21files in the samples. The format of the README file is:
22
23
24 Description is everything up to the first blank line.
25
26 api: plus (Used to look up the long name in discovery).
27 keywords: appengine (such as appengine, oauth2, cmdline)
28
29 The rest of the file is ignored when it comes to building the index.
30"""
INADA Naokie8d87822014-08-20 15:25:24 +090031from __future__ import print_function
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040032
33import httplib2
34import itertools
35import json
36import os
37import re
38
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070039BASE_HG_URI = "http://code.google.com/p/google-api-python-client/source/" "browse/#hg"
Joe Gregorioa633c792012-08-24 11:27:16 -040040
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070041http = httplib2.Http(".cache")
42r, c = http.request("https://www.googleapis.com/discovery/v1/apis")
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040043if r.status != 200:
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070044 raise ValueError("Received non-200 response when retrieving Discovery.")
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040045
46# Dictionary mapping api names to their discovery description.
47DIRECTORY = {}
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070048for item in json.loads(c)["items"]:
49 if item["preferred"]:
50 DIRECTORY[item["name"]] = item
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040051
52# A list of valid keywords. Should not be taken as complete, add to
53# this list as needed.
54KEYWORDS = {
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070055 "appengine": "Google App Engine",
56 "oauth2": "OAuth 2.0",
57 "cmdline": "Command-line",
58 "django": "Django",
59 "threading": "Threading",
60 "pagination": "Pagination",
61 "media": "Media Upload and Download",
62}
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040063
64
65def get_lines(name, lines):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070066 """Return lines that begin with name.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040067
68 Lines are expected to look like:
69
70 name: space separated values
71
72 Args:
73 name: string, parameter name.
74 lines: iterable of string, lines in the file.
75
76 Returns:
77 List of values in the lines that match.
78 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070079 retval = []
80 matches = itertools.ifilter(lambda x: x.startswith(name + ":"), lines)
81 for line in matches:
82 retval.extend(line[len(name) + 1 :].split())
83 return retval
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040084
85
86def wiki_escape(s):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070087 """Detect WikiSyntax (i.e. InterCaps, a.k.a. CamelCase) and escape it."""
88 ret = []
89 for word in s.split():
90 if re.match(r"[A-Z]+[a-z]+[A-Z]", word):
91 word = "!%s" % word
92 ret.append(word)
93 return " ".join(ret)
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040094
95
Joe Gregorioa633c792012-08-24 11:27:16 -040096def context_from_sample(api, keywords, dirname, desc, uri):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070097 """Return info for expanding a sample into a template.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -040098
99 Args:
100 api: string, name of api.
101 keywords: list of string, list of keywords for the given api.
102 dirname: string, directory name of the sample.
103 desc: string, long description of the sample.
Joe Gregorioa633c792012-08-24 11:27:16 -0400104 uri: string, uri of the sample code if provided in the README.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400105
106 Returns:
107 A dictionary of values useful for template expansion.
108 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700109 if uri is None:
110 uri = BASE_HG_URI + dirname.replace("/", "%2F")
111 else:
112 uri = "".join(uri)
113 if api is None:
114 return None
115 else:
116 entry = DIRECTORY[api]
117 context = {
118 "api": api,
119 "version": entry["version"],
120 "api_name": wiki_escape(entry.get("title", entry.get("description"))),
121 "api_desc": wiki_escape(entry["description"]),
122 "api_icon": entry["icons"]["x32"],
123 "keywords": keywords,
124 "dir": dirname,
125 "uri": uri,
126 "desc": wiki_escape(desc),
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400127 }
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700128 return context
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400129
130
Joe Gregorioa633c792012-08-24 11:27:16 -0400131def keyword_context_from_sample(keywords, dirname, desc, uri):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700132 """Return info for expanding a sample into a template.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400133
Joe Gregorioa633c792012-08-24 11:27:16 -0400134 Sample may not be about a specific api.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400135
136 Args:
137 keywords: list of string, list of keywords for the given api.
138 dirname: string, directory name of the sample.
139 desc: string, long description of the sample.
Joe Gregorioa633c792012-08-24 11:27:16 -0400140 uri: string, uri of the sample code if provided in the README.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400141
142 Returns:
143 A dictionary of values useful for template expansion.
144 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700145 if uri is None:
146 uri = BASE_HG_URI + dirname.replace("/", "%2F")
147 else:
148 uri = "".join(uri)
149 context = {
150 "keywords": keywords,
151 "dir": dirname,
152 "uri": uri,
153 "desc": wiki_escape(desc),
154 }
155 return context
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400156
157
158def scan_readme_files(dirname):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700159 """Scans all subdirs of dirname for README files.
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400160
161 Args:
162 dirname: string, name of directory to walk.
163
164 Returns:
165 (samples, keyword_set): list of information about all samples, the union
166 of all keywords found.
167 """
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700168 samples = []
169 keyword_set = set()
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400170
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700171 for root, dirs, files in os.walk(dirname):
172 if "README" in files:
173 filename = os.path.join(root, "README")
174 with open(filename, "r") as f:
175 content = f.read()
176 lines = content.splitlines()
177 desc = " ".join(itertools.takewhile(lambda x: x, lines))
178 api = get_lines("api", lines)
179 keywords = get_lines("keywords", lines)
180 uri = get_lines("uri", lines)
181 if not uri:
182 uri = None
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400183
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700184 for k in keywords:
185 if k not in KEYWORDS:
186 raise ValueError(
187 "%s is not a valid keyword in file %s" % (k, filename)
188 )
189 keyword_set.update(keywords)
190 if not api:
191 api = [None]
192 samples.append((api[0], keywords, root[1:], desc, uri))
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400193
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700194 samples.sort()
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400195
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700196 return samples, keyword_set
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400197
198
199def main():
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700200 # Get all the information we need out of the README files in the samples.
201 samples, keyword_set = scan_readme_files("./samples")
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400202
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700203 # Now build a wiki page with all that information. Accumulate all the
204 # information as string to be concatenated when were done.
205 page = ['<wiki:toc max_depth="3" />\n= Samples By API =\n']
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400206
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700207 # All the samples, grouped by API.
208 current_api = None
209 for api, keywords, dirname, desc, uri in samples:
210 context = context_from_sample(api, keywords, dirname, desc, uri)
211 if context is None:
212 continue
213 if current_api != api:
214 page.append(
215 """
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400216=== %(api_icon)s %(api_name)s ===
217
218%(api_desc)s
219
Joe Gregorio071f8972012-11-08 13:45:15 -0500220Documentation for the %(api_name)s in [https://google-api-client-libraries.appspot.com/documentation/%(api)s/%(version)s/python/latest/ PyDoc]
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400221
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700222"""
223 % context
224 )
225 current_api = api
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400226
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700227 page.append("|| [%(uri)s %(dir)s] || %(desc)s ||\n" % context)
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400228
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700229 # Now group the samples by keywords.
230 for keyword, keyword_name in KEYWORDS.iteritems():
231 if keyword not in keyword_set:
232 continue
233 page.append("\n= %s Samples =\n\n" % keyword_name)
234 page.append("<table border=1 cellspacing=0 cellpadding=8px>\n")
235 for _, keywords, dirname, desc, uri in samples:
236 context = keyword_context_from_sample(keywords, dirname, desc, uri)
237 if keyword not in keywords:
238 continue
239 page.append(
240 """
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400241<tr>
Joe Gregorioa633c792012-08-24 11:27:16 -0400242 <td>[%(uri)s %(dir)s] </td>
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400243 <td> %(desc)s </td>
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700244</tr>"""
245 % context
246 )
247 page.append("</table>\n")
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400248
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700249 print("".join(page))
Joe Gregorio9d56b5a2012-03-30 09:21:26 -0400250
251
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700252if __name__ == "__main__":
253 main()