diff --git a/mongoengine/dereference.py b/mongoengine/dereference.py index 18b365cc..40bc72b2 100644 --- a/mongoengine/dereference.py +++ b/mongoengine/dereference.py @@ -133,7 +133,12 @@ class DeReference(object): """ object_map = {} for collection, dbrefs in self.reference_map.iteritems(): - if hasattr(collection, 'objects'): # We have a document class for the refs + + # we use getattr instead of hasattr because as hasattr swallows any exception under python2 + # so it could hide nasty things without raising exceptions (cfr bug #1688)) + ref_document_cls_exists = (getattr(collection, 'objects', None) is not None) + + if ref_document_cls_exists: col_name = collection._get_collection_name() refs = [dbref for dbref in dbrefs if (col_name, dbref) not in object_map] diff --git a/tests/document/instance.py b/tests/document/instance.py index b255e8a6..c933eaf4 100644 --- a/tests/document/instance.py +++ b/tests/document/instance.py @@ -8,9 +8,12 @@ import weakref from datetime import datetime from bson import DBRef, ObjectId +from pymongo.errors import DuplicateKeyError + from tests import fixtures from tests.fixtures import (PickleEmbedded, PickleTest, PickleSignalsTest, PickleDynamicEmbedded, PickleDynamicTest) +from tests.utils import MongoDBTestCase from mongoengine import * from mongoengine.base import get_document, _document_registry @@ -30,12 +33,9 @@ TEST_IMAGE_PATH = os.path.join(os.path.dirname(__file__), __all__ = ("InstanceTest",) -class InstanceTest(unittest.TestCase): +class InstanceTest(MongoDBTestCase): def setUp(self): - connect(db='mongoenginetest') - self.db = get_db() - class Job(EmbeddedDocument): name = StringField() years = IntField() @@ -3248,6 +3248,23 @@ class InstanceTest(unittest.TestCase): blog.reload() self.assertEqual(blog.tags, [["value1", 123]]) + def test_accessing_objects_with_indexes_error(self): + insert_result = self.db.company.insert_many([{'name': 'Foo'}, + {'name': 'Foo'}]) # Force 2 doc with same name + REF_OID = insert_result.inserted_ids[0] + self.db.user.insert_one({'company': REF_OID}) # Force 2 doc with same name + + class Company(Document): + name = StringField(unique=True) + + class User(Document): + company = ReferenceField(Company) + + + # Ensure index creation exception aren't swallowed (#1688) + with self.assertRaises(DuplicateKeyError): + User.objects().select_related() + if __name__ == '__main__': unittest.main()