#!/usr/bin/python # -*- coding: utf-8 -*- # # Copyright 2014 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Build wiki page with a list of all samples. The information for the wiki page is built from data found in all the README files in the samples. The format of the README file is: Description is everything up to the first blank line. api: plus (Used to look up the long name in discovery). keywords: appengine (such as appengine, oauth2, cmdline) The rest of the file is ignored when it comes to building the index. """ from __future__ import print_function import httplib2 import itertools import json import os import re BASE_HG_URI = "http://code.google.com/p/google-api-python-client/source/" "browse/#hg" http = httplib2.Http(".cache") r, c = http.request("https://www.googleapis.com/discovery/v1/apis") if r.status != 200: raise ValueError("Received non-200 response when retrieving Discovery.") # Dictionary mapping api names to their discovery description. DIRECTORY = {} for item in json.loads(c)["items"]: if item["preferred"]: DIRECTORY[item["name"]] = item # A list of valid keywords. Should not be taken as complete, add to # this list as needed. KEYWORDS = { "appengine": "Google App Engine", "oauth2": "OAuth 2.0", "cmdline": "Command-line", "django": "Django", "threading": "Threading", "pagination": "Pagination", "media": "Media Upload and Download", } def get_lines(name, lines): """Return lines that begin with name. Lines are expected to look like: name: space separated values Args: name: string, parameter name. lines: iterable of string, lines in the file. Returns: List of values in the lines that match. """ retval = [] matches = itertools.ifilter(lambda x: x.startswith(name + ":"), lines) for line in matches: retval.extend(line[len(name) + 1 :].split()) return retval def wiki_escape(s): """Detect WikiSyntax (i.e. InterCaps, a.k.a. CamelCase) and escape it.""" ret = [] for word in s.split(): if re.match(r"[A-Z]+[a-z]+[A-Z]", word): word = "!%s" % word ret.append(word) return " ".join(ret) def context_from_sample(api, keywords, dirname, desc, uri): """Return info for expanding a sample into a template. Args: api: string, name of api. keywords: list of string, list of keywords for the given api. dirname: string, directory name of the sample. desc: string, long description of the sample. uri: string, uri of the sample code if provided in the README. Returns: A dictionary of values useful for template expansion. """ if uri is None: uri = BASE_HG_URI + dirname.replace("/", "%2F") else: uri = "".join(uri) if api is None: return None else: entry = DIRECTORY[api] context = { "api": api, "version": entry["version"], "api_name": wiki_escape(entry.get("title", entry.get("description"))), "api_desc": wiki_escape(entry["description"]), "api_icon": entry["icons"]["x32"], "keywords": keywords, "dir": dirname, "uri": uri, "desc": wiki_escape(desc), } return context def keyword_context_from_sample(keywords, dirname, desc, uri): """Return info for expanding a sample into a template. Sample may not be about a specific api. Args: keywords: list of string, list of keywords for the given api. dirname: string, directory name of the sample. desc: string, long description of the sample. uri: string, uri of the sample code if provided in the README. Returns: A dictionary of values useful for template expansion. """ if uri is None: uri = BASE_HG_URI + dirname.replace("/", "%2F") else: uri = "".join(uri) context = { "keywords": keywords, "dir": dirname, "uri": uri, "desc": wiki_escape(desc), } return context def scan_readme_files(dirname): """Scans all subdirs of dirname for README files. Args: dirname: string, name of directory to walk. Returns: (samples, keyword_set): list of information about all samples, the union of all keywords found. """ samples = [] keyword_set = set() for root, dirs, files in os.walk(dirname): if "README" in files: filename = os.path.join(root, "README") with open(filename, "r") as f: content = f.read() lines = content.splitlines() desc = " ".join(itertools.takewhile(lambda x: x, lines)) api = get_lines("api", lines) keywords = get_lines("keywords", lines) uri = get_lines("uri", lines) if not uri: uri = None for k in keywords: if k not in KEYWORDS: raise ValueError( "%s is not a valid keyword in file %s" % (k, filename) ) keyword_set.update(keywords) if not api: api = [None] samples.append((api[0], keywords, root[1:], desc, uri)) samples.sort() return samples, keyword_set def main(): # Get all the information we need out of the README files in the samples. samples, keyword_set = scan_readme_files("./samples") # Now build a wiki page with all that information. Accumulate all the # information as string to be concatenated when were done. page = ['\n= Samples By API =\n'] # All the samples, grouped by API. current_api = None for api, keywords, dirname, desc, uri in samples: context = context_from_sample(api, keywords, dirname, desc, uri) if context is None: continue if current_api != api: page.append( """ === %(api_icon)s %(api_name)s === %(api_desc)s Documentation for the %(api_name)s in [https://google-api-client-libraries.appspot.com/documentation/%(api)s/%(version)s/python/latest/ PyDoc] """ % context ) current_api = api page.append("|| [%(uri)s %(dir)s] || %(desc)s ||\n" % context) # Now group the samples by keywords. for keyword, keyword_name in KEYWORDS.iteritems(): if keyword not in keyword_set: continue page.append("\n= %s Samples =\n\n" % keyword_name) page.append("\n") for _, keywords, dirname, desc, uri in samples: context = keyword_context_from_sample(keywords, dirname, desc, uri) if keyword not in keywords: continue page.append( """ """ % context ) page.append("
[%(uri)s %(dir)s] %(desc)s
\n") print("".join(page)) if __name__ == "__main__": main()