Added Abstract Base Classes
Thanks to @theojulienne for the code :) #108
This commit is contained in:
parent
1126c85903
commit
088c40f9f2
@ -253,7 +253,16 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
|
|||||||
# __metaclass__ is only set on the class with the __metaclass__
|
# __metaclass__ is only set on the class with the __metaclass__
|
||||||
# attribute (i.e. it is not set on subclasses). This differentiates
|
# attribute (i.e. it is not set on subclasses). This differentiates
|
||||||
# 'real' documents from the 'Document' class
|
# 'real' documents from the 'Document' class
|
||||||
if attrs.get('__metaclass__') == TopLevelDocumentMetaclass:
|
#
|
||||||
|
# Also assume a class is abstract if it has abstract set to True in
|
||||||
|
# its meta dictionary. This allows custom Document superclasses.
|
||||||
|
if (attrs.get('__metaclass__') == TopLevelDocumentMetaclass or
|
||||||
|
('meta' in attrs and attrs['meta'].get('abstract', False))):
|
||||||
|
# Make sure no base class was non-abstract
|
||||||
|
non_abstract_bases = [b for b in bases
|
||||||
|
if hasattr(b,'_meta') and not b._meta.get('abstract', False)]
|
||||||
|
if non_abstract_bases:
|
||||||
|
raise ValueError("Abstract document cannot have non-abstract base")
|
||||||
return super_new(cls, name, bases, attrs)
|
return super_new(cls, name, bases, attrs)
|
||||||
|
|
||||||
collection = name.lower()
|
collection = name.lower()
|
||||||
@ -276,6 +285,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
|
|||||||
base_indexes += base._meta.get('indexes', [])
|
base_indexes += base._meta.get('indexes', [])
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
|
'abstract': False,
|
||||||
'collection': collection,
|
'collection': collection,
|
||||||
'max_documents': None,
|
'max_documents': None,
|
||||||
'max_size': None,
|
'max_size': None,
|
||||||
|
@ -29,6 +29,9 @@ class DocumentTest(unittest.TestCase):
|
|||||||
age = IntField()
|
age = IntField()
|
||||||
self.Person = Person
|
self.Person = Person
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.Person.drop_collection()
|
||||||
|
|
||||||
def test_drop_collection(self):
|
def test_drop_collection(self):
|
||||||
"""Ensure that the collection may be dropped from the database.
|
"""Ensure that the collection may be dropped from the database.
|
||||||
"""
|
"""
|
||||||
@ -188,6 +191,34 @@ class DocumentTest(unittest.TestCase):
|
|||||||
self.assertFalse('_cls' in comment.to_mongo())
|
self.assertFalse('_cls' in comment.to_mongo())
|
||||||
self.assertFalse('_types' in comment.to_mongo())
|
self.assertFalse('_types' in comment.to_mongo())
|
||||||
|
|
||||||
|
def test_abstract_documents(self):
|
||||||
|
"""Ensure that a document superclass can be marked as abstract
|
||||||
|
thereby not using it as the name for the collection."""
|
||||||
|
|
||||||
|
class Animal(Document):
|
||||||
|
name = StringField()
|
||||||
|
meta = {'abstract': True}
|
||||||
|
|
||||||
|
class Fish(Animal): pass
|
||||||
|
class Guppy(Fish): pass
|
||||||
|
|
||||||
|
class Mammal(Animal):
|
||||||
|
meta = {'abstract': True}
|
||||||
|
class Human(Mammal): pass
|
||||||
|
|
||||||
|
self.assertFalse('collection' in Animal._meta)
|
||||||
|
self.assertFalse('collection' in Mammal._meta)
|
||||||
|
|
||||||
|
self.assertEqual(Fish._meta['collection'], 'fish')
|
||||||
|
self.assertEqual(Guppy._meta['collection'], 'fish')
|
||||||
|
self.assertEqual(Human._meta['collection'], 'human')
|
||||||
|
|
||||||
|
def create_bad_abstract():
|
||||||
|
class EvilHuman(Human):
|
||||||
|
evil = BooleanField(default=True)
|
||||||
|
meta = {'abstract': True}
|
||||||
|
self.assertRaises(ValueError, create_bad_abstract)
|
||||||
|
|
||||||
def test_collection_name(self):
|
def test_collection_name(self):
|
||||||
"""Ensure that a collection with a specified name may be used.
|
"""Ensure that a collection with a specified name may be used.
|
||||||
"""
|
"""
|
||||||
@ -907,9 +938,6 @@ class DocumentTest(unittest.TestCase):
|
|||||||
A.drop_collection()
|
A.drop_collection()
|
||||||
B.drop_collection()
|
B.drop_collection()
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
self.Person.drop_collection()
|
|
||||||
|
|
||||||
def test_document_hash(self):
|
def test_document_hash(self):
|
||||||
"""Test document in list, dict, set
|
"""Test document in list, dict, set
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user