Skip to content

Commit ce741ab

Browse files
jmphillidanielhochman
authored andcommitted
deserialize map attributes correctly (#192)
1 parent ae06940 commit ce741ab

File tree

3 files changed

+82
-3
lines changed

3 files changed

+82
-3
lines changed

pynamodb/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ def from_raw_data(cls, data):
438438
attr = cls._get_attributes().get(name, None)
439439
if attr:
440440
deserialized_attr = attr.deserialize(attr.get_value(value))
441-
if isinstance(attr, MapAttribute):
441+
if isinstance(attr, MapAttribute) and not type(attr) == MapAttribute:
442442
deserialized_attr = type(attr)(**deserialized_attr)
443443
kwargs[name] = deserialized_attr
444444
return cls(*args, **kwargs)

pynamodb/tests/data.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1192,3 +1192,50 @@
11921192
}
11931193
}
11941194
}
1195+
1196+
EXPLICIT_RAW_MAP_MODEL_TABLE_DATA = {
1197+
'Table': {
1198+
'ItemCount': 0, 'TableName': 'ExplicitRawMapModel',
1199+
'ProvisionedThroughput': {
1200+
'ReadCapacityUnits': 2,
1201+
'WriteCapacityUnits': 2,
1202+
'NumberOfDecreasesToday': 0
1203+
},
1204+
'CreationDateTime': 1391471876.86,
1205+
'TableStatus': 'ACTIVE',
1206+
'AttributeDefinitions': [
1207+
{
1208+
'AttributeName': 'map_id',
1209+
'AttributeType': 'N'
1210+
},
1211+
{
1212+
'AttributeName': 'map_attr',
1213+
'AttributeType': 'M'
1214+
}
1215+
],
1216+
'KeySchema': [
1217+
{
1218+
'AttributeName': 'map_id', 'KeyType': 'HASH'
1219+
}
1220+
],
1221+
'TableSizeBytes': 0
1222+
}
1223+
}
1224+
1225+
EXPLICIT_RAW_MAP_MODEL_ITEM_DATA = {
1226+
'Item': {
1227+
'map_id': {
1228+
'N': '123',
1229+
},
1230+
'map_attr': {'M': {
1231+
'foo': {'S': 'bar'},
1232+
'num': {'N': '1'},
1233+
'bool_type': {'BOOL': True},
1234+
'other_b_type': {'BOOL': False},
1235+
'floaty': {'N': '1.2'},
1236+
'listy': {'L': [{'N': '1'}, {'N': '2'}, {'N': '3'}]},
1237+
'mapy': {'M': {'baz': {'S': 'bongo'}}}
1238+
}
1239+
}
1240+
}
1241+
}

pynamodb/tests/test_model.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
BOOLEAN_CONVERSION_MODEL_TABLE_DATA,
4444
BOOLEAN_CONVERSION_MODEL_NEW_STYLE_FALSE_ITEM_DATA, BOOLEAN_CONVERSION_MODEL_NEW_STYLE_TRUE_ITEM_DATA,
4545
BOOLEAN_CONVERSION_MODEL_OLD_STYLE_FALSE_ITEM_DATA, BOOLEAN_CONVERSION_MODEL_OLD_STYLE_TRUE_ITEM_DATA,
46-
BOOLEAN_CONVERSION_MODEL_TABLE_DATA_OLD_STYLE, TREE_MODEL_TABLE_DATA, TREE_MODEL_ITEM_DATA
46+
BOOLEAN_CONVERSION_MODEL_TABLE_DATA_OLD_STYLE, TREE_MODEL_TABLE_DATA, TREE_MODEL_ITEM_DATA,
47+
EXPLICIT_RAW_MAP_MODEL_TABLE_DATA, EXPLICIT_RAW_MAP_MODEL_ITEM_DATA
4748
)
4849

4950
if six.PY3:
@@ -400,7 +401,7 @@ class Meta:
400401
class ExplicitRawMapModel(Model):
401402
class Meta:
402403
table_name = 'ExplicitRawMapModel'
403-
404+
map_id = NumberAttribute(hash_key=True, default=123)
404405
map_attr = MapAttribute()
405406

406407

@@ -3076,3 +3077,34 @@ def test_raw_map_deserializes(self):
30763077
for k,v in six.iteritems(map_native):
30773078
self.assertEqual(v, actual[k])
30783079

3080+
def test_raw_map_from_raw_data_works(self):
3081+
map_native = {
3082+
'foo': 'bar', 'num': 1, 'bool_type': True,
3083+
'other_b_type': False, 'floaty': 1.2, 'listy': [1, 2, 3],
3084+
'mapy': {'baz': 'bongo'}
3085+
}
3086+
map_serialized = {
3087+
3088+
'M': {
3089+
'foo': {'S': 'bar'},
3090+
'num': {'N': 1},
3091+
'bool_type': {'BOOL': True},
3092+
'other_b_type': {'BOOL': False},
3093+
'floaty': {'N': 1.2},
3094+
'listy': {'L': [{'N': 1}, {'N': 2}, {'N': 3}]},
3095+
'mapy': {'M': {'baz': {'S': 'bongo'}}}
3096+
}
3097+
}
3098+
instance = ExplicitRawMapModel(map_attr=map_native, map_id=123)
3099+
fake_db = self.database_mocker(ExplicitRawMapModel,
3100+
EXPLICIT_RAW_MAP_MODEL_TABLE_DATA,
3101+
EXPLICIT_RAW_MAP_MODEL_ITEM_DATA,
3102+
'map_id', 'N',
3103+
'123')
3104+
with patch(PATCH_METHOD, new=fake_db) as req:
3105+
item = ExplicitRawMapModel.get(123)
3106+
actual = item.map_attr
3107+
for k, v in six.iteritems(map_native):
3108+
self.assertEqual(v, actual[k])
3109+
3110+

0 commit comments

Comments
 (0)