From 0458ef869eb07d98c2ebb4da82dc3ca0bcd94a49 Mon Sep 17 00:00:00 2001 From: Filip Kucharczyk Date: Tue, 3 Dec 2019 00:42:10 +0100 Subject: [PATCH] Add __eq__ to Q and Q operations --- mongoengine/queryset/visitor.py | 12 ++++++++++++ tests/queryset/test_visitor.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/mongoengine/queryset/visitor.py b/mongoengine/queryset/visitor.py index 0fe139fd..058c722a 100644 --- a/mongoengine/queryset/visitor.py +++ b/mongoengine/queryset/visitor.py @@ -96,9 +96,11 @@ class QNode(object): """Combine this node with another node into a QCombination object. """ + # If the other Q() is empty, ignore it and just use `self`. if getattr(other, "empty", True): return self + # Or if this Q is empty, ignore it and just use `other`. if self.empty: return other @@ -146,6 +148,13 @@ class QCombination(QNode): def empty(self): return not bool(self.children) + def __eq__(self, other): + return ( + self.__class__ == other.__class__ + and self.operation == other.operation + and self.children == other.children + ) + class Q(QNode): """A simple query object, used in a query tree to build up more complex @@ -164,3 +173,6 @@ class Q(QNode): @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 e597e3d8..e8504abd 100644 --- a/tests/queryset/test_visitor.py +++ b/tests/queryset/test_visitor.py @@ -374,6 +374,38 @@ class TestQ(unittest.TestCase): == 2 ) + def test_equality(self): + assert Q(name="John") == Q(name="John") + assert Q() == Q() + + def test_inequality(self): + assert Q(name="John") != Q(name="Ralph") + + def test_operation_equality(self): + q1 = Q(name="John") | Q(title="Sir") & Q(surname="Paul") + q2 = Q(name="John") | Q(title="Sir") & Q(surname="Paul") + assert q1 == q2 + + def test_operation_inequality(self): + q1 = Q(name="John") | Q(title="Sir") + q2 = Q(title="Sir") | Q(name="John") + assert q1 != q2 + + def test_combine_and_empty(self): + q = Q(x=1) + assert q & Q() == q + assert Q() & q == q + + def test_combine_and_both_empty(self): + assert Q() & Q() == Q() + + def test_combine_or_empty(self): + q = Q(x=1) + assert q | Q() == q + assert Q() | q == q + + def test_combine_or_both_empty(self): + assert Q() | Q() == Q() if __name__ == "__main__": unittest.main()