Compare commits

..

4 Commits

Author SHA1 Message Date
Ross Lawley
4defc82192 Version Bump 2012-09-11 15:16:39 +00:00
Ross Lawley
5949970a95 Fixed index inheritance issues
firmed up testcases (MongoEngine/mongoengine#123) (MongoEngine/mongoengine#125)
2012-09-11 15:14:37 +00:00
Ross Lawley
5c6035d636 Updated upgrade docs for BinaryFields 2012-09-11 08:56:32 +00:00
Ross Lawley
a2183e3dcc Reverted EmbeddedDocuments meta handling.
You now can turn off inheritance (MongoEngine/mongoengine#119)
2012-09-07 13:23:46 +01:00
8 changed files with 109 additions and 20 deletions

View File

@@ -2,6 +2,15 @@
Changelog Changelog
========= =========
Changes in 0.7.4
================
- Fixed index inheritance issues - firmed up testcases (MongoEngine/mongoengine#123) (MongoEngine/mongoengine#125)
Changes in 0.7.3
================
- Reverted EmbeddedDocuments meta handling - now can turn off inheritance (MongoEngine/mongoengine#119)
Changes in 0.7.2 Changes in 0.7.2
================ ================
- Update index spec generation so its not destructive (MongoEngine/mongoengine#113) - Update index spec generation so its not destructive (MongoEngine/mongoengine#113)

View File

@@ -61,6 +61,13 @@ stored in rather than as string representations. Your code may need to be
updated to handle native types rather than strings keys for the results of updated to handle native types rather than strings keys for the results of
item frequency queries. item frequency queries.
BinaryFields
------------
Binary fields have been updated so that they are native binary types. If you
previously were doing `str` comparisons with binary field values you will have
to update and wrap the value in a `str`.
0.5 to 0.6 0.5 to 0.6
========== ==========

View File

@@ -12,7 +12,7 @@ from signals import *
__all__ = (document.__all__ + fields.__all__ + connection.__all__ + __all__ = (document.__all__ + fields.__all__ + connection.__all__ +
queryset.__all__ + signals.__all__) queryset.__all__ + signals.__all__)
VERSION = (0, 7, 2) VERSION = (0, 7, 4)
def get_version(): def get_version():

View File

@@ -508,6 +508,10 @@ class DocumentMetaclass(type):
attrs['_is_document'] = attrs.get('_is_document', False) 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 # Handle document Fields
# Merge all fields from subclasses # Merge all fields from subclasses
@@ -571,6 +575,24 @@ class DocumentMetaclass(type):
superclasses[base._class_name] = base superclasses[base._class_name] = base
superclasses.update(base._superclasses) 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['_class_name'] = '.'.join(reversed(class_name))
attrs['_superclasses'] = superclasses attrs['_superclasses'] = superclasses
@@ -745,21 +767,6 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
if hasattr(base, 'meta'): if hasattr(base, 'meta'):
meta.merge(base.meta) meta.merge(base.meta)
elif hasattr(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) meta.merge(base._meta)
# Set collection in the meta if its callable # Set collection in the meta if its callable

View File

@@ -25,6 +25,14 @@ class EmbeddedDocument(BaseDocument):
collection. :class:`~mongoengine.EmbeddedDocument`\ s should be used as collection. :class:`~mongoengine.EmbeddedDocument`\ s should be used as
fields on :class:`~mongoengine.Document`\ s through the fields on :class:`~mongoengine.Document`\ s through the
:class:`~mongoengine.EmbeddedDocumentField` field type. :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 # The __metaclass__ attribute is removed by 2to3 when running with Python3

View File

@@ -501,8 +501,10 @@ class QuerySet(object):
""" """
if isinstance(spec, basestring): if isinstance(spec, basestring):
spec = {'fields': [spec]} spec = {'fields': [spec]}
if isinstance(spec, (list, tuple)): elif isinstance(spec, (list, tuple)):
spec = {'fields': spec} spec = {'fields': list(spec)}
elif isinstance(spec, dict):
spec = dict(spec)
index_list = [] index_list = []
direction = None direction = None

View File

@@ -5,7 +5,7 @@
%define srcname mongoengine %define srcname mongoengine
Name: python-%{srcname} Name: python-%{srcname}
Version: 0.7.2 Version: 0.7.4
Release: 1%{?dist} Release: 1%{?dist}
Summary: A Python Document-Object Mapper for working with MongoDB Summary: A Python Document-Object Mapper for working with MongoDB

View File

@@ -338,7 +338,6 @@ class DocumentTest(unittest.TestCase):
meta = {'allow_inheritance': False} meta = {'allow_inheritance': False}
self.assertRaises(ValueError, create_employee_class) self.assertRaises(ValueError, create_employee_class)
def test_allow_inheritance_abstract_document(self): def test_allow_inheritance_abstract_document(self):
"""Ensure that abstract documents can set inheritance rules and that """Ensure that abstract documents can set inheritance rules and that
_cls and _types will not be used. _cls and _types will not be used.
@@ -366,6 +365,31 @@ class DocumentTest(unittest.TestCase):
Animal.drop_collection() 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): def test_document_inheritance(self):
"""Ensure mutliple inheritance of abstract docs works """Ensure mutliple inheritance of abstract docs works
""" """
@@ -396,6 +420,9 @@ class DocumentTest(unittest.TestCase):
'indexes': ['name'] 'indexes': ['name']
} }
self.assertEqual(Animal._meta['index_specs'],
[{'fields': [('_types', 1), ('name', 1)]}])
Animal.drop_collection() Animal.drop_collection()
dog = Animal(name='dog') dog = Animal(name='dog')
@@ -417,6 +444,9 @@ class DocumentTest(unittest.TestCase):
'allow_inheritance': False, 'allow_inheritance': False,
'indexes': ['name'] 'indexes': ['name']
} }
self.assertEqual(Animal._meta['index_specs'],
[{'fields': [('name', 1)]}])
collection.update({}, {"$unset": {"_types": 1, "_cls": 1}}, multi=True) collection.update({}, {"$unset": {"_types": 1, "_cls": 1}}, multi=True)
# Confirm extra data is removed # Confirm extra data is removed
@@ -634,6 +664,12 @@ class DocumentTest(unittest.TestCase):
'allow_inheritance': True 'allow_inheritance': True
} }
self.assertEqual(BlogPost._meta['index_specs'],
[{'fields': [('_types', 1), ('addDate', -1)]},
{'fields': [('tags', 1)]},
{'fields': [('_types', 1), ('category', 1),
('addDate', -1)]}])
BlogPost.drop_collection() BlogPost.drop_collection()
info = BlogPost.objects._collection.index_information() info = BlogPost.objects._collection.index_information()
@@ -657,6 +693,13 @@ class DocumentTest(unittest.TestCase):
title = StringField() title = StringField()
meta = {'indexes': ['title']} meta = {'indexes': ['title']}
self.assertEqual(ExtendedBlogPost._meta['index_specs'],
[{'fields': [('_types', 1), ('addDate', -1)]},
{'fields': [('tags', 1)]},
{'fields': [('_types', 1), ('category', 1),
('addDate', -1)]},
{'fields': [('_types', 1), ('title', 1)]}])
BlogPost.drop_collection() BlogPost.drop_collection()
list(ExtendedBlogPost.objects) list(ExtendedBlogPost.objects)
@@ -687,6 +730,8 @@ class DocumentTest(unittest.TestCase):
description = StringField() description = StringField()
self.assertEqual(A._meta['index_specs'], B._meta['index_specs']) self.assertEqual(A._meta['index_specs'], B._meta['index_specs'])
self.assertEqual([{'fields': [('_types', 1), ('title', 1)]}],
A._meta['index_specs'])
def test_build_index_spec_is_not_destructive(self): def test_build_index_spec_is_not_destructive(self):
@@ -767,6 +812,9 @@ class DocumentTest(unittest.TestCase):
'allow_inheritance': False 'allow_inheritance': False
} }
self.assertEqual([{'fields': [('rank.title', 1)]}],
Person._meta['index_specs'])
Person.drop_collection() Person.drop_collection()
# Indexes are lazy so use list() to perform query # Indexes are lazy so use list() to perform query
@@ -785,6 +833,10 @@ class DocumentTest(unittest.TestCase):
'*location.point', '*location.point',
], ],
} }
self.assertEqual([{'fields': [('location.point', '2d')]}],
Place._meta['index_specs'])
Place.drop_collection() Place.drop_collection()
info = Place.objects._collection.index_information() info = Place.objects._collection.index_information()
@@ -810,6 +862,10 @@ class DocumentTest(unittest.TestCase):
], ],
} }
self.assertEqual([{'fields': [('addDate', -1)], 'unique': True,
'sparse': True, 'types': False}],
BlogPost._meta['index_specs'])
BlogPost.drop_collection() BlogPost.drop_collection()
info = BlogPost.objects._collection.index_information() info = BlogPost.objects._collection.index_information()