Fixed register_delete_rule inheritance issue
This commit is contained in:
parent
0eda7a5a3c
commit
3ccc495c75
@ -140,8 +140,31 @@ class DocumentMetaclass(type):
|
|||||||
base._subclasses += (_cls,)
|
base._subclasses += (_cls,)
|
||||||
base._types = base._subclasses # TODO depreciate _types
|
base._types = base._subclasses # TODO depreciate _types
|
||||||
|
|
||||||
# Handle delete rules
|
|
||||||
Document, EmbeddedDocument, DictField = cls._import_classes()
|
Document, EmbeddedDocument, DictField = cls._import_classes()
|
||||||
|
|
||||||
|
if issubclass(new_class, Document):
|
||||||
|
new_class._collection = None
|
||||||
|
|
||||||
|
# Add class to the _document_registry
|
||||||
|
_document_registry[new_class._class_name] = new_class
|
||||||
|
|
||||||
|
# In Python 2, User-defined methods objects have special read-only
|
||||||
|
# attributes 'im_func' and 'im_self' which contain the function obj
|
||||||
|
# and class instance object respectively. With Python 3 these special
|
||||||
|
# attributes have been replaced by __func__ and __self__. The Blinker
|
||||||
|
# module continues to use im_func and im_self, so the code below
|
||||||
|
# copies __func__ into im_func and __self__ into im_self for
|
||||||
|
# classmethod objects in Document derived classes.
|
||||||
|
if PY3:
|
||||||
|
for key, val in new_class.__dict__.items():
|
||||||
|
if isinstance(val, classmethod):
|
||||||
|
f = val.__get__(new_class)
|
||||||
|
if hasattr(f, '__func__') and not hasattr(f, 'im_func'):
|
||||||
|
f.__dict__.update({'im_func': getattr(f, '__func__')})
|
||||||
|
if hasattr(f, '__self__') and not hasattr(f, 'im_self'):
|
||||||
|
f.__dict__.update({'im_self': getattr(f, '__self__')})
|
||||||
|
|
||||||
|
# Handle delete rules
|
||||||
for field in new_class._fields.itervalues():
|
for field in new_class._fields.itervalues():
|
||||||
f = field
|
f = field
|
||||||
f.owner_document = new_class
|
f.owner_document = new_class
|
||||||
@ -167,33 +190,11 @@ class DocumentMetaclass(type):
|
|||||||
field.name, delete_rule)
|
field.name, delete_rule)
|
||||||
|
|
||||||
if (field.name and hasattr(Document, field.name) and
|
if (field.name and hasattr(Document, field.name) and
|
||||||
EmbeddedDocument not in new_class.mro()):
|
EmbeddedDocument not in new_class.mro()):
|
||||||
msg = ("%s is a document method and not a valid "
|
msg = ("%s is a document method and not a valid "
|
||||||
"field name" % field.name)
|
"field name" % field.name)
|
||||||
raise InvalidDocumentError(msg)
|
raise InvalidDocumentError(msg)
|
||||||
|
|
||||||
if issubclass(new_class, Document):
|
|
||||||
new_class._collection = None
|
|
||||||
|
|
||||||
# Add class to the _document_registry
|
|
||||||
_document_registry[new_class._class_name] = new_class
|
|
||||||
|
|
||||||
# In Python 2, User-defined methods objects have special read-only
|
|
||||||
# attributes 'im_func' and 'im_self' which contain the function obj
|
|
||||||
# and class instance object respectively. With Python 3 these special
|
|
||||||
# attributes have been replaced by __func__ and __self__. The Blinker
|
|
||||||
# module continues to use im_func and im_self, so the code below
|
|
||||||
# copies __func__ into im_func and __self__ into im_self for
|
|
||||||
# classmethod objects in Document derived classes.
|
|
||||||
if PY3:
|
|
||||||
for key, val in new_class.__dict__.items():
|
|
||||||
if isinstance(val, classmethod):
|
|
||||||
f = val.__get__(new_class)
|
|
||||||
if hasattr(f, '__func__') and not hasattr(f, 'im_func'):
|
|
||||||
f.__dict__.update({'im_func': getattr(f, '__func__')})
|
|
||||||
if hasattr(f, '__self__') and not hasattr(f, 'im_self'):
|
|
||||||
f.__dict__.update({'im_self': getattr(f, '__self__')})
|
|
||||||
|
|
||||||
return new_class
|
return new_class
|
||||||
|
|
||||||
def add_to_class(self, name, value):
|
def add_to_class(self, name, value):
|
||||||
|
@ -5,7 +5,7 @@ import unittest
|
|||||||
|
|
||||||
from mongoengine import *
|
from mongoengine import *
|
||||||
|
|
||||||
from mongoengine.queryset import NULLIFY
|
from mongoengine.queryset import NULLIFY, PULL
|
||||||
from mongoengine.connection import get_db
|
from mongoengine.connection import get_db
|
||||||
|
|
||||||
__all__ = ("ClassMethodsTest", )
|
__all__ = ("ClassMethodsTest", )
|
||||||
@ -85,6 +85,25 @@ class ClassMethodsTest(unittest.TestCase):
|
|||||||
self.assertEqual(self.Person._meta['delete_rules'],
|
self.assertEqual(self.Person._meta['delete_rules'],
|
||||||
{(Job, 'employee'): NULLIFY})
|
{(Job, 'employee'): NULLIFY})
|
||||||
|
|
||||||
|
def test_register_delete_rule_inherited(self):
|
||||||
|
|
||||||
|
class Vaccine(Document):
|
||||||
|
name = StringField(required=True)
|
||||||
|
|
||||||
|
meta = {"indexes": ["name"]}
|
||||||
|
|
||||||
|
class Animal(Document):
|
||||||
|
family = StringField(required=True)
|
||||||
|
vaccine_made = ListField(ReferenceField("Vaccine", reverse_delete_rule=PULL))
|
||||||
|
|
||||||
|
meta = {"allow_inheritance": True, "indexes": ["family"]}
|
||||||
|
|
||||||
|
class Cat(Animal):
|
||||||
|
name = StringField(required=True)
|
||||||
|
|
||||||
|
self.assertEqual(Vaccine._meta['delete_rules'][(Animal, 'vaccine_made')], PULL)
|
||||||
|
self.assertEqual(Vaccine._meta['delete_rules'][(Cat, 'vaccine_made')], PULL)
|
||||||
|
|
||||||
def test_collection_naming(self):
|
def test_collection_naming(self):
|
||||||
"""Ensure that a collection with a specified name may be used.
|
"""Ensure that a collection with a specified name may be used.
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user