From e231f71b4a373c103084636f8647e1328843f527 Mon Sep 17 00:00:00 2001 From: Ross Lawley Date: Fri, 2 Dec 2011 02:46:55 -0800 Subject: [PATCH] EmbeddedDocuments dont support Reverse Delete Rules Now throws an InvalidDocumentError Refs #227 --- docs/upgrade.rst | 5 +++-- mongoengine/base.py | 14 ++++++++++++++ tests/document.py | 8 ++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/docs/upgrade.rst b/docs/upgrade.rst index 1b25c076..cb72b356 100644 --- a/docs/upgrade.rst +++ b/docs/upgrade.rst @@ -8,10 +8,11 @@ Upgrading Embedded Documents - if you had a `pk` field you will have to rename it from `_id` to `pk` as pk is no longer a property of Embedded Documents. +Reverse Delete Rules in Embedded Documents, MapFields and DictFields now throw +an InvalidDocument error as they aren't currently supported. + Document._get_subclasses - Is no longer used and the class method has been removed. -Reverse Delete Rules on MapFields and DictFields now throw a InvalidDocument error -as they aren't supported. 0.4 to 0.5 =========== diff --git a/mongoengine/base.py b/mongoengine/base.py index 29be8764..00dd2eeb 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -518,6 +518,8 @@ class DocumentMetaclass(type): f = field.field if delete_rule != DO_NOTHING: + if issubclass(new_class, EmbeddedDocument): + raise InvalidDocumentError("Reverse delete rules are not supported for EmbeddedDocuments (field: %s)" % field.name) f.document_type.register_delete_rule(new_class, field.name, delete_rule) if field.name and hasattr(Document, field.name) and EmbeddedDocument not in new_class.mro(): @@ -663,6 +665,18 @@ class TopLevelDocumentMetaclass(DocumentMetaclass): return new_class + def __instancecheck__(cls, inst): + """Custom instance check for isinstance() as registering delete rules or + calling a cls method in __new__ seems to change the cls so vanilla + isinstance() fails""" + is_instance = super(DocumentMetaclass, cls).__instancecheck__(inst) + if hasattr(cls, '_meta') and 'delete_rules' in cls._meta and not is_instance: + try: + is_instance = get_document(cls.__name__) == get_document(inst.__class__.__name__) + except NotRegistered: + pass + return is_instance + @classmethod def _unique_with_indexes(cls, new_class, namespace=""): unique_indexes = [] diff --git a/tests/document.py b/tests/document.py index 391c3e25..a4f09929 100644 --- a/tests/document.py +++ b/tests/document.py @@ -2245,6 +2245,8 @@ class DocumentTest(unittest.TestCase): author.delete() self.assertEqual(len(BlogPost.objects), 0) + def test_invalid_reverse_delete_rules_raise_errors(self): + def throw_invalid_document_error(): class Blog(Document): content = StringField() @@ -2253,6 +2255,12 @@ class DocumentTest(unittest.TestCase): self.assertRaises(InvalidDocumentError, throw_invalid_document_error) + def throw_invalid_document_error_embedded(): + class Parents(EmbeddedDocument): + father = ReferenceField('Person', reverse_delete_rule=DENY) + mother = ReferenceField('Person', reverse_delete_rule=DENY) + + self.assertRaises(InvalidDocumentError, throw_invalid_document_error_embedded) def test_reverse_delete_rule_cascade_recurs(self): """Ensure that a chain of documents is also deleted upon cascaded