diff --git a/docs/changelog.rst b/docs/changelog.rst index b4c31436..2d10507d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,10 @@ Changelog ========= +Changes in 0.7.3 +================ +- Reverted EmbeddedDocuments meta handling - now can turn off inheritance (MongoEngine/mongoengine#119) + Changes in 0.7.2 ================ - Update index spec generation so its not destructive (MongoEngine/mongoengine#113) diff --git a/mongoengine/__init__.py b/mongoengine/__init__.py index e91e81f2..f5668c43 100644 --- a/mongoengine/__init__.py +++ b/mongoengine/__init__.py @@ -12,7 +12,7 @@ from signals import * __all__ = (document.__all__ + fields.__all__ + connection.__all__ + queryset.__all__ + signals.__all__) -VERSION = (0, 7, 2) +VERSION = (0, 7, 3) def get_version(): diff --git a/mongoengine/base.py b/mongoengine/base.py index dc7ef8a0..6e4cd917 100644 --- a/mongoengine/base.py +++ b/mongoengine/base.py @@ -508,6 +508,10 @@ class DocumentMetaclass(type): attrs['_is_document'] = attrs.get('_is_document', False) + # EmbeddedDocuments could have meta data for inheritance + if 'meta' in attrs: + attrs['_meta'] = attrs.pop('meta') + # Handle document Fields # Merge all fields from subclasses @@ -571,6 +575,24 @@ class DocumentMetaclass(type): superclasses[base._class_name] = base superclasses.update(base._superclasses) + if hasattr(base, '_meta'): + # Warn if allow_inheritance isn't set and prevent + # inheritance of classes where inheritance is set to False + allow_inheritance = base._meta.get('allow_inheritance', + ALLOW_INHERITANCE) + if (not getattr(base, '_is_base_cls', True) + and allow_inheritance is None): + warnings.warn( + "%s uses inheritance, the default for " + "allow_inheritance is changing to off by default. " + "Please add it to the document meta." % name, + FutureWarning + ) + elif (allow_inheritance == False and + not base._meta.get('abstract')): + raise ValueError('Document %s may not be subclassed' % + base.__name__) + attrs['_class_name'] = '.'.join(reversed(class_name)) attrs['_superclasses'] = superclasses @@ -745,21 +767,6 @@ class TopLevelDocumentMetaclass(DocumentMetaclass): if hasattr(base, 'meta'): meta.merge(base.meta) elif hasattr(base, '_meta'): - # Warn if allow_inheritance isn't set and prevent - # inheritance of classes where inheritance is set to False - allow_inheritance = base._meta.get('allow_inheritance', - ALLOW_INHERITANCE) - if not base._is_base_cls and allow_inheritance is None: - warnings.warn( - "%s uses inheritance, the default for " - "allow_inheritance is changing to off by default. " - "Please add it to the document meta." % name, - FutureWarning - ) - elif (allow_inheritance == False and - not base._meta.get('abstract')): - raise ValueError('Document %s may not be subclassed' % - base.__name__) meta.merge(base._meta) # Set collection in the meta if its callable diff --git a/mongoengine/document.py b/mongoengine/document.py index 9d528cbc..23009dbb 100644 --- a/mongoengine/document.py +++ b/mongoengine/document.py @@ -25,6 +25,14 @@ class EmbeddedDocument(BaseDocument): collection. :class:`~mongoengine.EmbeddedDocument`\ s should be used as fields on :class:`~mongoengine.Document`\ s through the :class:`~mongoengine.EmbeddedDocumentField` field type. + + A :class:`~mongoengine.EmbeddedDocument` subclass may be itself subclassed, + to create a specialised version of the embedded document that will be + stored in the same collection. To facilitate this behaviour, `_cls` and + `_types` fields are added to documents (hidden though the MongoEngine + interface though). To disable this behaviour and remove the dependence on + the presence of `_cls` and `_types`, set :attr:`allow_inheritance` to + ``False`` in the :attr:`meta` dictionary. """ # The __metaclass__ attribute is removed by 2to3 when running with Python3 diff --git a/python-mongoengine.spec b/python-mongoengine.spec index 9dbb16f8..12b867c0 100644 --- a/python-mongoengine.spec +++ b/python-mongoengine.spec @@ -5,7 +5,7 @@ %define srcname mongoengine Name: python-%{srcname} -Version: 0.7.2 +Version: 0.7.3 Release: 1%{?dist} Summary: A Python Document-Object Mapper for working with MongoDB diff --git a/tests/test_document.py b/tests/test_document.py index 9637bfeb..48ff8223 100644 --- a/tests/test_document.py +++ b/tests/test_document.py @@ -338,7 +338,6 @@ class DocumentTest(unittest.TestCase): meta = {'allow_inheritance': False} self.assertRaises(ValueError, create_employee_class) - def test_allow_inheritance_abstract_document(self): """Ensure that abstract documents can set inheritance rules and that _cls and _types will not be used. @@ -366,6 +365,31 @@ class DocumentTest(unittest.TestCase): Animal.drop_collection() + def test_allow_inheritance_embedded_document(self): + + # Test the same for embedded documents + class Comment(EmbeddedDocument): + content = StringField() + meta = {'allow_inheritance': False} + + def create_special_comment(): + class SpecialComment(Comment): + pass + + self.assertRaises(ValueError, create_special_comment) + + comment = Comment(content='test') + self.assertFalse('_cls' in comment.to_mongo()) + self.assertFalse('_types' in comment.to_mongo()) + + class Comment(EmbeddedDocument): + content = StringField() + meta = {'allow_inheritance': True} + + comment = Comment(content='test') + self.assertTrue('_cls' in comment.to_mongo()) + self.assertTrue('_types' in comment.to_mongo()) + def test_document_inheritance(self): """Ensure mutliple inheritance of abstract docs works """