Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/boto/dynamodb/layer1.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) 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 import time | |
| 24 from binascii import crc32 | |
| 25 | |
| 26 import boto | |
| 27 from boto.connection import AWSAuthConnection | |
| 28 from boto.exception import DynamoDBResponseError | |
| 29 from boto.provider import Provider | |
| 30 from boto.dynamodb import exceptions as dynamodb_exceptions | |
| 31 from boto.compat import json | |
| 32 | |
| 33 | |
| 34 class Layer1(AWSAuthConnection): | |
| 35 """ | |
| 36 This is the lowest-level interface to DynamoDB. Methods at this | |
| 37 layer map directly to API requests and parameters to the methods | |
| 38 are either simple, scalar values or they are the Python equivalent | |
| 39 of the JSON input as defined in the DynamoDB Developer's Guide. | |
| 40 All responses are direct decoding of the JSON response bodies to | |
| 41 Python data structures via the json or simplejson modules. | |
| 42 | |
| 43 :ivar throughput_exceeded_events: An integer variable that | |
| 44 keeps a running total of the number of ThroughputExceeded | |
| 45 responses this connection has received from Amazon DynamoDB. | |
| 46 """ | |
| 47 | |
| 48 DefaultRegionName = 'us-east-1' | |
| 49 """The default region name for DynamoDB API.""" | |
| 50 | |
| 51 ServiceName = 'DynamoDB' | |
| 52 """The name of the Service""" | |
| 53 | |
| 54 Version = '20111205' | |
| 55 """DynamoDB API version.""" | |
| 56 | |
| 57 ThruputError = "ProvisionedThroughputExceededException" | |
| 58 """The error response returned when provisioned throughput is exceeded""" | |
| 59 | |
| 60 SessionExpiredError = 'com.amazon.coral.service#ExpiredTokenException' | |
| 61 """The error response returned when session token has expired""" | |
| 62 | |
| 63 ConditionalCheckFailedError = 'ConditionalCheckFailedException' | |
| 64 """The error response returned when a conditional check fails""" | |
| 65 | |
| 66 ValidationError = 'ValidationException' | |
| 67 """The error response returned when an item is invalid in some way""" | |
| 68 | |
| 69 ResponseError = DynamoDBResponseError | |
| 70 | |
| 71 NumberRetries = 10 | |
| 72 """The number of times an error is retried.""" | |
| 73 | |
| 74 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, | |
| 75 is_secure=True, port=None, proxy=None, proxy_port=None, | |
| 76 debug=0, security_token=None, region=None, | |
| 77 validate_certs=True, validate_checksums=True, profile_name=None): | |
| 78 if not region: | |
| 79 region_name = boto.config.get('DynamoDB', 'region', | |
| 80 self.DefaultRegionName) | |
| 81 for reg in boto.dynamodb.regions(): | |
| 82 if reg.name == region_name: | |
| 83 region = reg | |
| 84 break | |
| 85 | |
| 86 self.region = region | |
| 87 super(Layer1, self).__init__(self.region.endpoint, | |
| 88 aws_access_key_id, | |
| 89 aws_secret_access_key, | |
| 90 is_secure, port, proxy, proxy_port, | |
| 91 debug=debug, security_token=security_token, | |
| 92 validate_certs=validate_certs, | |
| 93 profile_name=profile_name) | |
| 94 self.throughput_exceeded_events = 0 | |
| 95 self._validate_checksums = boto.config.getbool( | |
| 96 'DynamoDB', 'validate_checksums', validate_checksums) | |
| 97 | |
| 98 def _get_session_token(self): | |
| 99 self.provider = Provider(self._provider_type) | |
| 100 self._auth_handler.update_provider(self.provider) | |
| 101 | |
| 102 def _required_auth_capability(self): | |
| 103 return ['hmac-v4'] | |
| 104 | |
| 105 def make_request(self, action, body='', object_hook=None): | |
| 106 """ | |
| 107 :raises: ``DynamoDBExpiredTokenError`` if the security token expires. | |
| 108 """ | |
| 109 headers = {'X-Amz-Target': '%s_%s.%s' % (self.ServiceName, | |
| 110 self.Version, action), | |
| 111 'Host': self.region.endpoint, | |
| 112 'Content-Type': 'application/x-amz-json-1.0', | |
| 113 'Content-Length': str(len(body))} | |
| 114 http_request = self.build_base_http_request('POST', '/', '/', | |
| 115 {}, headers, body, None) | |
| 116 start = time.time() | |
| 117 response = self._mexe(http_request, sender=None, | |
| 118 override_num_retries=self.NumberRetries, | |
| 119 retry_handler=self._retry_handler) | |
| 120 elapsed = (time.time() - start) * 1000 | |
| 121 request_id = response.getheader('x-amzn-RequestId') | |
| 122 boto.log.debug('RequestId: %s' % request_id) | |
| 123 boto.perflog.debug('%s: id=%s time=%sms', | |
| 124 headers['X-Amz-Target'], request_id, int(elapsed)) | |
| 125 response_body = response.read().decode('utf-8') | |
| 126 boto.log.debug(response_body) | |
| 127 return json.loads(response_body, object_hook=object_hook) | |
| 128 | |
| 129 def _retry_handler(self, response, i, next_sleep): | |
| 130 status = None | |
| 131 if response.status == 400: | |
| 132 response_body = response.read().decode('utf-8') | |
| 133 boto.log.debug(response_body) | |
| 134 data = json.loads(response_body) | |
| 135 if self.ThruputError in data.get('__type'): | |
| 136 self.throughput_exceeded_events += 1 | |
| 137 msg = "%s, retry attempt %s" % (self.ThruputError, i) | |
| 138 next_sleep = self._exponential_time(i) | |
| 139 i += 1 | |
| 140 status = (msg, i, next_sleep) | |
| 141 if i == self.NumberRetries: | |
| 142 # If this was our last retry attempt, raise | |
| 143 # a specific error saying that the throughput | |
| 144 # was exceeded. | |
| 145 raise dynamodb_exceptions.DynamoDBThroughputExceededError( | |
| 146 response.status, response.reason, data) | |
| 147 elif self.SessionExpiredError in data.get('__type'): | |
| 148 msg = 'Renewing Session Token' | |
| 149 self._get_session_token() | |
| 150 status = (msg, i + self.num_retries - 1, 0) | |
| 151 elif self.ConditionalCheckFailedError in data.get('__type'): | |
| 152 raise dynamodb_exceptions.DynamoDBConditionalCheckFailedError( | |
| 153 response.status, response.reason, data) | |
| 154 elif self.ValidationError in data.get('__type'): | |
| 155 raise dynamodb_exceptions.DynamoDBValidationError( | |
| 156 response.status, response.reason, data) | |
| 157 else: | |
| 158 raise self.ResponseError(response.status, response.reason, | |
| 159 data) | |
| 160 expected_crc32 = response.getheader('x-amz-crc32') | |
| 161 if self._validate_checksums and expected_crc32 is not None: | |
| 162 boto.log.debug('Validating crc32 checksum for body: %s', | |
| 163 response.read().decode('utf-8')) | |
| 164 actual_crc32 = crc32(response.read()) & 0xffffffff | |
| 165 expected_crc32 = int(expected_crc32) | |
| 166 if actual_crc32 != expected_crc32: | |
| 167 msg = ("The calculated checksum %s did not match the expected " | |
| 168 "checksum %s" % (actual_crc32, expected_crc32)) | |
| 169 status = (msg, i + 1, self._exponential_time(i)) | |
| 170 return status | |
| 171 | |
| 172 def _exponential_time(self, i): | |
| 173 if i == 0: | |
| 174 next_sleep = 0 | |
| 175 else: | |
| 176 next_sleep = min(0.05 * (2 ** i), | |
| 177 boto.config.get('Boto', 'max_retry_delay', 60)) | |
| 178 return next_sleep | |
| 179 | |
| 180 def list_tables(self, limit=None, start_table=None): | |
| 181 """ | |
| 182 Returns a dictionary of results. The dictionary contains | |
| 183 a **TableNames** key whose value is a list of the table names. | |
| 184 The dictionary could also contain a **LastEvaluatedTableName** | |
| 185 key whose value would be the last table name returned if | |
| 186 the complete list of table names was not returned. This | |
| 187 value would then be passed as the ``start_table`` parameter on | |
| 188 a subsequent call to this method. | |
| 189 | |
| 190 :type limit: int | |
| 191 :param limit: The maximum number of tables to return. | |
| 192 | |
| 193 :type start_table: str | |
| 194 :param start_table: The name of the table that starts the | |
| 195 list. If you ran a previous list_tables and not | |
| 196 all results were returned, the response dict would | |
| 197 include a LastEvaluatedTableName attribute. Use | |
| 198 that value here to continue the listing. | |
| 199 """ | |
| 200 data = {} | |
| 201 if limit: | |
| 202 data['Limit'] = limit | |
| 203 if start_table: | |
| 204 data['ExclusiveStartTableName'] = start_table | |
| 205 json_input = json.dumps(data) | |
| 206 return self.make_request('ListTables', json_input) | |
| 207 | |
| 208 def describe_table(self, table_name): | |
| 209 """ | |
| 210 Returns information about the table including current | |
| 211 state of the table, primary key schema and when the | |
| 212 table was created. | |
| 213 | |
| 214 :type table_name: str | |
| 215 :param table_name: The name of the table to describe. | |
| 216 """ | |
| 217 data = {'TableName': table_name} | |
| 218 json_input = json.dumps(data) | |
| 219 return self.make_request('DescribeTable', json_input) | |
| 220 | |
| 221 def create_table(self, table_name, schema, provisioned_throughput): | |
| 222 """ | |
| 223 Add a new table to your account. The table name must be unique | |
| 224 among those associated with the account issuing the request. | |
| 225 This request triggers an asynchronous workflow to begin creating | |
| 226 the table. When the workflow is complete, the state of the | |
| 227 table will be ACTIVE. | |
| 228 | |
| 229 :type table_name: str | |
| 230 :param table_name: The name of the table to create. | |
| 231 | |
| 232 :type schema: dict | |
| 233 :param schema: A Python version of the KeySchema data structure | |
| 234 as defined by DynamoDB | |
| 235 | |
| 236 :type provisioned_throughput: dict | |
| 237 :param provisioned_throughput: A Python version of the | |
| 238 ProvisionedThroughput data structure defined by | |
| 239 DynamoDB. | |
| 240 """ | |
| 241 data = {'TableName': table_name, | |
| 242 'KeySchema': schema, | |
| 243 'ProvisionedThroughput': provisioned_throughput} | |
| 244 json_input = json.dumps(data) | |
| 245 response_dict = self.make_request('CreateTable', json_input) | |
| 246 return response_dict | |
| 247 | |
| 248 def update_table(self, table_name, provisioned_throughput): | |
| 249 """ | |
| 250 Updates the provisioned throughput for a given table. | |
| 251 | |
| 252 :type table_name: str | |
| 253 :param table_name: The name of the table to update. | |
| 254 | |
| 255 :type provisioned_throughput: dict | |
| 256 :param provisioned_throughput: A Python version of the | |
| 257 ProvisionedThroughput data structure defined by | |
| 258 DynamoDB. | |
| 259 """ | |
| 260 data = {'TableName': table_name, | |
| 261 'ProvisionedThroughput': provisioned_throughput} | |
| 262 json_input = json.dumps(data) | |
| 263 return self.make_request('UpdateTable', json_input) | |
| 264 | |
| 265 def delete_table(self, table_name): | |
| 266 """ | |
| 267 Deletes the table and all of it's data. After this request | |
| 268 the table will be in the DELETING state until DynamoDB | |
| 269 completes the delete operation. | |
| 270 | |
| 271 :type table_name: str | |
| 272 :param table_name: The name of the table to delete. | |
| 273 """ | |
| 274 data = {'TableName': table_name} | |
| 275 json_input = json.dumps(data) | |
| 276 return self.make_request('DeleteTable', json_input) | |
| 277 | |
| 278 def get_item(self, table_name, key, attributes_to_get=None, | |
| 279 consistent_read=False, object_hook=None): | |
| 280 """ | |
| 281 Return a set of attributes for an item that matches | |
| 282 the supplied key. | |
| 283 | |
| 284 :type table_name: str | |
| 285 :param table_name: The name of the table containing the item. | |
| 286 | |
| 287 :type key: dict | |
| 288 :param key: A Python version of the Key data structure | |
| 289 defined by DynamoDB. | |
| 290 | |
| 291 :type attributes_to_get: list | |
| 292 :param attributes_to_get: A list of attribute names. | |
| 293 If supplied, only the specified attribute names will | |
| 294 be returned. Otherwise, all attributes will be returned. | |
| 295 | |
| 296 :type consistent_read: bool | |
| 297 :param consistent_read: If True, a consistent read | |
| 298 request is issued. Otherwise, an eventually consistent | |
| 299 request is issued. | |
| 300 """ | |
| 301 data = {'TableName': table_name, | |
| 302 'Key': key} | |
| 303 if attributes_to_get: | |
| 304 data['AttributesToGet'] = attributes_to_get | |
| 305 if consistent_read: | |
| 306 data['ConsistentRead'] = True | |
| 307 json_input = json.dumps(data) | |
| 308 response = self.make_request('GetItem', json_input, | |
| 309 object_hook=object_hook) | |
| 310 if 'Item' not in response: | |
| 311 raise dynamodb_exceptions.DynamoDBKeyNotFoundError( | |
| 312 "Key does not exist." | |
| 313 ) | |
| 314 return response | |
| 315 | |
| 316 def batch_get_item(self, request_items, object_hook=None): | |
| 317 """ | |
| 318 Return a set of attributes for a multiple items in | |
| 319 multiple tables using their primary keys. | |
| 320 | |
| 321 :type request_items: dict | |
| 322 :param request_items: A Python version of the RequestItems | |
| 323 data structure defined by DynamoDB. | |
| 324 """ | |
| 325 # If the list is empty, return empty response | |
| 326 if not request_items: | |
| 327 return {} | |
| 328 data = {'RequestItems': request_items} | |
| 329 json_input = json.dumps(data) | |
| 330 return self.make_request('BatchGetItem', json_input, | |
| 331 object_hook=object_hook) | |
| 332 | |
| 333 def batch_write_item(self, request_items, object_hook=None): | |
| 334 """ | |
| 335 This operation enables you to put or delete several items | |
| 336 across multiple tables in a single API call. | |
| 337 | |
| 338 :type request_items: dict | |
| 339 :param request_items: A Python version of the RequestItems | |
| 340 data structure defined by DynamoDB. | |
| 341 """ | |
| 342 data = {'RequestItems': request_items} | |
| 343 json_input = json.dumps(data) | |
| 344 return self.make_request('BatchWriteItem', json_input, | |
| 345 object_hook=object_hook) | |
| 346 | |
| 347 def put_item(self, table_name, item, | |
| 348 expected=None, return_values=None, | |
| 349 object_hook=None): | |
| 350 """ | |
| 351 Create a new item or replace an old item with a new | |
| 352 item (including all attributes). If an item already | |
| 353 exists in the specified table with the same primary | |
| 354 key, the new item will completely replace the old item. | |
| 355 You can perform a conditional put by specifying an | |
| 356 expected rule. | |
| 357 | |
| 358 :type table_name: str | |
| 359 :param table_name: The name of the table in which to put the item. | |
| 360 | |
| 361 :type item: dict | |
| 362 :param item: A Python version of the Item data structure | |
| 363 defined by DynamoDB. | |
| 364 | |
| 365 :type expected: dict | |
| 366 :param expected: A Python version of the Expected | |
| 367 data structure defined by DynamoDB. | |
| 368 | |
| 369 :type return_values: str | |
| 370 :param return_values: Controls the return of attribute | |
| 371 name-value pairs before then were changed. Possible | |
| 372 values are: None or 'ALL_OLD'. If 'ALL_OLD' is | |
| 373 specified and the item is overwritten, the content | |
| 374 of the old item is returned. | |
| 375 """ | |
| 376 data = {'TableName': table_name, | |
| 377 'Item': item} | |
| 378 if expected: | |
| 379 data['Expected'] = expected | |
| 380 if return_values: | |
| 381 data['ReturnValues'] = return_values | |
| 382 json_input = json.dumps(data) | |
| 383 return self.make_request('PutItem', json_input, | |
| 384 object_hook=object_hook) | |
| 385 | |
| 386 def update_item(self, table_name, key, attribute_updates, | |
| 387 expected=None, return_values=None, | |
| 388 object_hook=None): | |
| 389 """ | |
| 390 Edits an existing item's attributes. You can perform a conditional | |
| 391 update (insert a new attribute name-value pair if it doesn't exist, | |
| 392 or replace an existing name-value pair if it has certain expected | |
| 393 attribute values). | |
| 394 | |
| 395 :type table_name: str | |
| 396 :param table_name: The name of the table. | |
| 397 | |
| 398 :type key: dict | |
| 399 :param key: A Python version of the Key data structure | |
| 400 defined by DynamoDB which identifies the item to be updated. | |
| 401 | |
| 402 :type attribute_updates: dict | |
| 403 :param attribute_updates: A Python version of the AttributeUpdates | |
| 404 data structure defined by DynamoDB. | |
| 405 | |
| 406 :type expected: dict | |
| 407 :param expected: A Python version of the Expected | |
| 408 data structure defined by DynamoDB. | |
| 409 | |
| 410 :type return_values: str | |
| 411 :param return_values: Controls the return of attribute | |
| 412 name-value pairs before then were changed. Possible | |
| 413 values are: None or 'ALL_OLD'. If 'ALL_OLD' is | |
| 414 specified and the item is overwritten, the content | |
| 415 of the old item is returned. | |
| 416 """ | |
| 417 data = {'TableName': table_name, | |
| 418 'Key': key, | |
| 419 'AttributeUpdates': attribute_updates} | |
| 420 if expected: | |
| 421 data['Expected'] = expected | |
| 422 if return_values: | |
| 423 data['ReturnValues'] = return_values | |
| 424 json_input = json.dumps(data) | |
| 425 return self.make_request('UpdateItem', json_input, | |
| 426 object_hook=object_hook) | |
| 427 | |
| 428 def delete_item(self, table_name, key, | |
| 429 expected=None, return_values=None, | |
| 430 object_hook=None): | |
| 431 """ | |
| 432 Delete an item and all of it's attributes by primary key. | |
| 433 You can perform a conditional delete by specifying an | |
| 434 expected rule. | |
| 435 | |
| 436 :type table_name: str | |
| 437 :param table_name: The name of the table containing the item. | |
| 438 | |
| 439 :type key: dict | |
| 440 :param key: A Python version of the Key data structure | |
| 441 defined by DynamoDB. | |
| 442 | |
| 443 :type expected: dict | |
| 444 :param expected: A Python version of the Expected | |
| 445 data structure defined by DynamoDB. | |
| 446 | |
| 447 :type return_values: str | |
| 448 :param return_values: Controls the return of attribute | |
| 449 name-value pairs before then were changed. Possible | |
| 450 values are: None or 'ALL_OLD'. If 'ALL_OLD' is | |
| 451 specified and the item is overwritten, the content | |
| 452 of the old item is returned. | |
| 453 """ | |
| 454 data = {'TableName': table_name, | |
| 455 'Key': key} | |
| 456 if expected: | |
| 457 data['Expected'] = expected | |
| 458 if return_values: | |
| 459 data['ReturnValues'] = return_values | |
| 460 json_input = json.dumps(data) | |
| 461 return self.make_request('DeleteItem', json_input, | |
| 462 object_hook=object_hook) | |
| 463 | |
| 464 def query(self, table_name, hash_key_value, range_key_conditions=None, | |
| 465 attributes_to_get=None, limit=None, consistent_read=False, | |
| 466 scan_index_forward=True, exclusive_start_key=None, | |
| 467 object_hook=None, count=False): | |
| 468 """ | |
| 469 Perform a query of DynamoDB. This version is currently punting | |
| 470 and expecting you to provide a full and correct JSON body | |
| 471 which is passed as is to DynamoDB. | |
| 472 | |
| 473 :type table_name: str | |
| 474 :param table_name: The name of the table to query. | |
| 475 | |
| 476 :type hash_key_value: dict | |
| 477 :param key: A DynamoDB-style HashKeyValue. | |
| 478 | |
| 479 :type range_key_conditions: dict | |
| 480 :param range_key_conditions: A Python version of the | |
| 481 RangeKeyConditions data structure. | |
| 482 | |
| 483 :type attributes_to_get: list | |
| 484 :param attributes_to_get: A list of attribute names. | |
| 485 If supplied, only the specified attribute names will | |
| 486 be returned. Otherwise, all attributes will be returned. | |
| 487 | |
| 488 :type limit: int | |
| 489 :param limit: The maximum number of items to return. | |
| 490 | |
| 491 :type count: bool | |
| 492 :param count: If True, Amazon DynamoDB returns a total | |
| 493 number of items for the Query operation, even if the | |
| 494 operation has no matching items for the assigned filter. | |
| 495 | |
| 496 :type consistent_read: bool | |
| 497 :param consistent_read: If True, a consistent read | |
| 498 request is issued. Otherwise, an eventually consistent | |
| 499 request is issued. | |
| 500 | |
| 501 :type scan_index_forward: bool | |
| 502 :param scan_index_forward: Specified forward or backward | |
| 503 traversal of the index. Default is forward (True). | |
| 504 | |
| 505 :type exclusive_start_key: list or tuple | |
| 506 :param exclusive_start_key: Primary key of the item from | |
| 507 which to continue an earlier query. This would be | |
| 508 provided as the LastEvaluatedKey in that query. | |
| 509 """ | |
| 510 data = {'TableName': table_name, | |
| 511 'HashKeyValue': hash_key_value} | |
| 512 if range_key_conditions: | |
| 513 data['RangeKeyCondition'] = range_key_conditions | |
| 514 if attributes_to_get: | |
| 515 data['AttributesToGet'] = attributes_to_get | |
| 516 if limit: | |
| 517 data['Limit'] = limit | |
| 518 if count: | |
| 519 data['Count'] = True | |
| 520 if consistent_read: | |
| 521 data['ConsistentRead'] = True | |
| 522 if scan_index_forward: | |
| 523 data['ScanIndexForward'] = True | |
| 524 else: | |
| 525 data['ScanIndexForward'] = False | |
| 526 if exclusive_start_key: | |
| 527 data['ExclusiveStartKey'] = exclusive_start_key | |
| 528 json_input = json.dumps(data) | |
| 529 return self.make_request('Query', json_input, | |
| 530 object_hook=object_hook) | |
| 531 | |
| 532 def scan(self, table_name, scan_filter=None, | |
| 533 attributes_to_get=None, limit=None, | |
| 534 exclusive_start_key=None, object_hook=None, count=False): | |
| 535 """ | |
| 536 Perform a scan of DynamoDB. This version is currently punting | |
| 537 and expecting you to provide a full and correct JSON body | |
| 538 which is passed as is to DynamoDB. | |
| 539 | |
| 540 :type table_name: str | |
| 541 :param table_name: The name of the table to scan. | |
| 542 | |
| 543 :type scan_filter: dict | |
| 544 :param scan_filter: A Python version of the | |
| 545 ScanFilter data structure. | |
| 546 | |
| 547 :type attributes_to_get: list | |
| 548 :param attributes_to_get: A list of attribute names. | |
| 549 If supplied, only the specified attribute names will | |
| 550 be returned. Otherwise, all attributes will be returned. | |
| 551 | |
| 552 :type limit: int | |
| 553 :param limit: The maximum number of items to evaluate. | |
| 554 | |
| 555 :type count: bool | |
| 556 :param count: If True, Amazon DynamoDB returns a total | |
| 557 number of items for the Scan operation, even if the | |
| 558 operation has no matching items for the assigned filter. | |
| 559 | |
| 560 :type exclusive_start_key: list or tuple | |
| 561 :param exclusive_start_key: Primary key of the item from | |
| 562 which to continue an earlier query. This would be | |
| 563 provided as the LastEvaluatedKey in that query. | |
| 564 """ | |
| 565 data = {'TableName': table_name} | |
| 566 if scan_filter: | |
| 567 data['ScanFilter'] = scan_filter | |
| 568 if attributes_to_get: | |
| 569 data['AttributesToGet'] = attributes_to_get | |
| 570 if limit: | |
| 571 data['Limit'] = limit | |
| 572 if count: | |
| 573 data['Count'] = True | |
| 574 if exclusive_start_key: | |
| 575 data['ExclusiveStartKey'] = exclusive_start_key | |
| 576 json_input = json.dumps(data) | |
| 577 return self.make_request('Scan', json_input, object_hook=object_hook) |
