Skip to content

Commit

Permalink
Merge c51c050 into d48c153
Browse files Browse the repository at this point in the history
  • Loading branch information
lafrech committed Nov 3, 2020
2 parents d48c153 + c51c050 commit 1d00c99
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 13 deletions.
27 changes: 27 additions & 0 deletions tests/frameworks/test_motor_asyncio.py
Expand Up @@ -112,6 +112,33 @@ async def do_test():

loop.run_until_complete(do_test())

def test_replace(self, loop, classroom_model):
Student = classroom_model.Student

async def do_test():
john = Student(name='John Doe', birthday=dt.datetime(1995, 12, 12))
# replace has no impact on creation
await john.commit(replace=True)
john.name = 'William Doe'
john.clear_modified()
ret = await john.commit(replace=True)
assert isinstance(ret, UpdateResult)
john2 = await Student.find_one(john.id)
assert john2._data == john._data
# Test conditional commit
john.name = 'Zorro Doe'
john.clear_modified()
with pytest.raises(exceptions.UpdateError):
await john.commit(conditions={'name': 'Bad Name'}, replace=True)
await john.commit(conditions={'name': 'William Doe'}, replace=True)
await john.reload()
assert john.name == 'Zorro Doe'
# Cannot use conditions when creating document
with pytest.raises(exceptions.NotCreatedError):
await Student(name='Joe').commit(conditions={'name': 'dummy'}, replace=True)

loop.run_until_complete(do_test())

def test_remove(self, loop, classroom_model):
Student = classroom_model.Student

Expand Down
23 changes: 23 additions & 0 deletions tests/frameworks/test_pymongo.py
Expand Up @@ -82,6 +82,29 @@ def test_update(self, classroom_model):
with pytest.raises(exceptions.NotCreatedError):
Student(name='Joe').commit(conditions={'name': 'dummy'})

def test_replace(self, classroom_model):
Student = classroom_model.Student
john = Student(name='John Doe', birthday=dt.datetime(1995, 12, 12))
# replace has no impact on creation
john.commit(replace=True)
john.name = 'William Doe'
john.clear_modified()
ret = john.commit(replace=True)
assert isinstance(ret, UpdateResult)
john2 = Student.find_one(john.id)
assert john2._data == john._data
# Test conditional commit
john.name = 'Zorro Doe'
john.clear_modified()
with pytest.raises(exceptions.UpdateError):
john.commit(conditions={'name': 'Bad Name'}, replace=True)
john.commit(conditions={'name': 'William Doe'}, replace=True)
john.reload()
assert john.name == 'Zorro Doe'
# Cannot use conditions when creating document
with pytest.raises(exceptions.NotCreatedError):
Student(name='Joe').commit(conditions={'name': 'dummy'}, replace=True)

def test_delete(self, classroom_model):
Student = classroom_model.Student
Student.collection.drop()
Expand Down
24 changes: 24 additions & 0 deletions tests/frameworks/test_txmongo.py
Expand Up @@ -112,6 +112,30 @@ def test_update(self, classroom_model):
with pytest.raises(exceptions.NotCreatedError):
yield Student(name='Joe').commit(conditions={'name': 'dummy'})

@pytest_inlineCallbacks
def test_replace(self, classroom_model):
Student = classroom_model.Student
john = Student(name='John Doe', birthday=dt.datetime(1995, 12, 12))
# replace has no impact on creation
yield john.commit(replace=True)
john.name = 'William Doe'
john.clear_modified()
ret = yield john.commit(replace=True)
assert isinstance(ret, UpdateResult)
john2 = yield Student.find_one(john.id)
assert john2._data == john._data
# Test conditional commit
john.name = 'Zorro Doe'
john.clear_modified()
with pytest.raises(exceptions.UpdateError):
yield john.commit(conditions={'name': 'Bad Name'}, replace=True)
yield john.commit(conditions={'name': 'William Doe'}, replace=True)
yield john.reload()
assert john.name == 'Zorro Doe'
# Cannot use conditions when creating document
with pytest.raises(exceptions.NotCreatedError):
yield Student(name='Joe').commit(conditions={'name': 'dummy'}, replace=True)

@pytest_inlineCallbacks
def test_delete(self, classroom_model):
Student = classroom_model.Student
Expand Down
13 changes: 9 additions & 4 deletions umongo/frameworks/motor_asyncio.py
Expand Up @@ -126,7 +126,7 @@ async def reload(self):
self._data = self.DataProxy()
self._data.from_mongo(ret)

async def commit(self, io_validate_all=False, conditions=None):
async def commit(self, io_validate_all=False, conditions=None, replace=False):
"""
Commit the document in database.
If the document doesn't already exist it will be inserted, otherwise
Expand All @@ -137,12 +137,13 @@ async def commit(self, io_validate_all=False, conditions=None):
satisfies condition(s) (e.g. version number).
Raises :class:`umongo.exceptions.UpdateError` if the
conditions are not satisfied.
:param replace: Replace the document rather than update.
:return: Update result dict returned by underlaying driver or
ObjectId of the inserted document.
"""
try:
if self.is_created:
if self.is_modified():
if self.is_modified() or replace:
query = conditions or {}
query['_id'] = self.pk
# pre_update can provide additional query filter and/or
Expand All @@ -152,8 +153,12 @@ async def commit(self, io_validate_all=False, conditions=None):
query.update(map_query(additional_filter, self.schema.fields))
self.required_validate()
await self.io_validate(validate_all=io_validate_all)
payload = self._data.to_mongo(update=True)
ret = await self.collection.update_one(query, payload)
if replace:
payload = self._data.to_mongo(update=False)
ret = await self.collection.replace_one(query, payload)
else:
payload = self._data.to_mongo(update=True)
ret = await self.collection.update_one(query, payload)
if ret.matched_count != 1:
raise UpdateError(ret)
await self.__coroutined_post_update(ret)
Expand Down
13 changes: 9 additions & 4 deletions umongo/frameworks/pymongo.py
Expand Up @@ -75,7 +75,7 @@ def reload(self):
self._data = self.DataProxy()
self._data.from_mongo(ret)

def commit(self, io_validate_all=False, conditions=None):
def commit(self, io_validate_all=False, conditions=None, replace=False):
"""
Commit the document in database.
If the document doesn't already exist it will be inserted, otherwise
Expand All @@ -86,12 +86,13 @@ def commit(self, io_validate_all=False, conditions=None):
satisfies condition(s) (e.g. version number).
Raises :class:`umongo.exceptions.UpdateError` if the
conditions are not satisfied.
:param replace: Replace the document rather than update.
:return: A :class:`pymongo.results.UpdateResult` or
:class:`pymongo.results.InsertOneResult` depending of the operation.
"""
try:
if self.is_created:
if self.is_modified():
if self.is_modified() or replace:
query = conditions or {}
query['_id'] = self.pk
# pre_update can provide additional query filter and/or
Expand All @@ -101,8 +102,12 @@ def commit(self, io_validate_all=False, conditions=None):
query.update(map_query(additional_filter, self.schema.fields))
self.required_validate()
self.io_validate(validate_all=io_validate_all)
payload = self._data.to_mongo(update=True)
ret = self.collection.update_one(query, payload)
if replace:
payload = self._data.to_mongo(update=False)
ret = self.collection.replace_one(query, payload)
else:
payload = self._data.to_mongo(update=True)
ret = self.collection.update_one(query, payload)
if ret.matched_count != 1:
raise UpdateError(ret)
self.post_update(ret)
Expand Down
15 changes: 10 additions & 5 deletions umongo/frameworks/txmongo.py
Expand Up @@ -38,7 +38,7 @@ def reload(self):
self._data.from_mongo(ret)

@inlineCallbacks
def commit(self, io_validate_all=False, conditions=None):
def commit(self, io_validate_all=False, conditions=None, replace=False):
"""
Commit the document in database.
If the document doesn't already exist it will be inserted, otherwise
Expand All @@ -49,12 +49,13 @@ def commit(self, io_validate_all=False, conditions=None):
satisfies condition(s) (e.g. version number).
Raises :class:`umongo.exceptions.UpdateError` if the
conditions are not satisfied.
:return: A :class:`pymongo.results.UpdateResult` or
:param replace: Replace the document rather than update.
:return: A :class:`pymongo.results.UpdateResult` or
:class:`pymongo.results.InsertOneResult` depending of the operation.
"""
try:
if self.is_created:
if self.is_modified():
if self.is_modified() or replace:
query = conditions or {}
query['_id'] = self.pk
# pre_update can provide additional query filter and/or
Expand All @@ -64,8 +65,12 @@ def commit(self, io_validate_all=False, conditions=None):
query.update(map_query(additional_filter, self.schema.fields))
self.required_validate()
yield self.io_validate(validate_all=io_validate_all)
payload = self._data.to_mongo(update=True)
ret = yield self.collection.update_one(query, payload)
if replace:
payload = self._data.to_mongo(update=False)
ret = yield self.collection.replace_one(query, payload)
else:
payload = self._data.to_mongo(update=True)
ret = yield self.collection.update_one(query, payload)
if ret.matched_count != 1:
raise UpdateError(ret)
yield maybeDeferred(self.post_update, ret)
Expand Down

0 comments on commit 1d00c99

Please sign in to comment.