Merge branch 'master' of github.com:MongoEngine/mongoengine into fix_cls_in_constructor

This commit is contained in:
Bastien Gérard 2018-11-13 21:48:16 +01:00
commit e50799e9c4
3 changed files with 41 additions and 19 deletions

View File

@ -6,6 +6,7 @@ Development
=========== ===========
- (Fill this out as you fix issues and develop your features). - (Fill this out as you fix issues and develop your features).
- Fix `_cls` that is not set properly in Document constructor (regression) #1950 - Fix `_cls` that is not set properly in Document constructor (regression) #1950
- Fix bug in _delta method - Update of a ListField depends on an unrelated dynamic field update #1733
- Remove deprecated `save()` method and used `insert_one()` #1899 - Remove deprecated `save()` method and used `insert_one()` #1899
================= =================

View File

@ -582,7 +582,6 @@ class BaseDocument(object):
set_fields = self._get_changed_fields() set_fields = self._get_changed_fields()
unset_data = {} unset_data = {}
parts = []
if hasattr(self, '_changed_fields'): if hasattr(self, '_changed_fields'):
set_data = {} set_data = {}
# Fetch each set item from its path # Fetch each set item from its path
@ -592,15 +591,13 @@ class BaseDocument(object):
new_path = [] new_path = []
for p in parts: for p in parts:
if isinstance(d, (ObjectId, DBRef)): if isinstance(d, (ObjectId, DBRef)):
# Don't dig in the references
break break
elif isinstance(d, list) and p.lstrip('-').isdigit(): elif isinstance(d, list) and p.isdigit():
if p[0] == '-': # An item of a list (identified by its index) is updated
p = str(len(d) + int(p))
try:
d = d[int(p)] d = d[int(p)]
except IndexError:
d = None
elif hasattr(d, 'get'): elif hasattr(d, 'get'):
# dict-like (dict, embedded document)
d = d.get(p) d = d.get(p)
new_path.append(p) new_path.append(p)
path = '.'.join(new_path) path = '.'.join(new_path)
@ -612,26 +609,26 @@ class BaseDocument(object):
# Determine if any changed items were actually unset. # Determine if any changed items were actually unset.
for path, value in set_data.items(): for path, value in set_data.items():
if value or isinstance(value, (numbers.Number, bool)): if value or isinstance(value, (numbers.Number, bool)): # Account for 0 and True that are truthy
continue continue
# If we've set a value that ain't the default value don't unset it. parts = path.split('.')
default = None
if (self._dynamic and len(parts) and parts[0] in if (self._dynamic and len(parts) and parts[0] in
self._dynamic_fields): self._dynamic_fields):
del set_data[path] del set_data[path]
unset_data[path] = 1 unset_data[path] = 1
continue continue
elif path in self._fields:
# If we've set a value that ain't the default value don't unset it.
default = None
if path in self._fields:
default = self._fields[path].default default = self._fields[path].default
else: # Perform a full lookup for lists / embedded lookups else: # Perform a full lookup for lists / embedded lookups
d = self d = self
parts = path.split('.')
db_field_name = parts.pop() db_field_name = parts.pop()
for p in parts: for p in parts:
if isinstance(d, list) and p.lstrip('-').isdigit(): if isinstance(d, list) and p.isdigit():
if p[0] == '-':
p = str(len(d) + int(p))
d = d[int(p)] d = d[int(p)]
elif (hasattr(d, '__getattribute__') and elif (hasattr(d, '__getattribute__') and
not isinstance(d, dict)): not isinstance(d, dict)):
@ -649,10 +646,9 @@ class BaseDocument(object):
default = None default = None
if default is not None: if default is not None:
if callable(default): default = default() if callable(default) else default
default = default()
if default != value: if value != default:
continue continue
del set_data[path] del set_data[path]

View File

@ -186,6 +186,31 @@ class FieldTest(MongoDBTestCase):
data_to_be_saved = sorted(person.to_mongo().keys()) data_to_be_saved = sorted(person.to_mongo().keys())
self.assertEqual(data_to_be_saved, ['age', 'created', 'userid']) self.assertEqual(data_to_be_saved, ['age', 'created', 'userid'])
def test_default_value_is_not_used_when_changing_value_to_empty_list_for_strict_doc(self):
"""List field with default can be set to the empty list (strict)"""
# Issue #1733
class Doc(Document):
x = ListField(IntField(), default=lambda: [42])
doc = Doc(x=[1]).save()
doc.x = []
doc.save()
reloaded = Doc.objects.get(id=doc.id)
self.assertEqual(reloaded.x, [])
def test_default_value_is_not_used_when_changing_value_to_empty_list_for_dyn_doc(self):
"""List field with default can be set to the empty list (dynamic)"""
# Issue #1733
class Doc(DynamicDocument):
x = ListField(IntField(), default=lambda: [42])
doc = Doc(x=[1]).save()
doc.x = []
doc.y = 2 # Was triggering the bug
doc.save()
reloaded = Doc.objects.get(id=doc.id)
self.assertEqual(reloaded.x, [])
def test_default_values_when_deleting_value(self): def test_default_values_when_deleting_value(self):
"""Ensure that default field values are used after non-default """Ensure that default field values are used after non-default
values are explicitly deleted. values are explicitly deleted.