From cb77bb6b69bb80c79c97d2f0792d173fc2f443d4 Mon Sep 17 00:00:00 2001 From: Filip Kucharczyk Date: Thu, 5 Dec 2019 00:21:03 +0100 Subject: [PATCH] Implement __bool__ on Q and QCombination --- mongoengine/queryset/base.py | 2 +- mongoengine/queryset/visitor.py | 20 ++++++++++++++++---- tests/queryset/test_visitor.py | 11 +++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/mongoengine/queryset/base.py b/mongoengine/queryset/base.py index a648391e..c6f467cc 100644 --- a/mongoengine/queryset/base.py +++ b/mongoengine/queryset/base.py @@ -686,7 +686,7 @@ class BaseQuerySet(object): .. versionchanged:: 0.6 Raises InvalidQueryError if filter has been set """ queryset = self.clone() - if not queryset._query_obj.empty: + if queryset._query_obj: msg = "Cannot use a filter whilst using `with_id`" raise InvalidQueryError(msg) return queryset.filter(pk=object_id).first() diff --git a/mongoengine/queryset/visitor.py b/mongoengine/queryset/visitor.py index 058c722a..a7295ae5 100644 --- a/mongoengine/queryset/visitor.py +++ b/mongoengine/queryset/visitor.py @@ -2,6 +2,8 @@ import copy from mongoengine.errors import InvalidQueryError from mongoengine.queryset import transform +import warnings + __all__ = ("Q", "QNode") @@ -101,13 +103,15 @@ class QNode(object): return self # Or if this Q is empty, ignore it and just use `other`. - if self.empty: + if not self: return other return QCombination(operation, [self, other]) @property def empty(self): + msg = "'empty' property is deprecated in favour of using 'not bool(filter)" + warnings.warn(msg, DeprecationWarning) return False def __or__(self, other): @@ -137,6 +141,9 @@ class QCombination(QNode): op = " & " if self.operation is self.AND else " | " return "(%s)" % op.join([repr(node) for node in self.children]) + def __bool__(self): + return bool(self.children) + def accept(self, visitor): for i in range(len(self.children)): if isinstance(self.children[i], QNode): @@ -146,6 +153,8 @@ class QCombination(QNode): @property def empty(self): + msg = "'empty' property is deprecated in favour of using 'not bool(filter)" + warnings.warn(msg, DeprecationWarning) return not bool(self.children) def __eq__(self, other): @@ -167,12 +176,15 @@ class Q(QNode): def __repr__(self): return "Q(**%s)" % repr(self.query) + def __bool__(self): + return bool(self.query) + + def __eq__(self, other): + return self.__class__ == other.__class__ and self.query == other.query + def accept(self, visitor): return visitor.visit_query(self) @property def empty(self): return not bool(self.query) - - def __eq__(self, other): - return self.__class__ == other.__class__ and self.query == other.query diff --git a/tests/queryset/test_visitor.py b/tests/queryset/test_visitor.py index afa00839..81e0f253 100644 --- a/tests/queryset/test_visitor.py +++ b/tests/queryset/test_visitor.py @@ -407,6 +407,17 @@ class TestQ(unittest.TestCase): def test_combine_or_both_empty(self): assert Q() | Q() == Q() + def test_q_bool(self): + assert Q(name="John") + assert not Q() + + def test_combine_bool(self): + assert not Q() & Q() + assert Q() & Q(name="John") + assert Q(name="John") & Q() + assert Q() | Q(name="John") + assert Q(name="John") | Q() + if __name__ == "__main__": unittest.main()