Merge pull request #2799 from ImFlog/fix_dynamodb_updated_new

Fix UPDATED_NEW return values differences
This commit is contained in:
Bert Blommers 2020-03-18 08:21:01 +00:00 committed by GitHub
commit 71bf314a0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 18 deletions

View file

@ -146,6 +146,9 @@ class DynamoType(object):
def __eq__(self, other):
return self.type == other.type and self.value == other.value
def __ne__(self, other):
return self.type != other.type or self.value != other.value
def __lt__(self, other):
return self.cast_value < other.cast_value

View file

@ -1,9 +1,12 @@
from __future__ import unicode_literals
import itertools
import copy
import json
import six
import re
import itertools
import six
from moto.core.responses import BaseResponse
from moto.core.utils import camelcase_to_underscores, amzn_request_id
from .exceptions import InvalidIndexNameError, InvalidUpdateExpression, ItemSizeTooLarge
@ -711,7 +714,8 @@ class DynamoHandler(BaseResponse):
attribute_updates = self.body.get("AttributeUpdates")
expression_attribute_names = self.body.get("ExpressionAttributeNames", {})
expression_attribute_values = self.body.get("ExpressionAttributeValues", {})
existing_item = self.dynamodb_backend.get_item(name, key)
# We need to copy the item in order to avoid it being modified by the update_item operation
existing_item = copy.deepcopy(self.dynamodb_backend.get_item(name, key))
if existing_item:
existing_attributes = existing_item.to_json()["Attributes"]
else:
@ -797,14 +801,39 @@ class DynamoHandler(BaseResponse):
k: v for k, v in existing_attributes.items() if k in changed_attributes
}
elif return_values == "UPDATED_NEW":
item_dict["Attributes"] = {
k: v
for k, v in item_dict["Attributes"].items()
if k in changed_attributes
}
item_dict["Attributes"] = self._build_updated_new_attributes(
existing_attributes, item_dict["Attributes"]
)
return dynamo_json_dump(item_dict)
def _build_updated_new_attributes(self, original, changed):
if type(changed) != type(original):
return changed
else:
if type(changed) is dict:
return {
key: self._build_updated_new_attributes(
original.get(key, None), changed[key]
)
for key in changed.keys()
if changed[key] != original.get(key, None)
}
elif type(changed) in (set, list):
if len(changed) != len(original):
return changed
else:
return [
self._build_updated_new_attributes(
original[index], changed[index]
)
for index in range(len(changed))
]
elif changed != original:
return changed
else:
return None
def describe_limits(self):
return json.dumps(
{