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

Side by Side Diff: third_party/gsutil/boto/dynamodb/table.py

Issue 12042069: Scripts to download files from google storage based on sha1 sums (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Removed gsutil/tests and gsutil/docs Created 7 years, 10 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 unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright (c) 2012 Mitch Garnaat http://garnaat.org/
2 # Copyright (c) 2012 Amazon.com, Inc. or its affiliates. All Rights Reserved
3 #
4 # Permission is hereby granted, free of charge, to any person obtaining a
5 # copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish, dis-
8 # tribute, sublicense, and/or sell copies of the Software, and to permit
9 # persons to whom the Software is furnished to do so, subject to the fol-
10 # lowing conditions:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 # IN THE SOFTWARE.
22 #
23
24 from boto.dynamodb.batch import BatchList
25 from boto.dynamodb.schema import Schema
26 from boto.dynamodb.item import Item
27 from boto.dynamodb import exceptions as dynamodb_exceptions
28 import time
29
30 class TableBatchGenerator(object):
31 """
32 A low-level generator used to page through results from
33 batch_get_item operations.
34
35 :ivar consumed_units: An integer that holds the number of
36 ConsumedCapacityUnits accumulated thus far for this
37 generator.
38 """
39
40 def __init__(self, table, keys, attributes_to_get=None, consistent_read=Fals e):
41 self.table = table
42 self.keys = keys
43 self.consumed_units = 0
44 self.attributes_to_get = attributes_to_get
45 self.consistent_read = consistent_read
46
47 def _queue_unprocessed(self, res):
48 if not u'UnprocessedKeys' in res:
49 return
50 if not self.table.name in res[u'UnprocessedKeys']:
51 return
52
53 keys = res[u'UnprocessedKeys'][self.table.name][u'Keys']
54
55 for key in keys:
56 h = key[u'HashKeyElement']
57 r = key[u'RangeKeyElement'] if u'RangeKeyElement' in key else None
58 self.keys.append((h, r))
59
60 def __iter__(self):
61 while self.keys:
62 # Build the next batch
63 batch = BatchList(self.table.layer2)
64 batch.add_batch(self.table, self.keys[:100], self.attributes_to_get)
65 res = batch.submit()
66
67 # parse the results
68 if not self.table.name in res[u'Responses']:
69 continue
70 self.consumed_units += res[u'Responses'][self.table.name][u'Consumed CapacityUnits']
71 for elem in res[u'Responses'][self.table.name][u'Items']:
72 yield elem
73
74 # re-queue un processed keys
75 self.keys = self.keys[100:]
76 self._queue_unprocessed(res)
77
78
79 class Table(object):
80 """
81 An Amazon DynamoDB table.
82
83 :ivar name: The name of the table.
84 :ivar create_time: The date and time that the table was created.
85 :ivar status: The current status of the table. One of:
86 'ACTIVE', 'UPDATING', 'DELETING'.
87 :ivar schema: A :class:`boto.dynamodb.schema.Schema` object representing
88 the schema defined for the table.
89 :ivar item_count: The number of items in the table. This value is
90 set only when the Table object is created or refreshed and
91 may not reflect the actual count.
92 :ivar size_bytes: Total size of the specified table, in bytes.
93 Amazon DynamoDB updates this value approximately every six hours.
94 Recent changes might not be reflected in this value.
95 :ivar read_units: The ReadCapacityUnits of the tables
96 Provisioned Throughput.
97 :ivar write_units: The WriteCapacityUnits of the tables
98 Provisioned Throughput.
99 :ivar schema: The Schema object associated with the table.
100 """
101
102 def __init__(self, layer2, response):
103 """
104
105 :type layer2: :class:`boto.dynamodb.layer2.Layer2`
106 :param layer2: A `Layer2` api object.
107
108 :type response: dict
109 :param response: The output of
110 `boto.dynamodb.layer1.Layer1.describe_table`.
111
112 """
113 self.layer2 = layer2
114 self._dict = {}
115 self.update_from_response(response)
116
117 def __repr__(self):
118 return 'Table(%s)' % self.name
119
120 @property
121 def name(self):
122 return self._dict['TableName']
123
124 @property
125 def create_time(self):
126 return self._dict['CreationDateTime']
127
128 @property
129 def status(self):
130 return self._dict['TableStatus']
131
132 @property
133 def item_count(self):
134 return self._dict.get('ItemCount', 0)
135
136 @property
137 def size_bytes(self):
138 return self._dict.get('TableSizeBytes', 0)
139
140 @property
141 def schema(self):
142 return self._schema
143
144 @property
145 def read_units(self):
146 return self._dict['ProvisionedThroughput']['ReadCapacityUnits']
147
148 @property
149 def write_units(self):
150 return self._dict['ProvisionedThroughput']['WriteCapacityUnits']
151
152 def update_from_response(self, response):
153 """
154 Update the state of the Table object based on the response
155 data received from Amazon DynamoDB.
156 """
157 if 'Table' in response:
158 self._dict.update(response['Table'])
159 elif 'TableDescription' in response:
160 self._dict.update(response['TableDescription'])
161 if 'KeySchema' in self._dict:
162 self._schema = Schema(self._dict['KeySchema'])
163
164 def refresh(self, wait_for_active=False, retry_seconds=5):
165 """
166 Refresh all of the fields of the Table object by calling
167 the underlying DescribeTable request.
168
169 :type wait_for_active: bool
170 :param wait_for_active: If True, this command will not return
171 until the table status, as returned from Amazon DynamoDB, is
172 'ACTIVE'.
173
174 :type retry_seconds: int
175 :param retry_seconds: If wait_for_active is True, this
176 parameter controls the number of seconds of delay between
177 calls to update_table in Amazon DynamoDB. Default is 5 seconds.
178 """
179 done = False
180 while not done:
181 response = self.layer2.describe_table(self.name)
182 self.update_from_response(response)
183 if wait_for_active:
184 if self.status == 'ACTIVE':
185 done = True
186 else:
187 time.sleep(retry_seconds)
188 else:
189 done = True
190
191 def update_throughput(self, read_units, write_units):
192 """
193 Update the ProvisionedThroughput for the Amazon DynamoDB Table.
194
195 :type read_units: int
196 :param read_units: The new value for ReadCapacityUnits.
197
198 :type write_units: int
199 :param write_units: The new value for WriteCapacityUnits.
200 """
201 self.layer2.update_throughput(self, read_units, write_units)
202
203 def delete(self):
204 """
205 Delete this table and all items in it. After calling this
206 the Table objects status attribute will be set to 'DELETING'.
207 """
208 self.layer2.delete_table(self)
209
210 def get_item(self, hash_key, range_key=None,
211 attributes_to_get=None, consistent_read=False,
212 item_class=Item):
213 """
214 Retrieve an existing item from the table.
215
216 :type hash_key: int|long|float|str|unicode
217 :param hash_key: The HashKey of the requested item. The
218 type of the value must match the type defined in the
219 schema for the table.
220
221 :type range_key: int|long|float|str|unicode
222 :param range_key: The optional RangeKey of the requested item.
223 The type of the value must match the type defined in the
224 schema for the table.
225
226 :type attributes_to_get: list
227 :param attributes_to_get: A list of attribute names.
228 If supplied, only the specified attribute names will
229 be returned. Otherwise, all attributes will be returned.
230
231 :type consistent_read: bool
232 :param consistent_read: If True, a consistent read
233 request is issued. Otherwise, an eventually consistent
234 request is issued.
235
236 :type item_class: Class
237 :param item_class: Allows you to override the class used
238 to generate the items. This should be a subclass of
239 :class:`boto.dynamodb.item.Item`
240 """
241 return self.layer2.get_item(self, hash_key, range_key,
242 attributes_to_get, consistent_read,
243 item_class)
244 lookup = get_item
245
246 def has_item(self, hash_key, range_key=None, consistent_read=False):
247 """
248 Checks the table to see if the Item with the specified ``hash_key``
249 exists. This may save a tiny bit of time/bandwidth over a
250 straight :py:meth:`get_item` if you have no intention to touch
251 the data that is returned, since this method specifically tells
252 Amazon not to return anything but the Item's key.
253
254 :type hash_key: int|long|float|str|unicode
255 :param hash_key: The HashKey of the requested item. The
256 type of the value must match the type defined in the
257 schema for the table.
258
259 :type range_key: int|long|float|str|unicode
260 :param range_key: The optional RangeKey of the requested item.
261 The type of the value must match the type defined in the
262 schema for the table.
263
264 :type consistent_read: bool
265 :param consistent_read: If True, a consistent read
266 request is issued. Otherwise, an eventually consistent
267 request is issued.
268
269 :rtype: bool
270 :returns: ``True`` if the Item exists, ``False`` if not.
271 """
272 try:
273 # Attempt to get the key. If it can't be found, it'll raise
274 # an exception.
275 self.get_item(hash_key, range_key=range_key,
276 # This minimizes the size of the response body.
277 attributes_to_get=[hash_key],
278 consistent_read=consistent_read)
279 except dynamodb_exceptions.DynamoDBKeyNotFoundError:
280 # Key doesn't exist.
281 return False
282 return True
283
284 def new_item(self, hash_key=None, range_key=None, attrs=None,
285 item_class=Item):
286 """
287 Return an new, unsaved Item which can later be PUT to
288 Amazon DynamoDB.
289
290 This method has explicit (but optional) parameters for
291 the hash_key and range_key values of the item. You can use
292 these explicit parameters when calling the method, such as::
293
294 >>> my_item = my_table.new_item(hash_key='a', range_key=1,
295 attrs={'key1': 'val1', 'key2': 'val2'})
296 >>> my_item
297 {u'bar': 1, u'foo': 'a', 'key1': 'val1', 'key2': 'val2'}
298
299 Or, if you prefer, you can simply put the hash_key and range_key
300 in the attrs dictionary itself, like this::
301
302 >>> attrs = {'foo': 'a', 'bar': 1, 'key1': 'val1', 'key2': 'val2'}
303 >>> my_item = my_table.new_item(attrs=attrs)
304 >>> my_item
305 {u'bar': 1, u'foo': 'a', 'key1': 'val1', 'key2': 'val2'}
306
307 The effect is the same.
308
309 .. note:
310 The explicit parameters take priority over the values in
311 the attrs dict. So, if you have a hash_key or range_key
312 in the attrs dict and you also supply either or both using
313 the explicit parameters, the values in the attrs will be
314 ignored.
315
316 :type hash_key: int|long|float|str|unicode
317 :param hash_key: The HashKey of the new item. The
318 type of the value must match the type defined in the
319 schema for the table.
320
321 :type range_key: int|long|float|str|unicode
322 :param range_key: The optional RangeKey of the new item.
323 The type of the value must match the type defined in the
324 schema for the table.
325
326 :type attrs: dict
327 :param attrs: A dictionary of key value pairs used to
328 populate the new item.
329
330 :type item_class: Class
331 :param item_class: Allows you to override the class used
332 to generate the items. This should be a subclass of
333 :class:`boto.dynamodb.item.Item`
334 """
335 return item_class(self, hash_key, range_key, attrs)
336
337 def query(self, hash_key, range_key_condition=None,
338 attributes_to_get=None, request_limit=None,
339 max_results=None, consistent_read=False,
340 scan_index_forward=True, exclusive_start_key=None,
341 item_class=Item):
342 """
343 Perform a query on the table.
344
345 :type hash_key: int|long|float|str|unicode
346 :param hash_key: The HashKey of the requested item. The
347 type of the value must match the type defined in the
348 schema for the table.
349
350 :type range_key_condition: :class:`boto.dynamodb.condition.Condition`
351 :param range_key_condition: A Condition object.
352 Condition object can be one of the following types:
353
354 EQ|LE|LT|GE|GT|BEGINS_WITH|BETWEEN
355
356 The only condition which expects or will accept two
357 values is 'BETWEEN', otherwise a single value should
358 be passed to the Condition constructor.
359
360 :type attributes_to_get: list
361 :param attributes_to_get: A list of attribute names.
362 If supplied, only the specified attribute names will
363 be returned. Otherwise, all attributes will be returned.
364
365 :type request_limit: int
366 :param request_limit: The maximum number of items to retrieve
367 from Amazon DynamoDB on each request. You may want to set
368 a specific request_limit based on the provisioned throughput
369 of your table. The default behavior is to retrieve as many
370 results as possible per request.
371
372 :type max_results: int
373 :param max_results: The maximum number of results that will
374 be retrieved from Amazon DynamoDB in total. For example,
375 if you only wanted to see the first 100 results from the
376 query, regardless of how many were actually available, you
377 could set max_results to 100 and the generator returned
378 from the query method will only yeild 100 results max.
379
380 :type consistent_read: bool
381 :param consistent_read: If True, a consistent read
382 request is issued. Otherwise, an eventually consistent
383 request is issued.
384
385 :type scan_index_forward: bool
386 :param scan_index_forward: Specified forward or backward
387 traversal of the index. Default is forward (True).
388
389 :type exclusive_start_key: list or tuple
390 :param exclusive_start_key: Primary key of the item from
391 which to continue an earlier query. This would be
392 provided as the LastEvaluatedKey in that query.
393
394 :type item_class: Class
395 :param item_class: Allows you to override the class used
396 to generate the items. This should be a subclass of
397 :class:`boto.dynamodb.item.Item`
398 """
399 return self.layer2.query(self, hash_key, range_key_condition,
400 attributes_to_get, request_limit,
401 max_results, consistent_read,
402 scan_index_forward, exclusive_start_key,
403 item_class=item_class)
404
405 def scan(self, scan_filter=None,
406 attributes_to_get=None, request_limit=None, max_results=None,
407 count=False, exclusive_start_key=None, item_class=Item):
408 """
409 Scan through this table, this is a very long
410 and expensive operation, and should be avoided if
411 at all possible.
412
413 :type scan_filter: A dict
414 :param scan_filter: A dictionary where the key is the
415 attribute name and the value is a
416 :class:`boto.dynamodb.condition.Condition` object.
417 Valid Condition objects include:
418
419 * EQ - equal (1)
420 * NE - not equal (1)
421 * LE - less than or equal (1)
422 * LT - less than (1)
423 * GE - greater than or equal (1)
424 * GT - greater than (1)
425 * NOT_NULL - attribute exists (0, use None)
426 * NULL - attribute does not exist (0, use None)
427 * CONTAINS - substring or value in list (1)
428 * NOT_CONTAINS - absence of substring or value in list (1)
429 * BEGINS_WITH - substring prefix (1)
430 * IN - exact match in list (N)
431 * BETWEEN - >= first value, <= second value (2)
432
433 :type attributes_to_get: list
434 :param attributes_to_get: A list of attribute names.
435 If supplied, only the specified attribute names will
436 be returned. Otherwise, all attributes will be returned.
437
438 :type request_limit: int
439 :param request_limit: The maximum number of items to retrieve
440 from Amazon DynamoDB on each request. You may want to set
441 a specific request_limit based on the provisioned throughput
442 of your table. The default behavior is to retrieve as many
443 results as possible per request.
444
445 :type max_results: int
446 :param max_results: The maximum number of results that will
447 be retrieved from Amazon DynamoDB in total. For example,
448 if you only wanted to see the first 100 results from the
449 query, regardless of how many were actually available, you
450 could set max_results to 100 and the generator returned
451 from the query method will only yeild 100 results max.
452
453 :type count: bool
454 :param count: If True, Amazon DynamoDB returns a total
455 number of items for the Scan operation, even if the
456 operation has no matching items for the assigned filter.
457
458 :type exclusive_start_key: list or tuple
459 :param exclusive_start_key: Primary key of the item from
460 which to continue an earlier query. This would be
461 provided as the LastEvaluatedKey in that query.
462
463 :type item_class: Class
464 :param item_class: Allows you to override the class used
465 to generate the items. This should be a subclass of
466 :class:`boto.dynamodb.item.Item`
467
468 :return: A TableGenerator (generator) object which will iterate over all results
469 :rtype: :class:`boto.dynamodb.layer2.TableGenerator`
470 """
471 return self.layer2.scan(self, scan_filter, attributes_to_get,
472 request_limit, max_results, count,
473 exclusive_start_key, item_class=item_class)
474
475 def batch_get_item(self, keys, attributes_to_get=None):
476 """
477 Return a set of attributes for a multiple items from a single table
478 using their primary keys. This abstraction removes the 100 Items per
479 batch limitations as well as the "UnprocessedKeys" logic.
480
481 :type keys: list
482 :param keys: A list of scalar or tuple values. Each element in the
483 list represents one Item to retrieve. If the schema for the
484 table has both a HashKey and a RangeKey, each element in the
485 list should be a tuple consisting of (hash_key, range_key). If
486 the schema for the table contains only a HashKey, each element
487 in the list should be a scalar value of the appropriate type
488 for the table schema. NOTE: The maximum number of items that
489 can be retrieved for a single operation is 100. Also, the
490 number of items retrieved is constrained by a 1 MB size limit.
491
492 :type attributes_to_get: list
493 :param attributes_to_get: A list of attribute names.
494 If supplied, only the specified attribute names will
495 be returned. Otherwise, all attributes will be returned.
496
497 :return: A TableBatchGenerator (generator) object which will iterate ove r all results
498 :rtype: :class:`boto.dynamodb.table.TableBatchGenerator`
499 """
500 return TableBatchGenerator(self, keys, attributes_to_get)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698