Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1311)

Unified Diff: boto/roboto/awsqueryrequest.py

Issue 8386013: Merging in latest boto. (Closed) Base URL: svn://svn.chromium.org/boto
Patch Set: Redoing vendor drop by deleting and then merging. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « boto/roboto/__init__.py ('k') | boto/roboto/awsqueryservice.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: boto/roboto/awsqueryrequest.py
diff --git a/boto/roboto/awsqueryrequest.py b/boto/roboto/awsqueryrequest.py
new file mode 100644
index 0000000000000000000000000000000000000000..9e05ac638e7e732061a9550b1147a9a6d0b28274
--- /dev/null
+++ b/boto/roboto/awsqueryrequest.py
@@ -0,0 +1,504 @@
+# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/
+# Copyright (c) 2010, Eucalyptus Systems, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish, dis-
+# tribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to the fol-
+# lowing conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+import sys
+import os
+import boto
+import optparse
+import copy
+import boto.exception
+import boto.roboto.awsqueryservice
+
+import bdb
+import traceback
+try:
+ import epdb as debugger
+except ImportError:
+ import pdb as debugger
+
+def boto_except_hook(debugger_flag, debug_flag):
+ def excepthook(typ, value, tb):
+ if typ is bdb.BdbQuit:
+ sys.exit(1)
+ sys.excepthook = sys.__excepthook__
+
+ if debugger_flag and sys.stdout.isatty() and sys.stdin.isatty():
+ if debugger.__name__ == 'epdb':
+ debugger.post_mortem(tb, typ, value)
+ else:
+ debugger.post_mortem(tb)
+ elif debug_flag:
+ print traceback.print_tb(tb)
+ sys.exit(1)
+ else:
+ print value
+ sys.exit(1)
+
+ return excepthook
+
+class Line(object):
+
+ def __init__(self, fmt, data, label):
+ self.fmt = fmt
+ self.data = data
+ self.label = label
+ self.line = '%s\t' % label
+ self.printed = False
+
+ def append(self, datum):
+ self.line += '%s\t' % datum
+
+ def print_it(self):
+ if not self.printed:
+ print self.line
+ self.printed = True
+
+class RequiredParamError(boto.exception.BotoClientError):
+
+ def __init__(self, required):
+ self.required = required
+ s = 'Required parameters are missing: %s' % self.required
+ boto.exception.BotoClientError.__init__(self, s)
+
+class EncoderError(boto.exception.BotoClientError):
+
+ def __init__(self, error_msg):
+ s = 'Error encoding value (%s)' % error_msg
+ boto.exception.BotoClientError.__init__(self, s)
+
+class FilterError(boto.exception.BotoClientError):
+
+ def __init__(self, filters):
+ self.filters = filters
+ s = 'Unknown filters: %s' % self.filters
+ boto.exception.BotoClientError.__init__(self, s)
+
+class Encoder:
+
+ @classmethod
+ def encode(cls, p, rp, v, label=None):
+ if p.name.startswith('_'):
+ return
+ try:
+ mthd = getattr(cls, 'encode_'+p.ptype)
+ mthd(p, rp, v, label)
+ except AttributeError:
+ raise EncoderError('Unknown type: %s' % p.ptype)
+
+ @classmethod
+ def encode_string(cls, p, rp, v, l):
+ if l:
+ label = l
+ else:
+ label = p.name
+ rp[label] = v
+
+ encode_file = encode_string
+ encode_enum = encode_string
+
+ @classmethod
+ def encode_integer(cls, p, rp, v, l):
+ if l:
+ label = l
+ else:
+ label = p.name
+ rp[label] = '%d' % v
+
+ @classmethod
+ def encode_boolean(cls, p, rp, v, l):
+ if l:
+ label = l
+ else:
+ label = p.name
+ if v:
+ v = 'true'
+ else:
+ v = 'false'
+ rp[label] = v
+
+ @classmethod
+ def encode_datetime(cls, p, rp, v, l):
+ if l:
+ label = l
+ else:
+ label = p.name
+ rp[label] = v
+
+ @classmethod
+ def encode_array(cls, p, rp, v, l):
+ v = boto.utils.mklist(v)
+ if l:
+ label = l
+ else:
+ label = p.name
+ label = label + '.%d'
+ for i, value in enumerate(v):
+ rp[label%(i+1)] = value
+
+class AWSQueryRequest(object):
+
+ ServiceClass = None
+
+ Description = ''
+ Params = []
+ Args = []
+ Filters = []
+ Response = {}
+
+ CLITypeMap = {'string' : 'string',
+ 'integer' : 'int',
+ 'int' : 'int',
+ 'enum' : 'choice',
+ 'datetime' : 'string',
+ 'dateTime' : 'string',
+ 'file' : 'string',
+ 'boolean' : None}
+
+ @classmethod
+ def name(cls):
+ return cls.__name__
+
+ def __init__(self, **args):
+ self.args = args
+ self.parser = None
+ self.cli_options = None
+ self.cli_args = None
+ self.cli_output_format = None
+ self.connection = None
+ self.list_markers = []
+ self.item_markers = []
+ self.request_params = {}
+ self.connection_args = None
+
+ def __repr__(self):
+ return self.name()
+
+ def get_connection(self, **args):
+ if self.connection is None:
+ self.connection = self.ServiceClass(**args)
+ return self.connection
+
+ @property
+ def status(self):
+ retval = None
+ if self.http_response is not None:
+ retval = self.http_response.status
+ return retval
+
+ @property
+ def reason(self):
+ retval = None
+ if self.http_response is not None:
+ retval = self.http_response.reason
+ return retval
+
+ @property
+ def request_id(self):
+ retval = None
+ if self.aws_response is not None:
+ retval = getattr(self.aws_response, 'requestId')
+ return retval
+
+ def process_filters(self):
+ filters = self.args.get('filters', [])
+ filter_names = [f['name'] for f in self.Filters]
+ unknown_filters = [f for f in filters if f not in filter_names]
+ if unknown_filters:
+ raise FilterError, 'Unknown filters: %s' % unknown_filters
+ for i, filter in enumerate(self.Filters):
+ name = filter['name']
+ if name in filters:
+ self.request_params['Filter.%d.Name' % (i+1)] = name
+ for j, value in enumerate(boto.utils.mklist(filters[name])):
+ Encoder.encode(filter, self.request_params, value,
+ 'Filter.%d.Value.%d' % (i+1,j+1))
+
+ def process_args(self, **args):
+ """
+ Responsible for walking through Params defined for the request and:
+
+ * Matching them with keyword parameters passed to the request
+ constructor or via the command line.
+ * Checking to see if all required parameters have been specified
+ and raising an exception, if not.
+ * Encoding each value into the set of request parameters that will
+ be sent in the request to the AWS service.
+ """
+ self.args.update(args)
+ self.connection_args = copy.copy(self.args)
+ if 'debug' in self.args and self.args['debug'] >= 2:
+ boto.set_stream_logger(self.name())
+ required = [p.name for p in self.Params+self.Args if not p.optional]
+ for param in self.Params+self.Args:
+ if param.long_name:
+ python_name = param.long_name.replace('-', '_')
+ else:
+ python_name = boto.utils.pythonize_name(param.name, '_')
+ value = None
+ if python_name in self.args:
+ value = self.args[python_name]
+ if value is None:
+ value = param.default
+ if value is not None:
+ if param.name in required:
+ required.remove(param.name)
+ if param.request_param:
+ if param.encoder:
+ param.encoder(param, self.request_params, value)
+ else:
+ Encoder.encode(param, self.request_params, value)
+ if python_name in self.args:
+ del self.connection_args[python_name]
+ if required:
+ l = []
+ for p in self.Params+self.Args:
+ if p.name in required:
+ if p.short_name and p.long_name:
+ l.append('(%s, %s)' % (p.optparse_short_name,
+ p.optparse_long_name))
+ elif p.short_name:
+ l.append('(%s)' % p.optparse_short_name)
+ else:
+ l.append('(%s)' % p.optparse_long_name)
+ raise RequiredParamError(','.join(l))
+ boto.log.debug('request_params: %s' % self.request_params)
+ self.process_markers(self.Response)
+
+ def process_markers(self, fmt, prev_name=None):
+ if fmt and fmt['type'] == 'object':
+ for prop in fmt['properties']:
+ self.process_markers(prop, fmt['name'])
+ elif fmt and fmt['type'] == 'array':
+ self.list_markers.append(prev_name)
+ self.item_markers.append(fmt['name'])
+
+ def send(self, verb='GET', **args):
+ self.process_args(**args)
+ self.process_filters()
+ conn = self.get_connection(**self.connection_args)
+ self.http_response = conn.make_request(self.name(),
+ self.request_params,
+ verb=verb)
+ self.body = self.http_response.read()
+ boto.log.debug(self.body)
+ if self.http_response.status == 200:
+ self.aws_response = boto.jsonresponse.Element(list_marker=self.list_markers,
+ item_marker=self.item_markers)
+ h = boto.jsonresponse.XmlHandler(self.aws_response, self)
+ h.parse(self.body)
+ return self.aws_response
+ else:
+ boto.log.error('%s %s' % (self.http_response.status,
+ self.http_response.reason))
+ boto.log.error('%s' % self.body)
+ raise conn.ResponseError(self.http_response.status,
+ self.http_response.reason,
+ self.body)
+
+ def add_standard_options(self):
+ group = optparse.OptionGroup(self.parser, 'Standard Options')
+ # add standard options that all commands get
+ group.add_option('-D', '--debug', action='store_true',
+ help='Turn on all debugging output')
+ group.add_option('--debugger', action='store_true',
+ default=False,
+ help='Enable interactive debugger on error')
+ group.add_option('-U', '--url', action='store',
+ help='Override service URL with value provided')
+ group.add_option('--region', action='store',
+ help='Name of the region to connect to')
+ group.add_option('-I', '--access-key-id', action='store',
+ help='Override access key value')
+ group.add_option('-S', '--secret-key', action='store',
+ help='Override secret key value')
+ group.add_option('--version', action='store_true',
+ help='Display version string')
+ if self.Filters:
+ self.group.add_option('--help-filters', action='store_true',
+ help='Display list of available filters')
+ self.group.add_option('--filter', action='append',
+ metavar=' name=value',
+ help='A filter for limiting the results')
+ self.parser.add_option_group(group)
+
+ def process_standard_options(self, options, args, d):
+ if hasattr(options, 'help_filters') and options.help_filters:
+ print 'Available filters:'
+ for filter in self.Filters:
+ print '%s\t%s' % (filter.name, filter.doc)
+ sys.exit(0)
+ if options.debug:
+ self.args['debug'] = 2
+ if options.url:
+ self.args['url'] = options.url
+ if options.region:
+ self.args['region'] = options.region
+ if options.access_key_id:
+ self.args['aws_access_key_id'] = options.access_key_id
+ if options.secret_key:
+ self.args['aws_secret_access_key'] = options.secret_key
+ if options.version:
+ # TODO - Where should the version # come from?
+ print 'version x.xx'
+ exit(0)
+ sys.excepthook = boto_except_hook(options.debugger,
+ options.debug)
+
+ def get_usage(self):
+ s = 'usage: %prog [options] '
+ l = [ a.long_name for a in self.Args ]
+ s += ' '.join(l)
+ for a in self.Args:
+ if a.doc:
+ s += '\n\n\t%s - %s' % (a.long_name, a.doc)
+ return s
+
+ def build_cli_parser(self):
+ self.parser = optparse.OptionParser(description=self.Description,
+ usage=self.get_usage())
+ self.add_standard_options()
+ for param in self.Params:
+ ptype = action = choices = None
+ if param.ptype in self.CLITypeMap:
+ ptype = self.CLITypeMap[param.ptype]
+ action = 'store'
+ if param.ptype == 'boolean':
+ action = 'store_true'
+ elif param.ptype == 'array':
+ if len(param.items) == 1:
+ ptype = param.items[0]['type']
+ action = 'append'
+ elif param.cardinality != 1:
+ action = 'append'
+ if ptype or action == 'store_true':
+ if param.short_name:
+ self.parser.add_option(param.optparse_short_name,
+ param.optparse_long_name,
+ action=action, type=ptype,
+ choices=param.choices,
+ help=param.doc)
+ elif param.long_name:
+ self.parser.add_option(param.optparse_long_name,
+ action=action, type=ptype,
+ choices=param.choices,
+ help=param.doc)
+
+ def do_cli(self):
+ if not self.parser:
+ self.build_cli_parser()
+ self.cli_options, self.cli_args = self.parser.parse_args()
+ d = {}
+ self.process_standard_options(self.cli_options, self.cli_args, d)
+ for param in self.Params:
+ if param.long_name:
+ p_name = param.long_name.replace('-', '_')
+ else:
+ p_name = boto.utils.pythonize_name(param.name)
+ value = getattr(self.cli_options, p_name)
+ if param.ptype == 'file' and value:
+ if value == '-':
+ value = sys.stdin.read()
+ else:
+ path = os.path.expanduser(value)
+ path = os.path.expandvars(path)
+ if os.path.isfile(path):
+ fp = open(path)
+ value = fp.read()
+ fp.close()
+ else:
+ self.parser.error('Unable to read file: %s' % path)
+ d[p_name] = value
+ for arg in self.Args:
+ if arg.long_name:
+ p_name = arg.long_name.replace('-', '_')
+ else:
+ p_name = boto.utils.pythonize_name(arg.name)
+ value = None
+ if arg.cardinality == 1:
+ if len(self.cli_args) >= 1:
+ value = self.cli_args[0]
+ else:
+ value = self.cli_args
+ d[p_name] = value
+ self.args.update(d)
+ if hasattr(self.cli_options, 'filter') and self.cli_options.filter:
+ d = {}
+ for filter in self.cli_options.filter:
+ name, value = filter.split('=')
+ d[name] = value
+ if 'filters' in self.args:
+ self.args['filters'].update(d)
+ else:
+ self.args['filters'] = d
+ try:
+ response = self.main()
+ self.cli_formatter(response)
+ except RequiredParamError, e:
+ print e
+ sys.exit(1)
+ except self.ServiceClass.ResponseError, err:
+ print 'Error(%s): %s' % (err.error_code, err.error_message)
+ sys.exit(1)
+ except boto.roboto.awsqueryservice.NoCredentialsError, err:
+ print 'Unable to find credentials.'
+ sys.exit(1)
+ except Exception, e:
+ print e
+ sys.exit(1)
+
+ def _generic_cli_formatter(self, fmt, data, label=''):
+ if fmt['type'] == 'object':
+ for prop in fmt['properties']:
+ if 'name' in fmt:
+ if fmt['name'] in data:
+ data = data[fmt['name']]
+ if fmt['name'] in self.list_markers:
+ label = fmt['name']
+ if label[-1] == 's':
+ label = label[0:-1]
+ label = label.upper()
+ self._generic_cli_formatter(prop, data, label)
+ elif fmt['type'] == 'array':
+ for item in data:
+ line = Line(fmt, item, label)
+ if isinstance(item, dict):
+ for field_name in item:
+ line.append(item[field_name])
+ elif isinstance(item, basestring):
+ line.append(item)
+ line.print_it()
+
+ def cli_formatter(self, data):
+ """
+ This method is responsible for formatting the output for the
+ command line interface. The default behavior is to call the
+ generic CLI formatter which attempts to print something
+ reasonable. If you want specific formatting, you should
+ override this method and do your own thing.
+
+ :type data: dict
+ :param data: The data returned by AWS.
+ """
+ if data:
+ self._generic_cli_formatter(self.Response, data)
+
+
« no previous file with comments | « boto/roboto/__init__.py ('k') | boto/roboto/awsqueryservice.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698