blob: 3ab0bb5feab8ec21ad6edd67a7f81a0382734e1f [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 Gregorioc5edb3c2011-03-18 10:54:10 -040035from google.appengine.api import memcache
Joe Gregorioc204b642010-09-21 12:01:23 -040036from google.appengine.ext import webapp
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040037from google.appengine.ext.webapp import template
Joe Gregorioc204b642010-09-21 12:01:23 -040038from google.appengine.ext.webapp import util
39
Joe Gregoriod44bb002010-09-21 14:34:44 -040040
Joe Gregorio583d9e42011-09-16 15:54:15 -040041DISCOVERY_URI = 'https://www.googleapis.com/discovery/v1/apis?preferred=true'
42
43
44def get_directory_doc():
45 http = httplib2.Http(memcache)
46 ip = os.environ.get('REMOTE_ADDR', None)
47 uri = DISCOVERY_URI
48 if ip:
49 uri += ('&userIp=' + ip)
50 resp, content = http.request(uri)
51 directory = simplejson.loads(content)['items']
52 return directory
53
54
Joe Gregorioc204b642010-09-21 12:01:23 -040055class MainHandler(webapp.RequestHandler):
Joe Gregorio9c8588a2011-07-01 12:01:36 -040056 """Handles serving the main landing page.
57 """
Joe Gregorioc204b642010-09-21 12:01:23 -040058
59 def get(self):
Joe Gregorio583d9e42011-09-16 15:54:15 -040060 directory = get_directory_doc()
Joe Gregorio6a63a762011-05-02 22:36:05 -040061 for item in directory:
62 item['title'] = item.get('title', item.get('description', ''))
Joe Gregorioc5edb3c2011-03-18 10:54:10 -040063 path = os.path.join(os.path.dirname(__file__), 'index.html')
64 self.response.out.write(
65 template.render(
66 path, {'directory': directory,
67 }))
Joe Gregorioc204b642010-09-21 12:01:23 -040068
Joe Gregorio140062f2010-09-21 16:12:41 -040069
Joe Gregorio9c8588a2011-07-01 12:01:36 -040070class GadgetHandler(webapp.RequestHandler):
71 """Handles serving the Google Gadget.
72 """
73
74 def get(self):
Joe Gregorio583d9e42011-09-16 15:54:15 -040075 directory = get_directory_doc()
Joe Gregorio9c8588a2011-07-01 12:01:36 -040076 for item in directory:
77 item['title'] = item.get('title', item.get('description', ''))
78 path = os.path.join(os.path.dirname(__file__), 'gadget.html')
79 self.response.out.write(
80 template.render(
81 path, {'directory': directory,
82 }))
83 self.response.headers.add_header('Content-Type', 'application/xml')
84
85
86def _render(resource):
87 """Use pydoc helpers on an instance to generate the help documentation.
88 """
Joe Gregorioafc45f22011-02-20 16:11:28 -050089 obj, name = pydoc.resolve(type(resource))
90 return pydoc.html.page(
91 pydoc.describe(obj), pydoc.html.document(obj, name))
92
Joe Gregorioc204b642010-09-21 12:01:23 -040093
Joe Gregorio0fb19e12011-02-22 07:53:24 -050094class ResourceHandler(webapp.RequestHandler):
Joe Gregorio9c8588a2011-07-01 12:01:36 -040095 """Handles serving the PyDoc for a given collection.
96 """
Joe Gregorioc204b642010-09-21 12:01:23 -040097
98 def get(self, service_name, version, collection):
Joe Gregorio583d9e42011-09-16 15:54:15 -040099 http = httplib2.Http(memcache)
100 resource = discovery.build(service_name, version, http=http)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400101 # descend the object path
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500102 if collection:
103 path = collection.split('/')
104 if path:
105 for method in path:
106 resource = getattr(resource, method)()
Joe Gregorio9c8588a2011-07-01 12:01:36 -0400107 page = _render(resource)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400108
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500109 collections = []
110 for name in dir(resource):
111 if not "_" in name and callable(getattr(resource, name)) and hasattr(
112 getattr(resource, name), '__is_resource__'):
113 collections.append(name)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400114
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500115 if collection is None:
116 collection_path = ''
117 else:
118 collection_path = collection + '/'
119 for name in collections:
120 page = re.sub('strong>(%s)<' % name,
121 r'strong><a href="/%s/%s/%s">\1</a><' % (
122 service_name, version, collection_path + name), page)
Joe Gregorio20cfcda2010-10-26 11:58:08 -0400123
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500124 # TODO(jcgregorio) breadcrumbs
125 # TODO(jcgregorio) sample code?
126 page = re.sub('<p>', r'<a href="/">Home</a><p>', page, 1)
Joe Gregorioc204b642010-09-21 12:01:23 -0400127 self.response.out.write(page)
128
Joe Gregorio140062f2010-09-21 16:12:41 -0400129
Joe Gregorioc204b642010-09-21 12:01:23 -0400130def main():
131 application = webapp.WSGIApplication(
132 [
133 (r'/', MainHandler),
Joe Gregorio9c8588a2011-07-01 12:01:36 -0400134 (r'/_gadget/', GadgetHandler),
Joe Gregorio0fb19e12011-02-22 07:53:24 -0500135 (r'/([^\/]*)/([^\/]*)(?:/(.*))?', ResourceHandler),
Joe Gregorioc204b642010-09-21 12:01:23 -0400136 ],
137 debug=True)
138 util.run_wsgi_app(application)
139
140
141if __name__ == '__main__':
142 main()