PageRenderTime 483ms CodeModel.GetById 312ms app.highlight 14ms RepoModel.GetById 87ms app.codeStats 0ms

/src/googlecl/discovery/__init__.py

http://googlecl.googlecode.com/
Python | 177 lines | 150 code | 3 blank | 24 comment | 4 complexity | 69af9b8144cf10758b53cdc09ceee214 MD5 | raw file
  1# Copyright (C) 2011 Google Inc.
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7#      http://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14
 15"""Subprogram for GoogleCL which handles all requests 
 16   using the Discovery service
 17
 18This program uses the Discovery API to take interact with other APIs.
 19It is called when GoogleCL cannot identify a requested service as using gdata.
 20Syntax is generally similar to using gdata services.
 21
 22General usage (omitting initial 'google'):
 23  > <service> <method path> <parameters>
 24  > help <service> <path>
 25  > format <service> <method path>
 26
 27Examples:
 28  # Creating a new shortened goo.gl URL
 29  urlshortener insert --body {"longUrl":"<longUrl>"}
 30
 31  # Getting data for a shortened goo.gl URL
 32  urlshortener url get <shortUrl>
 33"""
 34
 35import httplib2
 36import logging
 37
 38import googlecl
 39
 40from apiclient.discovery import build_from_document
 41from googlecl.discovery import authentication
 42from googlecl.discovery import output
 43from googlecl.discovery import data
 44from googlecl.discovery import docs
 45import simplejson as json
 46
 47LOG = logging.getLogger(googlecl.LOGGER_NAME)
 48DISCOVERY_URI = '%s/discovery/v1/apis/{api}/{apiVersion}/rest'
 49
 50class DiscoveryManager():
 51
 52  def __init__(self, email):
 53    self.dataManager = data.DefaultManager(email)
 54    self.docManager = docs.DocManager(self.dataManager.local_apis, self.dataManager.base_url)
 55
 56  def run(self, argv):
 57   try:
 58    """Primary function for the program
 59    Executes methods, displays help, and organizes formatting for services 
 60    using Discovery
 61
 62    Args:
 63      cache: A cache, which may already contain objects to be used
 64      argv: The arguments, parsed into a list as from the command line
 65    """
 66    # Determines if the help, format, or default is being called
 67    LOG.debug('Running Discovery...')
 68    isHelp = argv[0]=='help'
 69    verbose = False
 70    if isHelp:
 71      argv = argv[1:]
 72      if argv[-1] == '--verbose' or argv[-1] == '-v':
 73        verbose = True
 74        argv = argv[:-1]
 75
 76    http = httplib2.Http()
 77    
 78    LOG.debug('Parsing service...')
 79    # Fetches service, version, docs, etc. 
 80    try:
 81      servicename, version, doc, args = self.docManager.run(argv, isHelp,
 82                                                            verbose)
 83    except TypeError:
 84      return
 85
 86    LOG.debug('Managing auth...')
 87    # Checks if credentials are needed and, if so, whether they are possessed.
 88    # If not, gets appropriate credentials.
 89    if 'auth' in doc:
 90      if '--force-auth' in args:
 91        args.remove('--force-auth')
 92        force_auth = True
 93      else:
 94        force_auth = False
 95      http = authentication.authenticate(self.dataManager.email, servicename, doc, http,
 96        self.dataManager.client_id, self.dataManager.client_secret, force_auth)
 97
 98      # Builds the service and finds the method
 99      service = build_from_document(json.dumps(doc), DISCOVERY_URI % self.dataManager.base_url, http=http)
100    else:
101      service = build_from_document(json.dumps(doc), DISCOVERY_URI % self.dataManager.base_url,
102                      developerKey=self.dataManager.devkey2, http=http)
103    LOG.debug('Determining task...')
104    try:
105      metinfo, method, args = getMethod(service, doc, args)
106    except:
107      #LOG.error('Did not recognize task.')
108      return
109
110    LOG.debug('Parsing parameters...')
111    try:
112      kwargs = self.dataManager.fill_out_options(metinfo, doc, args)
113    except TypeError, err:
114      raise
115      return
116
117    LOG.debug('Executing method...')
118    try:
119      resp = method(**kwargs).execute()
120    except Exception, err:
121      LOG.error(err)
122      return
123
124    LOG.debug('Displaying output...')
125    # Displays formatted output
126    output.output(resp, self.dataManager.formatting)
127   except Exception, err:
128    print 'Uncaught error'
129    raise
130
131  def apis_list(self):
132    # Returns a list of the APIs that may be used
133    return [str(d['name']) for d in self.docManager.directory['items']]
134
135def getMethod(service, doc, args):
136  """ Locates the method to be executed 
137  Capable of finding some methods implicitly
138  Displays assistance if method isn't identified
139
140  Args:
141    service: The service object being used
142    doc: Documentation describing the service
143    args: List containing the method path to be followed
144
145  Returns:
146    A tuple of the meta-info describing the method, 
147    the method itself, and the parameters for the method
148  """
149  obj = doc
150  attr = service
151  i = 0
152  while 'resources' in obj or 'methods' in obj:
153    if i < len(args) and 'resources' in obj and args[i] in obj['resources']:
154      attr = getattr(attr, args[i])
155      obj = obj['resources'][args[i]]
156      i=i+1
157    elif i < len(args) and 'methods' in obj and args[i] in obj['methods']:
158      attr = getattr(attr, args[i])
159      obj = obj['methods'][args[i]]
160      i=i+1
161    elif ('resources' in obj and not 'methods' in obj and
162        len(obj['resources'])==1):
163      attr = getattr(attr, obj['resources'].keys()[0])
164      obj = obj['resources'][obj['resources'].keys()[0]]
165    elif 'methods' in obj and not 'resources' in obj and len(obj['methods'])==1:
166      attr = getattr(attr, obj['methods'].keys()[0])
167      obj = obj['methods'][obj['methods'].keys()[0]]
168    else:
169      print 'Did not recognize task.'
170      if 'methods' in obj:
171        LOG.error('Possible methods: ' + ', '.join(obj['methods']))
172      if 'resources' in obj:
173        LOG.error('Possible resources: ' + ', '.join(obj['resources']))
174      return
175    if not 'id' in obj:
176      attr = attr()
177  return obj, attr, args[i:]