From 02edc6fa00fd700e38dc854dfbf1090cdc16804c Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Mon, 1 May 2017 12:31:31 -0700 Subject: [PATCH 1/2] Idempotent Dynamodb2 deletes Fixes #873 --- moto/dynamodb2/responses.py | 14 +++++--------- .../test_dynamodb_table_with_range_key.py | 3 ++- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/moto/dynamodb2/responses.py b/moto/dynamodb2/responses.py index 3ceda0be1..3811bbb73 100644 --- a/moto/dynamodb2/responses.py +++ b/moto/dynamodb2/responses.py @@ -419,16 +419,12 @@ class DynamoHandler(BaseResponse): keys = self.body['Key'] return_values = self.body.get('ReturnValues', '') item = dynamodb_backend2.delete_item(name, keys) - if item: - if return_values == 'ALL_OLD': - item_dict = item.to_json() - else: - item_dict = {'Attributes': {}} - item_dict['ConsumedCapacityUnits'] = 0.5 - return dynamo_json_dump(item_dict) + if item and return_values == 'ALL_OLD': + item_dict = item.to_json() else: - er = 'com.amazonaws.dynamodb.v20120810#ConditionalCheckFailedException' - return self.error(er) + item_dict = {'Attributes': {}} + item_dict['ConsumedCapacityUnits'] = 0.5 + return dynamo_json_dump(item_dict) def update_item(self): name = self.body['TableName'] diff --git a/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py b/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py index 58e0d66d1..402424f07 100644 --- a/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py +++ b/tests/test_dynamodb2/test_dynamodb_table_with_range_key.py @@ -314,7 +314,8 @@ def test_delete_item(): response.should.equal(True) table.count().should.equal(0) - item.delete().should.equal(False) + # Deletes are idempotent + item.delete().should.equal(True) @requires_boto_gte("2.9") From 8e3d46fb05fe9328e54322b1ae3a5c63991cf5d9 Mon Sep 17 00:00:00 2001 From: Jack Danger Canty Date: Mon, 8 May 2017 17:25:59 -1000 Subject: [PATCH 2/2] Deleting from an unknown table raises error If the table exists then we deletes are idempotent --- moto/dynamodb2/models.py | 2 +- moto/dynamodb2/responses.py | 5 +++++ .../test_dynamodb2/test_dynamodb_table_without_range_key.py | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/moto/dynamodb2/models.py b/moto/dynamodb2/models.py index 2ee5da203..f516d14a0 100644 --- a/moto/dynamodb2/models.py +++ b/moto/dynamodb2/models.py @@ -659,7 +659,7 @@ class DynamoDBBackend(BaseBackend): return item def delete_item(self, table_name, keys): - table = self.tables.get(table_name) + table = self.get_table(table_name) if not table: return None hash_key, range_key = self.get_keys_value(table, keys) diff --git a/moto/dynamodb2/responses.py b/moto/dynamodb2/responses.py index 3811bbb73..1e23c832a 100644 --- a/moto/dynamodb2/responses.py +++ b/moto/dynamodb2/responses.py @@ -418,6 +418,11 @@ class DynamoHandler(BaseResponse): name = self.body['TableName'] keys = self.body['Key'] return_values = self.body.get('ReturnValues', '') + table = dynamodb_backend2.get_table(name) + if not table: + er = 'com.amazonaws.dynamodb.v20120810#ConditionalCheckFailedException' + return self.error(er) + item = dynamodb_backend2.delete_item(name, keys) if item and return_values == 'ALL_OLD': item_dict = item.to_json() diff --git a/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py b/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py index 36e1b6c61..5ea242116 100644 --- a/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py +++ b/tests/test_dynamodb2/test_dynamodb_table_without_range_key.py @@ -199,7 +199,8 @@ def test_delete_item(): table.count().should.equal(0) - item.delete().should.equal(False) + # Deletes are idempotent and 'False' here would imply an error condition + item.delete().should.equal(True) @requires_boto_gte("2.9")