Skip to content

Commit

Permalink
Merge pull request #269 from Scille/rework-abstract-embedded-doc
Browse files Browse the repository at this point in the history
Rework abstract EmbeddedDocument policy to match Document
  • Loading branch information
lafrech committed May 4, 2020
2 parents dd07a0e + b71f1b7 commit 2f3322c
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 12 deletions.
22 changes: 20 additions & 2 deletions tests/test_embedded_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class MyDoc(Document):
})

assert document is not None
assert isinstance(document, MyDoc)
assert isinstance(document.embedded, MyParentEmbeddedDocument)
assert isinstance(document.embedded.embedded, MyChildEmbeddedDocument)

def test_embedded_document(self):
@self.instance.register
Expand Down Expand Up @@ -294,10 +297,25 @@ class OtherEmbedded(EmbeddedDocument):
cgc = ConcreteGrandChild(a=1, b=2, c=3, d=4)
ccgc = ConcreteConcreteGrandChild(a=1, b=2, c=3, d=4)

assert cc.to_mongo() == {'in_mongo_a_parent': 1, 'b': 2, 'c': 3, '_cls': 'ConcreteChild'}
assert cgc.to_mongo() == {'in_mongo_a_child': 1, 'b': 2, 'c': 3, 'd': 4, '_cls': 'ConcreteGrandChild'}
# Child of abstract doesn't need `cls` hint field in serialization
assert cc.to_mongo() == {'in_mongo_a_parent': 1, 'b': 2, 'c': 3}
assert cgc.to_mongo() == {'in_mongo_a_child': 1, 'b': 2, 'c': 3, 'd': 4}
# But child of non abstract does
assert ccgc.to_mongo() == {'in_mongo_a_parent': 1, 'b': 2, 'c': 3, 'd': 4, '_cls': 'ConcreteConcreteGrandChild'}

# Cannot use abstract embedded document in EmbeddedField
with pytest.raises(exceptions.DocumentDefinitionError) as exc:
@self.instance.register
class MyDoc(Document):
impossibru = fields.EmbeddedField(AbstractParent)
assert exc.value.args[0] == "EmbeddedField doesn't accept abstract embedded document"
with pytest.raises(exceptions.DocumentDefinitionError) as exc:
@self.instance.register
class MyDoc(Document):
impossibru = fields.EmbeddedField(AbstractChild)
assert exc.value.args[0] == "EmbeddedField doesn't accept abstract embedded document"


def test_bad_inheritance(self):
with pytest.raises(exceptions.DocumentDefinitionError) as exc:
@self.instance.register
Expand Down
5 changes: 2 additions & 3 deletions umongo/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ def _is_child(bases):
def _is_child_embedded_document(bases):
"""Same thing than _is_child, but for EmbeddedDocument...
"""
return any(b for b in bases
if issubclass(b, EmbeddedDocumentImplementation) and
b is not EmbeddedDocumentImplementation)
return any(b for b in bases if issubclass(b, EmbeddedDocumentImplementation) and
not b.opts.abstract)


def _on_need_add_id_field(bases, fields_dict):
Expand Down
12 changes: 6 additions & 6 deletions umongo/embedded_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ class Meta:
==================== ====================== ===========
attribute configurable in Meta description
==================== ====================== ===========
template no Origine template of the Document
template no Origin template of the embedded document
instance no Implementation's instance
abstract yes Document has no collection
and can only be inherited
allow_inheritance yes Allow the document to be subclassed
is_child no Document inherit of a non-abstract document
abstract yes Embedded document can only be inherited
allow_inheritance yes Allow the embedded document to be subclassed
is_child no Embedded document inherit of a non-abstract
embedded document
strict yes Don't accept unknown fields from mongo
(default: True)
offspring no List of EmbeddedDocuments inheriting this one
offspring no List of embedded documents inheriting this one
==================== ====================== ===========
"""
def __repr__(self):
Expand Down
5 changes: 4 additions & 1 deletion umongo/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# from .registerer import retrieve_document
from .document import DocumentImplementation
from .exceptions import NotRegisteredDocumentError
from .exceptions import NotRegisteredDocumentError, DocumentDefinitionError
from .template import get_template
from .data_objects import Reference, List, Dict
from . import marshmallow_bonus as ma_bonus_fields
Expand Down Expand Up @@ -475,6 +475,9 @@ def embedded_document_cls(self):
if not self._embedded_document_cls:
self._embedded_document_cls = self.instance.retrieve_embedded_document(
self.embedded_document)
if self._embedded_document_cls.opts.abstract:
raise DocumentDefinitionError(
"EmbeddedField doesn't accept abstract embedded document")
return self._embedded_document_cls

def _serialize(self, value, attr, obj):
Expand Down

0 comments on commit 2f3322c

Please sign in to comment.