diff --git a/AUTHORS b/AUTHORS index ffd63227..34f8903f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -210,3 +210,4 @@ that much better: * Jay Shirley (https://github.com/jshirley) * DavidBord (https://github.com/DavidBord) * Axel Haustant (https://github.com/noirbizarre) + * David Czarnecki (https://github.com/czarneckid) diff --git a/docs/changelog.rst b/docs/changelog.rst index f17a61c2..b8467381 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,8 @@ Changelog Changes in 0.9.X - DEV ====================== +- Add Support For MongoDB 2.6.X's maxTimeMS #778 +- abstract shouldn't be inherited in EmbeddedDocument # 789 - Allow specifying the '_cls' as a field for indexes #397 - Stop ensure_indexes running on a secondaries unless connection is through mongos #746 - Not overriding default values when loading a subset of fields #399 @@ -54,6 +56,8 @@ Changes in 0.9.X - DEV - Allow atomic update for the entire `DictField` #742 - Added MultiPointField, MultiLineField, MultiPolygonField - Fix multiple connections aliases being rewritten #748 +- Fixed a few instances where reverse_delete_rule was written as reverse_delete_rules. #791 + Changes in 0.8.7 ================ diff --git a/docs/guide/signals.rst b/docs/guide/signals.rst index dc295d47..fc93e4ca 100644 --- a/docs/guide/signals.rst +++ b/docs/guide/signals.rst @@ -145,7 +145,7 @@ cleaner looking while still allowing manual execution of the callback:: ReferenceFields and Signals --------------------------- -Currently `reverse_delete_rules` do not trigger signals on the other part of +Currently `reverse_delete_rule` does not trigger signals on the other part of the relationship. If this is required you must manually handle the reverse deletion. diff --git a/docs/guide/text-indexes.rst b/docs/guide/text-indexes.rst index b597d957..695159c6 100644 --- a/docs/guide/text-indexes.rst +++ b/docs/guide/text-indexes.rst @@ -46,4 +46,6 @@ Next, start a text search using :attr:`QuerySet.search_text` method:: Ordering by text score ====================== +:: + objects = News.objects.search('mongo').order_by('$text_score') diff --git a/mongoengine/__init__.py b/mongoengine/__init__.py index ac33ad2b..b215181a 100644 --- a/mongoengine/__init__.py +++ b/mongoengine/__init__.py @@ -15,7 +15,7 @@ import django __all__ = (list(document.__all__) + fields.__all__ + connection.__all__ + list(queryset.__all__) + signals.__all__ + list(errors.__all__)) -VERSION = (0, 8, 7) +VERSION = (0, 9, 0) def get_version(): diff --git a/mongoengine/base/metaclasses.py b/mongoengine/base/metaclasses.py index e8014553..48da84f4 100644 --- a/mongoengine/base/metaclasses.py +++ b/mongoengine/base/metaclasses.py @@ -46,8 +46,9 @@ class DocumentMetaclass(type): elif hasattr(base, '_meta'): meta.merge(base._meta) attrs['_meta'] = meta + attrs['_meta']['abstract'] = False # 789: EmbeddedDocument shouldn't inherit abstract - if '_meta' in attrs and attrs['_meta'].get('allow_inheritance', ALLOW_INHERITANCE): + if attrs['_meta'].get('allow_inheritance', ALLOW_INHERITANCE): StringField = _import_class('StringField') attrs['_cls'] = StringField() diff --git a/mongoengine/fields.py b/mongoengine/fields.py index 2441a754..870d09e5 100644 --- a/mongoengine/fields.py +++ b/mongoengine/fields.py @@ -859,7 +859,7 @@ class ReferenceField(BaseField): Use the `reverse_delete_rule` to handle what should happen if the document the field is referencing is deleted. EmbeddedDocuments, DictFields and - MapFields do not support reverse_delete_rules and an `InvalidDocumentError` + MapFields does not support reverse_delete_rule and an `InvalidDocumentError` will be raised if trying to set on one of these Document / Field types. The options are: @@ -883,7 +883,7 @@ class ReferenceField(BaseField): Bar.register_delete_rule(Foo, 'bar', NULLIFY) .. note :: - `reverse_delete_rules` do not trigger pre / post delete signals to be + `reverse_delete_rule` does not trigger pre / post delete signals to be triggered. .. versionchanged:: 0.5 added `reverse_delete_rule` diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py index 7094dacc..f10b1e32 100644 --- a/mongoengine/queryset/base.py +++ b/mongoengine/queryset/base.py @@ -82,6 +82,7 @@ class BaseQuerySet(object): self._skip = None self._hint = -1 # Using -1 as None is a valid value for hint self.only_fields = [] + self._max_time_ms = None def __call__(self, q_obj=None, class_check=True, slave_okay=False, read_preference=None, **query): @@ -672,7 +673,7 @@ class BaseQuerySet(object): '_timeout', '_class_check', '_slave_okay', '_read_preference', '_iter', '_scalar', '_as_pymongo', '_as_pymongo_coerce', '_limit', '_skip', '_hint', '_auto_dereference', - '_search_text', '_include_text_scores', 'only_fields') + '_search_text', '_include_text_scores', 'only_fields', '_max_time_ms') for prop in copy_props: val = getattr(self, prop) @@ -969,6 +970,13 @@ class BaseQuerySet(object): queryset._as_pymongo_coerce = coerce_types return queryset + def max_time_ms(self, ms): + """Wait `ms` milliseconds before killing the query on the server + + :param ms: the number of milliseconds before killing the query on the server + """ + return self._chainable_method("max_time_ms", ms) + # JSON Helpers def to_json(self, *args, **kwargs): @@ -1700,6 +1708,13 @@ class BaseQuerySet(object): code) return code + def _chainable_method(self, method_name, val): + queryset = self.clone() + method = getattr(queryset._cursor, method_name) + method(val) + setattr(queryset, "_" + method_name, val) + return queryset + # Deprecated def ensure_index(self, **kwargs): """Deprecated use :func:`Document.ensure_index`""" diff --git a/tests/document/inheritance.py b/tests/document/inheritance.py index 566d3699..e8347054 100644 --- a/tests/document/inheritance.py +++ b/tests/document/inheritance.py @@ -397,6 +397,16 @@ class InheritanceTest(unittest.TestCase): meta = {'abstract': True} self.assertRaises(ValueError, create_bad_abstract) + def test_abstract_embedded_documents(self): + # 789: EmbeddedDocument shouldn't inherit abstract + class A(EmbeddedDocument): + meta = {"abstract": True} + + class B(A): + pass + + self.assertFalse(B._meta["abstract"]) + def test_inherited_collections(self): """Ensure that subclassed documents don't override parents' collections diff --git a/tests/document/instance.py b/tests/document/instance.py index 0982a527..360d5385 100644 --- a/tests/document/instance.py +++ b/tests/document/instance.py @@ -1858,7 +1858,7 @@ class InstanceTest(unittest.TestCase): self.assertEqual(Bar.objects.count(), 1) # No effect on the BlogPost self.assertEqual(Bar.objects.get().foo, None) - def test_invalid_reverse_delete_rules_raise_errors(self): + def test_invalid_reverse_delete_rule_raise_errors(self): def throw_invalid_document_error(): class Blog(Document): diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index fc56df7d..8efee8b3 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -4401,6 +4401,10 @@ class QuerySetTest(unittest.TestCase): self.Person.objects().delete() self.assertEqual(self.Person.objects().skip(1).delete(), 0) # test Document delete without existing documents + def test_max_time_ms(self): + # 778: max_time_ms can get only int or None as input + self.assertRaises(TypeError, self.Person.objects(name="name").max_time_ms, "not a number") + if __name__ == '__main__': unittest.main()