/src/googlecl/discovery/__init__.py
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:]