/src/googlecl/discovery/data.py
Python | 203 lines | 180 code | 4 blank | 19 comment | 6 complexity | 3fa3bf141e963335f313e5a2a0e2b2f2 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""" Subclass which manages data for Discovery 16 17Manages defaults, config values, parsing the arguments, 18and prompting for missing parameters 19Defaults may be viewed/edited by calling 'edit defaults' 20TODO: Integrate ConfigParser 21""" 22 23import logging 24 25import simplejson as json 26import googlecl 27import googlecl.config 28import optparse 29 30LOG = logging.getLogger(googlecl.LOGGER_NAME) 31DEFAULT_FILENAME_FORMAT = 'dcd_%s' 32# Args governing prompting 33META_ARGS = ['prompt', 'editor', 'editmode'] 34# Args that aren't in method parameters 35EXTRA_ARGS = ['fields'] 36 37class DefaultManager: 38 39 def __init__(self, email): 40 self.email = email 41 # Loads config options 42 config = googlecl.config.load_configuration(None) 43 self.client_id = config.lazy_get(None, 'client_id', 44 default='20958643459.apps.googleusercontent.com', option_type=str) 45 self.client_secret = config.lazy_get(None, 'client_secret', 46 default='3D1TrF0sgq52J7zH80jdfbit', option_type=str) 47 self.devkey2 = config.lazy_get(None, 'devkey2', 48 default='AIzaSyAmK-fJLcJ0jS2mMIX5EXgU6M6UPT39e50', option_type=str) 49 # Should make ^ required 50 self.prompt = config.lazy_get(None, 'prompt', 51 default='required', option_type=str) 52 self.editmode = config.lazy_get(None, 'editmode', 53 default='cl', option_type=str) 54 self.formatting = config.lazy_get(None, 'formatting', 55 default='pprint', option_type=str) 56 self.local_apis = config.lazy_get(None, 'local_apis', default='', option_type=str) 57 if '[' in self.local_apis or '(' in self.local_apis: 58 self.local_apis = json.loads(self.local_apis) 59 self.base_url = config.lazy_get(None, 'base_url', default='https://www.googleapis.com', option_type=str) 60 editor = config.safe_get('DOCS', 'document_editor') 61 if not editor: 62 editor = config.safe_get(None, 'editor') 63 if not editor: 64 import os 65 editor = os.getenv('EDITOR') 66 if not editor: 67 editor = 'vim' 68 self.editor = editor 69 70 def fill_out_options(self, metinfo, doc, args): 71 """ Turns a list of arguments into a map of keys/values 72 Starts by doing basic parse, then loads defaults, 73 and finally prompts for missing values 74 75 Args: 76 metinfo: The meta-info for the method, 77 such as the required/optional parameters 78 args: The arguments which are passed in 79 """ 80 parser = optparse.OptionParser() 81 # Set up options 82 for arg in META_ARGS: 83 parser.add_option('--'+arg, default=getattr(self, arg)) 84 for arg in EXTRA_ARGS: 85 parser.add_option('--'+arg) 86 if 'parameters' in metinfo: 87 for arg in metinfo['parameters']: 88 parser.add_option("--"+arg) 89 if 'request' in metinfo: 90 parser.add_option("--body") 91 for arg in doc['schemas'][metinfo['request']['$ref']]['properties']: 92 try: 93 parser.add_option('--'+arg) 94 except optparse.OptionConflictError: 95 pass 96 97 # Parse args 98 (options, args) = parser.parse_args(args) 99 kwargs = vars(options) 100 for arg in kwargs.keys(): 101 if kwargs[arg] == None or kwargs[arg] == '': 102 del kwargs[arg] 103 104 # Loads defaults 105 config = googlecl.config.load_configuration() 106 if config.parser.has_section(metinfo['id']): 107 for arg in config.parser.options(metinfo['id']): 108 if arg not in kwargs: 109 kwargs[arg] = config.get(metinfo['id'], arg) 110 111 # Attaches unmatched values to appropriate keys 112 if args: 113 if not 'parameterOrder' in metinfo: 114 LOG.error('Received unexpected parameter.') 115 return 116 args = dict(zip([i for i in metinfo['parameterOrder'] 117 if i not in kwargs.keys() or kwargs[i] == None],args)) 118 kwargs = dict(kwargs.items() + args.items()) 119 120 # Prompts for missing values 121 if not kwargs['prompt'] == 'none' and 'parameterOrder' in metinfo: 122 for a in metinfo['parameterOrder']: # Required parameters 123 if a not in kwargs: 124 value = raw_input('Please specify ' + a + ': ') 125 if not value: 126 return 127 kwargs[a] = value 128 if kwargs['prompt'] == 'all' and 'parameters' in metinfo: 129 for a in metinfo['parameters']: # Optional parameters 130 if a not in kwargs: 131 value = raw_input('Please specify ' + a + ': ') 132 if value: 133 kwargs[a] = value 134 if kwargs: 135 for arg in kwargs.keys(): 136 if '{' == kwargs[arg][0] or '[' == kwargs[arg][0] or '(' == kwargs[arg][0]: 137 kwargs[arg] = json.loads(kwargs[arg]) 138 139 if 'parameters' in metinfo: 140 pars = set(metinfo['parameters']) 141 else: 142 pars = {} 143 # Assumes that unknown keys are part of body 144 if 'body' not in kwargs and 'request' in metinfo and not set(kwargs.keys()) - set(META_ARGS) - set(EXTRA_ARGS) <= set(pars): 145 body = {} 146 for a in set(kwargs.keys()) - set(pars) - set(META_ARGS) - set(EXTRA_ARGS): 147 body[a] = kwargs[a] 148 del kwargs[a] 149 kwargs['body'] = body 150 151 # Prompts for missing body 152 if not kwargs['prompt'] == 'none' and 'body' not in kwargs and 'request' in metinfo: 153 schemaname = metinfo['request']['$ref'] 154 schema = doc['schemas'][schemaname] 155 if kwargs['editmode'] == 'editor': 156 import subprocess 157 import tempfile 158 import os 159 160 fd, filename = tempfile.mkstemp(text=True) 161 f = open(filename, 'w') 162 body = {} 163 # Assembles the outline of the body 164 # Will modify to use required/mutable args if/when it is available 165 for p in schema['properties']: 166 if 'default' in schema['properties'][p]: 167 body[p] = schema['properties'][p]['default'] 168 elif 'type' in schema['properties'][p]: 169 body[p] = "<"+schema['properties'][p]['type']+">" 170 json.dump(body, f, indent=2) 171 f.close() 172 cmd = '%s %s' % (kwargs['editor'], filename) 173 raw_input('Missing body...') 174 subprocess.call(cmd, shell=True) 175 f = open(filename) 176 value = json.load(f) 177 f.close() 178 os.remove(filename) 179 else: 180 print 'Missing body - Schema: ' + schemaname 181 sargs = ', '.join(schema['properties']) 182 print ' Args: ' + sargs 183 bodyparser = optparse.OptionParser() 184 for arg in doc['schemas'][metinfo['request']['$ref']]['properties']: 185 bodyparser.add_option('--'+arg) 186 (options, args) = bodyparser.parse_args(raw_input('Please specify body: ').split()) 187 value = vars(options) 188 for arg in value.keys(): 189 if value[arg] == None or value[arg] == '': 190 del value[arg] 191 if not value: 192 return 193 kwargs['body'] = value 194 # Get rid of meta-args 195 for arg in META_ARGS: 196 del kwargs[arg] 197 # Can't have '-'s in keys 198 for k in kwargs: 199 if '-' in k: 200 kwargs[k.replace('-','_')] = kwargs[k] 201 del kwargs[k] 202 203 return kwargs