Skip to content

Commit

Permalink
Raise AlreadyCreatedError when modifying pk of created document
Browse files Browse the repository at this point in the history
  • Loading branch information
lafrech committed Apr 26, 2020
1 parent ab81833 commit 6de2473
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 14 deletions.
22 changes: 22 additions & 0 deletions tests/test_document.py
Expand Up @@ -419,6 +419,28 @@ class Parent(Document):
assert jane.id != john.id
assert jane.name == 'John Doe'

def test_modify_pk_field(self):

@self.instance.register
class User(Document):
primary_key = fields.ObjectIdField(attribute='_id', default=ObjectId)
name = fields.StrField()

john = User()
john.primary_key = ObjectId()
john.from_mongo({'name': 'John Doc'})
assert john.is_created
with pytest.raises(exceptions.AlreadyCreatedError):
john.primary_key = ObjectId()
with pytest.raises(exceptions.AlreadyCreatedError):
john['primary_key'] = ObjectId()
with pytest.raises(exceptions.AlreadyCreatedError):
del john.primary_key
with pytest.raises(exceptions.AlreadyCreatedError):
del john['primary_key']
with pytest.raises(exceptions.AlreadyCreatedError):
john.update({'primary_key': ObjectId()})


class TestConfig(BaseTest):

Expand Down
2 changes: 2 additions & 0 deletions umongo/__init__.py
Expand Up @@ -20,6 +20,7 @@
ValidationError,
UpdateError,
DeleteError,
AlreadyCreatedError,
NotCreatedError,
NoneReferenceError,
UnknownFieldInDBError,
Expand Down Expand Up @@ -56,6 +57,7 @@
'ValidationError',
'UpdateError',
'DeleteError',
'AlreadyCreatedError',
'NotCreatedError',
'NoneReferenceError',
'UnknownFieldInDBError',
Expand Down
35 changes: 21 additions & 14 deletions umongo/document.py
Expand Up @@ -5,7 +5,7 @@

from .abstract import BaseDataObject
from .data_proxy import missing
from .exceptions import (NotCreatedError, NoDBDefinedError,
from .exceptions import (AlreadyCreatedError, NotCreatedError, NoDBDefinedError,
AbstractDocumentError, DocumentDefinitionError)
from .template import Implementation, Template, MetaImplementation
from .data_objects import Reference
Expand Down Expand Up @@ -233,14 +233,13 @@ def to_mongo(self, update=False):
update payload instead of containing the entire document
"""
if update and not self.is_created:
raise NotCreatedError('Must create the document before'
' using update')
raise NotCreatedError('Must create the document before using update')
return self._data.to_mongo(update=update)

def update(self, data):
"""
Update the document with the given data.
"""
"""Update the document with the given data."""
if self.is_created and self.pk_field in data.keys():
raise AlreadyCreatedError("Can't modify id of a created document")
self._data.update(data)

def dump(self):
Expand Down Expand Up @@ -273,11 +272,21 @@ def __getitem__(self, name):
value = self._data.get(name)
return value if value is not missing else None

def __setitem__(self, name, value):
if self.is_created and name == self.pk_field:
raise AlreadyCreatedError("Can't modify id of a created document")
self._data.set(name, value)

def __delitem__(self, name):
if self.is_created and name == self.pk_field:
raise AlreadyCreatedError("Can't modify id of a created document")
self._data.delete(name)

def __setitem__(self, name, value):
self._data.set(name, value)
def __getattr__(self, name):
if name[:2] == name[-2:] == '__':
raise AttributeError(name)
value = self._data.get(name, to_raise=AttributeError)
return value if value is not missing else None

def __setattr__(self, name, value):
# Try to retrieve name among class's attributes and __slots__
Expand All @@ -288,20 +297,18 @@ def __setattr__(self, name, value):
if name in self.__real_attributes:
object.__setattr__(self, name, value)
else:
if self.is_created and name == self.pk_field:
raise AlreadyCreatedError("Can't modify id of a created document")
self._data.set(name, value, to_raise=AttributeError)

def __getattr__(self, name):
if name[:2] == name[-2:] == '__':
raise AttributeError(name)
value = self._data.get(name, to_raise=AttributeError)
return value if value is not missing else None

def __delattr__(self, name):
if not self.__real_attributes:
type(self).__real_attributes = dir(self)
if name in self.__real_attributes:
object.__delattr__(self, name)
else:
if self.is_created and name == self.pk_field:
raise AlreadyCreatedError("Can't modify pk of a created document")
self._data.delete(name, to_raise=AttributeError)

# Callbacks
Expand Down
4 changes: 4 additions & 0 deletions umongo/exceptions.py
Expand Up @@ -38,6 +38,10 @@ class DeleteError(UMongoError):
"""Error while deleting document"""


class AlreadyCreatedError(UMongoError):
"""Modifying id of an already created document"""


class NotCreatedError(UMongoError):
"""Document does not exist in database"""

Expand Down

0 comments on commit 6de2473

Please sign in to comment.