Skip to content

Commit

Permalink
Merge pull request #231 from Scille/230_default_data_object
Browse files Browse the repository at this point in the history
Fix DictField/ListField default
  • Loading branch information
lafrech authored Mar 28, 2020
2 parents 3c54692 + 9b6cd3c commit f26c785
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
57 changes: 57 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,33 @@ class MySchema(Schema):
d4.from_mongo({'in_mongo_dict': None})
assert d4.get('dict') is None

def test_dict_default(self):

class MySchema(Schema):
# Passing a mutable as default is a bad idea in real life
d_dict = fields.DictField(default={'1': 1, '2': 2})
c_dict = fields.DictField(default=lambda: {'1': 1, '2': 2})

MyDataProxy = data_proxy_factory('My', MySchema())
d = MyDataProxy()
assert d.to_mongo() == {
'd_dict': {'1': 1, '2': 2},
'c_dict': {'1': 1, '2': 2},
}
assert isinstance(d.get('d_dict'), Dict)
assert isinstance(d.get('c_dict'), Dict)
d.get('d_dict')['3'] = 3
d.get('c_dict')['3'] = 3

d.delete('d_dict')
d.delete('c_dict')
assert d.to_mongo() == {
'd_dict': {'1': 1, '2': 2},
'c_dict': {'1': 1, '2': 2},
}
assert isinstance(d.get('d_dict'), Dict)
assert isinstance(d.get('c_dict'), Dict)

def test_list(self):

class MySchema(Schema):
Expand Down Expand Up @@ -360,6 +387,36 @@ class MySchema(Schema):
d3._data.get('in_mongo_list')
) == '<object umongo.data_objects.List([])>'

def test_list_default(self):

class MySchema(Schema):
d_list = fields.ListField(fields.IntField(), default=(1, 2, 3))
c_list = fields.ListField(fields.IntField(), default=lambda: (1, 2, 3))

MyDataProxy = data_proxy_factory('My', MySchema())
d = MyDataProxy()
assert d.to_mongo() == {
'd_list': [1, 2, 3],
'c_list': [1, 2, 3],
}
assert isinstance(d.get('d_list'), List)
assert isinstance(d.get('c_list'), List)
d.get('d_list').append(4)
d.get('c_list').append(4)
assert d.to_mongo(update=True) == {
'$set': {'c_list': [1, 2, 3, 4], 'd_list': [1, 2, 3, 4]}}

d.delete('d_list')
d.delete('c_list')
assert d.to_mongo() == {
'd_list': [1, 2, 3],
'c_list': [1, 2, 3],
}
assert isinstance(d.get('d_list'), List)
assert isinstance(d.get('c_list'), List)
assert d.to_mongo(update=True) == {
'$set': {'c_list': [1, 2, 3], 'd_list': [1, 2, 3]}}

def test_complex_list(self):

@self.instance.register
Expand Down
26 changes: 26 additions & 0 deletions umongo/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@

class DictField(BaseField, ma_fields.Dict):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def cast_value_or_callable(value):
if value is missing:
return missing
if callable(value):
return lambda: Dict(value())
return Dict(value)

self.default = cast_value_or_callable(self.default)
self.missing = cast_value_or_callable(self.missing)

def _deserialize(self, value, attr, data, **kwargs):
value = super()._deserialize(value, attr, data, **kwargs)
return Dict(value)
Expand All @@ -75,6 +88,19 @@ def translate_query(self, key, query):

class ListField(BaseField, ma_fields.List):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def cast_value_or_callable(inner, value):
if value is missing:
return missing
if callable(value):
return lambda: List(inner, value())
return List(inner, value)

self.default = cast_value_or_callable(self.inner, self.default)
self.missing = cast_value_or_callable(self.inner, self.missing)

def _deserialize(self, value, attr, data, **kwargs):
ret = List(self.inner, super()._deserialize(value, attr, data, **kwargs))
return ret
Expand Down

0 comments on commit f26c785

Please sign in to comment.