Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/boto/dynamodb/layer2.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author | guerler |
---|---|
date | Fri, 31 Jul 2020 00:18:57 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:d30785e31577 |
---|---|
1 # Copyright (c) 2011 Mitch Garnaat http://garnaat.org/ | |
2 # Copyright (c) 2011 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 from boto.dynamodb.layer1 import Layer1 | |
24 from boto.dynamodb.table import Table | |
25 from boto.dynamodb.schema import Schema | |
26 from boto.dynamodb.item import Item | |
27 from boto.dynamodb.batch import BatchList, BatchWriteList | |
28 from boto.dynamodb.types import get_dynamodb_type, Dynamizer, \ | |
29 LossyFloatDynamizer, NonBooleanDynamizer | |
30 | |
31 | |
32 class TableGenerator(object): | |
33 """ | |
34 This is an object that wraps up the table_generator function. | |
35 The only real reason to have this is that we want to be able | |
36 to accumulate and return the ConsumedCapacityUnits element that | |
37 is part of each response. | |
38 | |
39 :ivar last_evaluated_key: A sequence representing the key(s) | |
40 of the item last evaluated, or None if no additional | |
41 results are available. | |
42 | |
43 :ivar remaining: The remaining quantity of results requested. | |
44 | |
45 :ivar table: The table to which the call was made. | |
46 """ | |
47 | |
48 def __init__(self, table, callable, remaining, item_class, kwargs): | |
49 self.table = table | |
50 self.callable = callable | |
51 self.remaining = -1 if remaining is None else remaining | |
52 self.item_class = item_class | |
53 self.kwargs = kwargs | |
54 self._consumed_units = 0.0 | |
55 self.last_evaluated_key = None | |
56 self._count = 0 | |
57 self._scanned_count = 0 | |
58 self._response = None | |
59 | |
60 @property | |
61 def count(self): | |
62 """ | |
63 The total number of items retrieved thus far. This value changes with | |
64 iteration and even when issuing a call with count=True, it is necessary | |
65 to complete the iteration to assert an accurate count value. | |
66 """ | |
67 self.response | |
68 return self._count | |
69 | |
70 @property | |
71 def scanned_count(self): | |
72 """ | |
73 As above, but representing the total number of items scanned by | |
74 DynamoDB, without regard to any filters. | |
75 """ | |
76 self.response | |
77 return self._scanned_count | |
78 | |
79 @property | |
80 def consumed_units(self): | |
81 """ | |
82 Returns a float representing the ConsumedCapacityUnits accumulated. | |
83 """ | |
84 self.response | |
85 return self._consumed_units | |
86 | |
87 @property | |
88 def response(self): | |
89 """ | |
90 The current response to the call from DynamoDB. | |
91 """ | |
92 return self.next_response() if self._response is None else self._response | |
93 | |
94 def next_response(self): | |
95 """ | |
96 Issue a call and return the result. You can invoke this method | |
97 while iterating over the TableGenerator in order to skip to the | |
98 next "page" of results. | |
99 """ | |
100 # preserve any existing limit in case the user alters self.remaining | |
101 limit = self.kwargs.get('limit') | |
102 if (self.remaining > 0 and (limit is None or limit > self.remaining)): | |
103 self.kwargs['limit'] = self.remaining | |
104 self._response = self.callable(**self.kwargs) | |
105 self.kwargs['limit'] = limit | |
106 self._consumed_units += self._response.get('ConsumedCapacityUnits', 0.0) | |
107 self._count += self._response.get('Count', 0) | |
108 self._scanned_count += self._response.get('ScannedCount', 0) | |
109 # at the expense of a possibly gratuitous dynamize, ensure that | |
110 # early generator termination won't result in bad LEK values | |
111 if 'LastEvaluatedKey' in self._response: | |
112 lek = self._response['LastEvaluatedKey'] | |
113 esk = self.table.layer2.dynamize_last_evaluated_key(lek) | |
114 self.kwargs['exclusive_start_key'] = esk | |
115 lektuple = (lek['HashKeyElement'],) | |
116 if 'RangeKeyElement' in lek: | |
117 lektuple += (lek['RangeKeyElement'],) | |
118 self.last_evaluated_key = lektuple | |
119 else: | |
120 self.last_evaluated_key = None | |
121 return self._response | |
122 | |
123 def __iter__(self): | |
124 while self.remaining != 0: | |
125 response = self.response | |
126 for item in response.get('Items', []): | |
127 self.remaining -= 1 | |
128 yield self.item_class(self.table, attrs=item) | |
129 if self.remaining == 0: | |
130 break | |
131 if response is not self._response: | |
132 break | |
133 else: | |
134 if self.last_evaluated_key is not None: | |
135 self.next_response() | |
136 continue | |
137 break | |
138 if response is not self._response: | |
139 continue | |
140 break | |
141 | |
142 | |
143 class Layer2(object): | |
144 | |
145 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, | |
146 is_secure=True, port=None, proxy=None, proxy_port=None, | |
147 debug=0, security_token=None, region=None, | |
148 validate_certs=True, dynamizer=LossyFloatDynamizer, | |
149 profile_name=None): | |
150 self.layer1 = Layer1(aws_access_key_id, aws_secret_access_key, | |
151 is_secure, port, proxy, proxy_port, | |
152 debug, security_token, region, | |
153 validate_certs=validate_certs, | |
154 profile_name=profile_name) | |
155 self.dynamizer = dynamizer() | |
156 | |
157 def use_decimals(self, use_boolean=False): | |
158 """ | |
159 Use the ``decimal.Decimal`` type for encoding/decoding numeric types. | |
160 | |
161 By default, ints/floats are used to represent numeric types | |
162 ('N', 'NS') received from DynamoDB. Using the ``Decimal`` | |
163 type is recommended to prevent loss of precision. | |
164 | |
165 """ | |
166 # Eventually this should be made the default dynamizer. | |
167 self.dynamizer = Dynamizer() if use_boolean else NonBooleanDynamizer() | |
168 | |
169 def dynamize_attribute_updates(self, pending_updates): | |
170 """ | |
171 Convert a set of pending item updates into the structure | |
172 required by Layer1. | |
173 """ | |
174 d = {} | |
175 for attr_name in pending_updates: | |
176 action, value = pending_updates[attr_name] | |
177 if value is None: | |
178 # DELETE without an attribute value | |
179 d[attr_name] = {"Action": action} | |
180 else: | |
181 d[attr_name] = {"Action": action, | |
182 "Value": self.dynamizer.encode(value)} | |
183 return d | |
184 | |
185 def dynamize_item(self, item): | |
186 d = {} | |
187 for attr_name in item: | |
188 d[attr_name] = self.dynamizer.encode(item[attr_name]) | |
189 return d | |
190 | |
191 def dynamize_range_key_condition(self, range_key_condition): | |
192 """ | |
193 Convert a layer2 range_key_condition parameter into the | |
194 structure required by Layer1. | |
195 """ | |
196 return range_key_condition.to_dict() | |
197 | |
198 def dynamize_scan_filter(self, scan_filter): | |
199 """ | |
200 Convert a layer2 scan_filter parameter into the | |
201 structure required by Layer1. | |
202 """ | |
203 d = None | |
204 if scan_filter: | |
205 d = {} | |
206 for attr_name in scan_filter: | |
207 condition = scan_filter[attr_name] | |
208 d[attr_name] = condition.to_dict() | |
209 return d | |
210 | |
211 def dynamize_expected_value(self, expected_value): | |
212 """ | |
213 Convert an expected_value parameter into the data structure | |
214 required for Layer1. | |
215 """ | |
216 d = None | |
217 if expected_value: | |
218 d = {} | |
219 for attr_name in expected_value: | |
220 attr_value = expected_value[attr_name] | |
221 if attr_value is True: | |
222 attr_value = {'Exists': True} | |
223 elif attr_value is False: | |
224 attr_value = {'Exists': False} | |
225 else: | |
226 val = self.dynamizer.encode(expected_value[attr_name]) | |
227 attr_value = {'Value': val} | |
228 d[attr_name] = attr_value | |
229 return d | |
230 | |
231 def dynamize_last_evaluated_key(self, last_evaluated_key): | |
232 """ | |
233 Convert a last_evaluated_key parameter into the data structure | |
234 required for Layer1. | |
235 """ | |
236 d = None | |
237 if last_evaluated_key: | |
238 hash_key = last_evaluated_key['HashKeyElement'] | |
239 d = {'HashKeyElement': self.dynamizer.encode(hash_key)} | |
240 if 'RangeKeyElement' in last_evaluated_key: | |
241 range_key = last_evaluated_key['RangeKeyElement'] | |
242 d['RangeKeyElement'] = self.dynamizer.encode(range_key) | |
243 return d | |
244 | |
245 def build_key_from_values(self, schema, hash_key, range_key=None): | |
246 """ | |
247 Build a Key structure to be used for accessing items | |
248 in Amazon DynamoDB. This method takes the supplied hash_key | |
249 and optional range_key and validates them against the | |
250 schema. If there is a mismatch, a TypeError is raised. | |
251 Otherwise, a Python dict version of a Amazon DynamoDB Key | |
252 data structure is returned. | |
253 | |
254 :type hash_key: int|float|str|unicode|Binary | |
255 :param hash_key: The hash key of the item you are looking for. | |
256 The type of the hash key should match the type defined in | |
257 the schema. | |
258 | |
259 :type range_key: int|float|str|unicode|Binary | |
260 :param range_key: The range key of the item your are looking for. | |
261 This should be supplied only if the schema requires a | |
262 range key. The type of the range key should match the | |
263 type defined in the schema. | |
264 """ | |
265 dynamodb_key = {} | |
266 dynamodb_value = self.dynamizer.encode(hash_key) | |
267 if list(dynamodb_value.keys())[0] != schema.hash_key_type: | |
268 msg = 'Hashkey must be of type: %s' % schema.hash_key_type | |
269 raise TypeError(msg) | |
270 dynamodb_key['HashKeyElement'] = dynamodb_value | |
271 if range_key is not None: | |
272 dynamodb_value = self.dynamizer.encode(range_key) | |
273 if list(dynamodb_value.keys())[0] != schema.range_key_type: | |
274 msg = 'RangeKey must be of type: %s' % schema.range_key_type | |
275 raise TypeError(msg) | |
276 dynamodb_key['RangeKeyElement'] = dynamodb_value | |
277 return dynamodb_key | |
278 | |
279 def new_batch_list(self): | |
280 """ | |
281 Return a new, empty :class:`boto.dynamodb.batch.BatchList` | |
282 object. | |
283 """ | |
284 return BatchList(self) | |
285 | |
286 def new_batch_write_list(self): | |
287 """ | |
288 Return a new, empty :class:`boto.dynamodb.batch.BatchWriteList` | |
289 object. | |
290 """ | |
291 return BatchWriteList(self) | |
292 | |
293 def list_tables(self, limit=None): | |
294 """ | |
295 Return a list of the names of all tables associated with the | |
296 current account and region. | |
297 | |
298 :type limit: int | |
299 :param limit: The maximum number of tables to return. | |
300 """ | |
301 tables = [] | |
302 start_table = None | |
303 while not limit or len(tables) < limit: | |
304 this_round_limit = None | |
305 if limit: | |
306 this_round_limit = limit - len(tables) | |
307 this_round_limit = min(this_round_limit, 100) | |
308 result = self.layer1.list_tables(limit=this_round_limit, start_table=start_table) | |
309 tables.extend(result.get('TableNames', [])) | |
310 start_table = result.get('LastEvaluatedTableName', None) | |
311 if not start_table: | |
312 break | |
313 return tables | |
314 | |
315 def describe_table(self, name): | |
316 """ | |
317 Retrieve information about an existing table. | |
318 | |
319 :type name: str | |
320 :param name: The name of the desired table. | |
321 | |
322 """ | |
323 return self.layer1.describe_table(name) | |
324 | |
325 def table_from_schema(self, name, schema): | |
326 """ | |
327 Create a Table object from a schema. | |
328 | |
329 This method will create a Table object without | |
330 making any API calls. If you know the name and schema | |
331 of the table, you can use this method instead of | |
332 ``get_table``. | |
333 | |
334 Example usage:: | |
335 | |
336 table = layer2.table_from_schema( | |
337 'tablename', | |
338 Schema.create(hash_key=('foo', 'N'))) | |
339 | |
340 :type name: str | |
341 :param name: The name of the table. | |
342 | |
343 :type schema: :class:`boto.dynamodb.schema.Schema` | |
344 :param schema: The schema associated with the table. | |
345 | |
346 :rtype: :class:`boto.dynamodb.table.Table` | |
347 :return: A Table object representing the table. | |
348 | |
349 """ | |
350 return Table.create_from_schema(self, name, schema) | |
351 | |
352 def get_table(self, name): | |
353 """ | |
354 Retrieve the Table object for an existing table. | |
355 | |
356 :type name: str | |
357 :param name: The name of the desired table. | |
358 | |
359 :rtype: :class:`boto.dynamodb.table.Table` | |
360 :return: A Table object representing the table. | |
361 """ | |
362 response = self.layer1.describe_table(name) | |
363 return Table(self, response) | |
364 | |
365 lookup = get_table | |
366 | |
367 def create_table(self, name, schema, read_units, write_units): | |
368 """ | |
369 Create a new Amazon DynamoDB table. | |
370 | |
371 :type name: str | |
372 :param name: The name of the desired table. | |
373 | |
374 :type schema: :class:`boto.dynamodb.schema.Schema` | |
375 :param schema: The Schema object that defines the schema used | |
376 by this table. | |
377 | |
378 :type read_units: int | |
379 :param read_units: The value for ReadCapacityUnits. | |
380 | |
381 :type write_units: int | |
382 :param write_units: The value for WriteCapacityUnits. | |
383 | |
384 :rtype: :class:`boto.dynamodb.table.Table` | |
385 :return: A Table object representing the new Amazon DynamoDB table. | |
386 """ | |
387 response = self.layer1.create_table(name, schema.dict, | |
388 {'ReadCapacityUnits': read_units, | |
389 'WriteCapacityUnits': write_units}) | |
390 return Table(self, response) | |
391 | |
392 def update_throughput(self, table, read_units, write_units): | |
393 """ | |
394 Update the ProvisionedThroughput for the Amazon DynamoDB Table. | |
395 | |
396 :type table: :class:`boto.dynamodb.table.Table` | |
397 :param table: The Table object whose throughput is being updated. | |
398 | |
399 :type read_units: int | |
400 :param read_units: The new value for ReadCapacityUnits. | |
401 | |
402 :type write_units: int | |
403 :param write_units: The new value for WriteCapacityUnits. | |
404 """ | |
405 response = self.layer1.update_table(table.name, | |
406 {'ReadCapacityUnits': read_units, | |
407 'WriteCapacityUnits': write_units}) | |
408 table.update_from_response(response) | |
409 | |
410 def delete_table(self, table): | |
411 """ | |
412 Delete this table and all items in it. After calling this | |
413 the Table objects status attribute will be set to 'DELETING'. | |
414 | |
415 :type table: :class:`boto.dynamodb.table.Table` | |
416 :param table: The Table object that is being deleted. | |
417 """ | |
418 response = self.layer1.delete_table(table.name) | |
419 table.update_from_response(response) | |
420 | |
421 def create_schema(self, hash_key_name, hash_key_proto_value, | |
422 range_key_name=None, range_key_proto_value=None): | |
423 """ | |
424 Create a Schema object used when creating a Table. | |
425 | |
426 :type hash_key_name: str | |
427 :param hash_key_name: The name of the HashKey for the schema. | |
428 | |
429 :type hash_key_proto_value: int|long|float|str|unicode|Binary | |
430 :param hash_key_proto_value: A sample or prototype of the type | |
431 of value you want to use for the HashKey. Alternatively, | |
432 you can also just pass in the Python type (e.g. int, float, etc.). | |
433 | |
434 :type range_key_name: str | |
435 :param range_key_name: The name of the RangeKey for the schema. | |
436 This parameter is optional. | |
437 | |
438 :type range_key_proto_value: int|long|float|str|unicode|Binary | |
439 :param range_key_proto_value: A sample or prototype of the type | |
440 of value you want to use for the RangeKey. Alternatively, | |
441 you can also pass in the Python type (e.g. int, float, etc.) | |
442 This parameter is optional. | |
443 """ | |
444 hash_key = (hash_key_name, get_dynamodb_type(hash_key_proto_value)) | |
445 if range_key_name and range_key_proto_value is not None: | |
446 range_key = (range_key_name, | |
447 get_dynamodb_type(range_key_proto_value)) | |
448 else: | |
449 range_key = None | |
450 return Schema.create(hash_key, range_key) | |
451 | |
452 def get_item(self, table, hash_key, range_key=None, | |
453 attributes_to_get=None, consistent_read=False, | |
454 item_class=Item): | |
455 """ | |
456 Retrieve an existing item from the table. | |
457 | |
458 :type table: :class:`boto.dynamodb.table.Table` | |
459 :param table: The Table object from which the item is retrieved. | |
460 | |
461 :type hash_key: int|long|float|str|unicode|Binary | |
462 :param hash_key: The HashKey of the requested item. The | |
463 type of the value must match the type defined in the | |
464 schema for the table. | |
465 | |
466 :type range_key: int|long|float|str|unicode|Binary | |
467 :param range_key: The optional RangeKey of the requested item. | |
468 The type of the value must match the type defined in the | |
469 schema for the table. | |
470 | |
471 :type attributes_to_get: list | |
472 :param attributes_to_get: A list of attribute names. | |
473 If supplied, only the specified attribute names will | |
474 be returned. Otherwise, all attributes will be returned. | |
475 | |
476 :type consistent_read: bool | |
477 :param consistent_read: If True, a consistent read | |
478 request is issued. Otherwise, an eventually consistent | |
479 request is issued. | |
480 | |
481 :type item_class: Class | |
482 :param item_class: Allows you to override the class used | |
483 to generate the items. This should be a subclass of | |
484 :class:`boto.dynamodb.item.Item` | |
485 """ | |
486 key = self.build_key_from_values(table.schema, hash_key, range_key) | |
487 response = self.layer1.get_item(table.name, key, | |
488 attributes_to_get, consistent_read, | |
489 object_hook=self.dynamizer.decode) | |
490 item = item_class(table, hash_key, range_key, response['Item']) | |
491 if 'ConsumedCapacityUnits' in response: | |
492 item.consumed_units = response['ConsumedCapacityUnits'] | |
493 return item | |
494 | |
495 def batch_get_item(self, batch_list): | |
496 """ | |
497 Return a set of attributes for a multiple items in | |
498 multiple tables using their primary keys. | |
499 | |
500 :type batch_list: :class:`boto.dynamodb.batch.BatchList` | |
501 :param batch_list: A BatchList object which consists of a | |
502 list of :class:`boto.dynamoddb.batch.Batch` objects. | |
503 Each Batch object contains the information about one | |
504 batch of objects that you wish to retrieve in this | |
505 request. | |
506 """ | |
507 request_items = batch_list.to_dict() | |
508 return self.layer1.batch_get_item(request_items, | |
509 object_hook=self.dynamizer.decode) | |
510 | |
511 def batch_write_item(self, batch_list): | |
512 """ | |
513 Performs multiple Puts and Deletes in one batch. | |
514 | |
515 :type batch_list: :class:`boto.dynamodb.batch.BatchWriteList` | |
516 :param batch_list: A BatchWriteList object which consists of a | |
517 list of :class:`boto.dynamoddb.batch.BatchWrite` objects. | |
518 Each Batch object contains the information about one | |
519 batch of objects that you wish to put or delete. | |
520 """ | |
521 request_items = batch_list.to_dict() | |
522 return self.layer1.batch_write_item(request_items, | |
523 object_hook=self.dynamizer.decode) | |
524 | |
525 def put_item(self, item, expected_value=None, return_values=None): | |
526 """ | |
527 Store a new item or completely replace an existing item | |
528 in Amazon DynamoDB. | |
529 | |
530 :type item: :class:`boto.dynamodb.item.Item` | |
531 :param item: The Item to write to Amazon DynamoDB. | |
532 | |
533 :type expected_value: dict | |
534 :param expected_value: A dictionary of name/value pairs that you expect. | |
535 This dictionary should have name/value pairs where the name | |
536 is the name of the attribute and the value is either the value | |
537 you are expecting or False if you expect the attribute not to | |
538 exist. | |
539 | |
540 :type return_values: str | |
541 :param return_values: Controls the return of attribute | |
542 name-value pairs before then were changed. Possible | |
543 values are: None or 'ALL_OLD'. If 'ALL_OLD' is | |
544 specified and the item is overwritten, the content | |
545 of the old item is returned. | |
546 """ | |
547 expected_value = self.dynamize_expected_value(expected_value) | |
548 response = self.layer1.put_item(item.table.name, | |
549 self.dynamize_item(item), | |
550 expected_value, return_values, | |
551 object_hook=self.dynamizer.decode) | |
552 if 'ConsumedCapacityUnits' in response: | |
553 item.consumed_units = response['ConsumedCapacityUnits'] | |
554 return response | |
555 | |
556 def update_item(self, item, expected_value=None, return_values=None): | |
557 """ | |
558 Commit pending item updates to Amazon DynamoDB. | |
559 | |
560 :type item: :class:`boto.dynamodb.item.Item` | |
561 :param item: The Item to update in Amazon DynamoDB. It is expected | |
562 that you would have called the add_attribute, put_attribute | |
563 and/or delete_attribute methods on this Item prior to calling | |
564 this method. Those queued changes are what will be updated. | |
565 | |
566 :type expected_value: dict | |
567 :param expected_value: A dictionary of name/value pairs that you | |
568 expect. This dictionary should have name/value pairs where the | |
569 name is the name of the attribute and the value is either the | |
570 value you are expecting or False if you expect the attribute | |
571 not to exist. | |
572 | |
573 :type return_values: str | |
574 :param return_values: Controls the return of attribute name/value pairs | |
575 before they were updated. Possible values are: None, 'ALL_OLD', | |
576 'UPDATED_OLD', 'ALL_NEW' or 'UPDATED_NEW'. If 'ALL_OLD' is | |
577 specified and the item is overwritten, the content of the old item | |
578 is returned. If 'ALL_NEW' is specified, then all the attributes of | |
579 the new version of the item are returned. If 'UPDATED_NEW' is | |
580 specified, the new versions of only the updated attributes are | |
581 returned. | |
582 | |
583 """ | |
584 expected_value = self.dynamize_expected_value(expected_value) | |
585 key = self.build_key_from_values(item.table.schema, | |
586 item.hash_key, item.range_key) | |
587 attr_updates = self.dynamize_attribute_updates(item._updates) | |
588 | |
589 response = self.layer1.update_item(item.table.name, key, | |
590 attr_updates, | |
591 expected_value, return_values, | |
592 object_hook=self.dynamizer.decode) | |
593 item._updates.clear() | |
594 if 'ConsumedCapacityUnits' in response: | |
595 item.consumed_units = response['ConsumedCapacityUnits'] | |
596 return response | |
597 | |
598 def delete_item(self, item, expected_value=None, return_values=None): | |
599 """ | |
600 Delete the item from Amazon DynamoDB. | |
601 | |
602 :type item: :class:`boto.dynamodb.item.Item` | |
603 :param item: The Item to delete from Amazon DynamoDB. | |
604 | |
605 :type expected_value: dict | |
606 :param expected_value: A dictionary of name/value pairs that you expect. | |
607 This dictionary should have name/value pairs where the name | |
608 is the name of the attribute and the value is either the value | |
609 you are expecting or False if you expect the attribute not to | |
610 exist. | |
611 | |
612 :type return_values: str | |
613 :param return_values: Controls the return of attribute | |
614 name-value pairs before then were changed. Possible | |
615 values are: None or 'ALL_OLD'. If 'ALL_OLD' is | |
616 specified and the item is overwritten, the content | |
617 of the old item is returned. | |
618 """ | |
619 expected_value = self.dynamize_expected_value(expected_value) | |
620 key = self.build_key_from_values(item.table.schema, | |
621 item.hash_key, item.range_key) | |
622 return self.layer1.delete_item(item.table.name, key, | |
623 expected=expected_value, | |
624 return_values=return_values, | |
625 object_hook=self.dynamizer.decode) | |
626 | |
627 def query(self, table, hash_key, range_key_condition=None, | |
628 attributes_to_get=None, request_limit=None, | |
629 max_results=None, consistent_read=False, | |
630 scan_index_forward=True, exclusive_start_key=None, | |
631 item_class=Item, count=False): | |
632 """ | |
633 Perform a query on the table. | |
634 | |
635 :type table: :class:`boto.dynamodb.table.Table` | |
636 :param table: The Table object that is being queried. | |
637 | |
638 :type hash_key: int|long|float|str|unicode|Binary | |
639 :param hash_key: The HashKey of the requested item. The | |
640 type of the value must match the type defined in the | |
641 schema for the table. | |
642 | |
643 :type range_key_condition: :class:`boto.dynamodb.condition.Condition` | |
644 :param range_key_condition: A Condition object. | |
645 Condition object can be one of the following types: | |
646 | |
647 EQ|LE|LT|GE|GT|BEGINS_WITH|BETWEEN | |
648 | |
649 The only condition which expects or will accept two | |
650 values is 'BETWEEN', otherwise a single value should | |
651 be passed to the Condition constructor. | |
652 | |
653 :type attributes_to_get: list | |
654 :param attributes_to_get: A list of attribute names. | |
655 If supplied, only the specified attribute names will | |
656 be returned. Otherwise, all attributes will be returned. | |
657 | |
658 :type request_limit: int | |
659 :param request_limit: The maximum number of items to retrieve | |
660 from Amazon DynamoDB on each request. You may want to set | |
661 a specific request_limit based on the provisioned throughput | |
662 of your table. The default behavior is to retrieve as many | |
663 results as possible per request. | |
664 | |
665 :type max_results: int | |
666 :param max_results: The maximum number of results that will | |
667 be retrieved from Amazon DynamoDB in total. For example, | |
668 if you only wanted to see the first 100 results from the | |
669 query, regardless of how many were actually available, you | |
670 could set max_results to 100 and the generator returned | |
671 from the query method will only yeild 100 results max. | |
672 | |
673 :type consistent_read: bool | |
674 :param consistent_read: If True, a consistent read | |
675 request is issued. Otherwise, an eventually consistent | |
676 request is issued. | |
677 | |
678 :type scan_index_forward: bool | |
679 :param scan_index_forward: Specified forward or backward | |
680 traversal of the index. Default is forward (True). | |
681 | |
682 :type count: bool | |
683 :param count: If True, Amazon DynamoDB returns a total | |
684 number of items for the Query operation, even if the | |
685 operation has no matching items for the assigned filter. | |
686 If count is True, the actual items are not returned and | |
687 the count is accessible as the ``count`` attribute of | |
688 the returned object. | |
689 | |
690 :type exclusive_start_key: list or tuple | |
691 :param exclusive_start_key: Primary key of the item from | |
692 which to continue an earlier query. This would be | |
693 provided as the LastEvaluatedKey in that query. | |
694 | |
695 :type item_class: Class | |
696 :param item_class: Allows you to override the class used | |
697 to generate the items. This should be a subclass of | |
698 :class:`boto.dynamodb.item.Item` | |
699 | |
700 :rtype: :class:`boto.dynamodb.layer2.TableGenerator` | |
701 """ | |
702 if range_key_condition: | |
703 rkc = self.dynamize_range_key_condition(range_key_condition) | |
704 else: | |
705 rkc = None | |
706 if exclusive_start_key: | |
707 esk = self.build_key_from_values(table.schema, | |
708 *exclusive_start_key) | |
709 else: | |
710 esk = None | |
711 kwargs = {'table_name': table.name, | |
712 'hash_key_value': self.dynamizer.encode(hash_key), | |
713 'range_key_conditions': rkc, | |
714 'attributes_to_get': attributes_to_get, | |
715 'limit': request_limit, | |
716 'count': count, | |
717 'consistent_read': consistent_read, | |
718 'scan_index_forward': scan_index_forward, | |
719 'exclusive_start_key': esk, | |
720 'object_hook': self.dynamizer.decode} | |
721 return TableGenerator(table, self.layer1.query, | |
722 max_results, item_class, kwargs) | |
723 | |
724 def scan(self, table, scan_filter=None, | |
725 attributes_to_get=None, request_limit=None, max_results=None, | |
726 exclusive_start_key=None, item_class=Item, count=False): | |
727 """ | |
728 Perform a scan of DynamoDB. | |
729 | |
730 :type table: :class:`boto.dynamodb.table.Table` | |
731 :param table: The Table object that is being scanned. | |
732 | |
733 :type scan_filter: A dict | |
734 :param scan_filter: A dictionary where the key is the | |
735 attribute name and the value is a | |
736 :class:`boto.dynamodb.condition.Condition` object. | |
737 Valid Condition objects include: | |
738 | |
739 * EQ - equal (1) | |
740 * NE - not equal (1) | |
741 * LE - less than or equal (1) | |
742 * LT - less than (1) | |
743 * GE - greater than or equal (1) | |
744 * GT - greater than (1) | |
745 * NOT_NULL - attribute exists (0, use None) | |
746 * NULL - attribute does not exist (0, use None) | |
747 * CONTAINS - substring or value in list (1) | |
748 * NOT_CONTAINS - absence of substring or value in list (1) | |
749 * BEGINS_WITH - substring prefix (1) | |
750 * IN - exact match in list (N) | |
751 * BETWEEN - >= first value, <= second value (2) | |
752 | |
753 :type attributes_to_get: list | |
754 :param attributes_to_get: A list of attribute names. | |
755 If supplied, only the specified attribute names will | |
756 be returned. Otherwise, all attributes will be returned. | |
757 | |
758 :type request_limit: int | |
759 :param request_limit: The maximum number of items to retrieve | |
760 from Amazon DynamoDB on each request. You may want to set | |
761 a specific request_limit based on the provisioned throughput | |
762 of your table. The default behavior is to retrieve as many | |
763 results as possible per request. | |
764 | |
765 :type max_results: int | |
766 :param max_results: The maximum number of results that will | |
767 be retrieved from Amazon DynamoDB in total. For example, | |
768 if you only wanted to see the first 100 results from the | |
769 query, regardless of how many were actually available, you | |
770 could set max_results to 100 and the generator returned | |
771 from the query method will only yeild 100 results max. | |
772 | |
773 :type count: bool | |
774 :param count: If True, Amazon DynamoDB returns a total | |
775 number of items for the Scan operation, even if the | |
776 operation has no matching items for the assigned filter. | |
777 If count is True, the actual items are not returned and | |
778 the count is accessible as the ``count`` attribute of | |
779 the returned object. | |
780 | |
781 :type exclusive_start_key: list or tuple | |
782 :param exclusive_start_key: Primary key of the item from | |
783 which to continue an earlier query. This would be | |
784 provided as the LastEvaluatedKey in that query. | |
785 | |
786 :type item_class: Class | |
787 :param item_class: Allows you to override the class used | |
788 to generate the items. This should be a subclass of | |
789 :class:`boto.dynamodb.item.Item` | |
790 | |
791 :rtype: :class:`boto.dynamodb.layer2.TableGenerator` | |
792 """ | |
793 if exclusive_start_key: | |
794 esk = self.build_key_from_values(table.schema, | |
795 *exclusive_start_key) | |
796 else: | |
797 esk = None | |
798 kwargs = {'table_name': table.name, | |
799 'scan_filter': self.dynamize_scan_filter(scan_filter), | |
800 'attributes_to_get': attributes_to_get, | |
801 'limit': request_limit, | |
802 'count': count, | |
803 'exclusive_start_key': esk, | |
804 'object_hook': self.dynamizer.decode} | |
805 return TableGenerator(table, self.layer1.scan, | |
806 max_results, item_class, kwargs) |