blob: 888c32e33f1c01fe2befd3334d74080b0690fa61 [file] [log] [blame]
Joe Gregorioc204b642010-09-21 12:01:23 -04001#!/usr/bin/env python
2#
Joe Gregorio9c8588a2011-07-01 12:01:36 -04003# Copyright 2011 Google Inc.
Joe Gregorioc204b642010-09-21 12:01:23 -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 Gregorio9c8588a2011-07-01 12:01:36 -040017"""Sample application for Python documentation of APIs.
18
19This is running live at http://api-python-client-doc.appspot.com where it
20provides a list of APIs and PyDoc documentation for all the generated API
21surfaces as they appear in the google-api-python-client. In addition it also
22provides a Google Gadget.
23"""
Joe Gregorioc204b642010-09-21 12:01:23 -040024
25__author__ = 'jcgregorio@google.com (Joe Gregorio)'
26
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040027import httplib2
Joe Gregoriod44bb002010-09-21 14:34:44 -040028import inspect
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040029import os
Joe Gregorioc204b642010-09-21 12:01:23 -040030import pydoc
31import re
32
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040033from apiclient.anyjson import simplejson
Joe Gregorio9c8588a2011-07-01 12:01:36 -040034from apiclient import discovery
Joe Gregorio985e5402011-12-08 12:21:14 -050035from apiclient.errors import HttpError
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040036from google.appengine.api import memcache
Joe Gregorioc204b642010-09-21 12:01:23 -040037from google.appengine.ext import webapp
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040038from google.appengine.ext.webapp import template
Joe Gregorioc204b642010-09-21 12:01:23 -040039from google.appengine.ext.webapp import util
40
Joe Gregoriod44bb002010-09-21 14:34:44 -040041
Joe Gregorio583d9e42011-09-16 15:54:15 -040042DISCOVERY_URI = 'https://www.googleapis.com/discovery/v1/apis?preferred=true'
43
44
45def get_directory_doc():
46 http = httplib2.Http(memcache)
47 ip = os.environ.get('REMOTE_ADDR', None)
48 uri = DISCOVERY_URI
49 if ip:
50 uri += ('&userIp=' + ip)
51 resp, content = http.request(uri)
52 directory = simplejson.loads(content)['items']
53 return directory
54
55
Joe Gregorioc204b642010-09-21 12:01:23 -040056class MainHandler(webapp.RequestHandler):
Joe Gregorio9c8588a2011-07-01 12:01:36 -040057 """Handles serving the main landing page.
58 """
Joe Gregorioc204b642010-09-21 12:01:23 -040059
60 def get(self):
Joe Gregorio583d9e42011-09-16 15:54:15 -040061 directory = get_directory_doc()
Joe Gregorio6a63a762011-05-02 22:36:05 -040062 for item in directory:
63 item['title'] = item.get('title', item.get('description', ''))
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040064 path = os.path.join(os.path.dirname(__file__), 'index.html')
65 self.response.out.write(
66 template.render(
67 path, {'directory': directory,
68 }))
Joe Gregorioc204b642010-09-21 12:01:23 -040069
Joe Gregorio140062f2010-09-21 16:12:41 -040070
Joe Gregorio9c8588a2011-07-01 12:01:36 -040071class GadgetHandler(webapp.RequestHandler):
72 """Handles serving the Google Gadget.
73 """
74
75 def get(self):
Joe Gregorio583d9e42011-09-16 15:54:15 -040076 directory = get_directory_doc()
Joe Gregorio9c8588a2011-07-01 12:01:36 -040077 for item in directory:
78 item['title'] = item.get('title', item.get('description', ''))
79 path = os.path.join(os.path.dirname(__file__), 'gadget.html')
80 self.response.out.write(
81 template.render(
82 path, {'directory': directory,
83 }))
84 self.response.headers.add_header('Content-Type', 'application/xml')
85
86
87def _render(resource):
88 """Use pydoc helpers on an instance to generate the help documentation.
89 """
Joe Gregorioafc45f22011-02-20 16:11:28 -050090 obj, name = pydoc.resolve(type(resource))
91 return pydoc.html.page(
92 pydoc.describe(obj), pydoc.html.document(obj, name))
93
Joe Gregorioc204b642010-09-21 12:01:23 -040094
Joe Gregorio0fb19e12011-02-22 07:53:24 -050095class ResourceHandler(webapp.RequestHandler):
Joe Gregorio9c8588a2011-07-01 12:01:36 -040096 """Handles serving the PyDoc for a given collection.
97 """
Joe Gregorioc204b642010-09-21 12:01:23 -040098
99 def get(self, service_name, version, collection):
Joe Gregorio583d9e42011-09-16 15:54:15 -0400100 http = httplib2.Http(memcache)
Joe Gregorio985e5402011-12-08 12:21:14 -0500101 try:
102 resource = discovery.build(service_name, version, http=http)
103 except:
104 return self.error(404)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400105 # descend the object path
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500106 if collection:
Joe Gregorio985e5402011-12-08 12:21:14 -0500107 try:
108 path = collection.split('/')
109 if path:
110 for method in path:
111 resource = getattr(resource, method)()
112 except:
113 return self.error(404)
114
Joe Gregorio9c8588a2011-07-01 12:01:36 -0400115 page = _render(resource)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400116
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500117 collections = []
118 for name in dir(resource):
119 if not "_" in name and callable(getattr(resource, name)) and hasattr(
120 getattr(resource, name), '__is_resource__'):
121 collections.append(name)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400122
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500123 if collection is None:
124 collection_path = ''
125 else:
126 collection_path = collection + '/'
127 for name in collections:
128 page = re.sub('strong>(%s)<' % name,
129 r'strong><a href="/%s/%s/%s">\1</a><' % (
130 service_name, version, collection_path + name), page)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400131
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500132 # TODO(jcgregorio) breadcrumbs
133 # TODO(jcgregorio) sample code?
134 page = re.sub('<p>', r'<a href="/">Home</a><p>', page, 1)
Joe Gregorioc204b642010-09-21 12:01:23 -0400135 self.response.out.write(page)
136
Joe Gregorio140062f2010-09-21 16:12:41 -0400137
Joe Gregorioc204b642010-09-21 12:01:23 -0400138def main():
139 application = webapp.WSGIApplication(
140 [
141 (r'/', MainHandler),
Joe Gregorio9c8588a2011-07-01 12:01:36 -0400142 (r'/_gadget/', GadgetHandler),
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500143 (r'/([^\/]*)/([^\/]*)(?:/(.*))?', ResourceHandler),
Joe Gregorioc204b642010-09-21 12:01:23 -0400144 ],
Joe Gregorio985e5402011-12-08 12:21:14 -0500145 debug=False)
Joe Gregorioc204b642010-09-21 12:01:23 -0400146 util.run_wsgi_app(application)
147
148
149if __name__ == '__main__':
150 main()