mirror of
https://github.com/django/django.git
synced 2025-01-15 04:45:51 +00:00
ddf0002bb7
Node._new_instance() was added in 6dd2b5468fa275d53aa60fdcaff8c28bdc5e9c25 to work around Q.__init__() having an incompatible signature with Node.__init__(). It was intended as a hook that could be overridden if subclasses needed to change the behaviour of instantiation of their specialised form of Node. In practice this doesn't ever seem to have been used for this purpose and there are very few calls to Node._new_instance() with other code, e.g. Node.__deepcopy__() calling Node and overriding __class__ as required. Rename this to Node.create() to make it a more "official" piece of private API that we can use to simplify a lot of other areas internally. The docstring and nearby comment have been reworded to read more clearly.
127 lines
4.7 KiB
Python
127 lines
4.7 KiB
Python
import copy
|
|
import unittest
|
|
|
|
from django.db.models.sql import AND, OR
|
|
from django.utils.tree import Node
|
|
|
|
|
|
class NodeTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.node1_children = [("a", 1), ("b", 2)]
|
|
self.node1 = Node(self.node1_children)
|
|
self.node2 = Node()
|
|
|
|
def test_str(self):
|
|
self.assertEqual(str(self.node1), "(DEFAULT: ('a', 1), ('b', 2))")
|
|
self.assertEqual(str(self.node2), "(DEFAULT: )")
|
|
|
|
def test_repr(self):
|
|
self.assertEqual(repr(self.node1), "<Node: (DEFAULT: ('a', 1), ('b', 2))>")
|
|
self.assertEqual(repr(self.node2), "<Node: (DEFAULT: )>")
|
|
|
|
def test_hash(self):
|
|
node3 = Node(self.node1_children, negated=True)
|
|
node4 = Node(self.node1_children, connector="OTHER")
|
|
node5 = Node(self.node1_children)
|
|
node6 = Node([["a", 1], ["b", 2]])
|
|
node7 = Node([("a", [1, 2])])
|
|
node8 = Node([("a", (1, 2))])
|
|
self.assertNotEqual(hash(self.node1), hash(self.node2))
|
|
self.assertNotEqual(hash(self.node1), hash(node3))
|
|
self.assertNotEqual(hash(self.node1), hash(node4))
|
|
self.assertEqual(hash(self.node1), hash(node5))
|
|
self.assertEqual(hash(self.node1), hash(node6))
|
|
self.assertEqual(hash(self.node2), hash(Node()))
|
|
self.assertEqual(hash(node7), hash(node8))
|
|
|
|
def test_len(self):
|
|
self.assertEqual(len(self.node1), 2)
|
|
self.assertEqual(len(self.node2), 0)
|
|
|
|
def test_bool(self):
|
|
self.assertTrue(self.node1)
|
|
self.assertFalse(self.node2)
|
|
|
|
def test_contains(self):
|
|
self.assertIn(("a", 1), self.node1)
|
|
self.assertNotIn(("a", 1), self.node2)
|
|
|
|
def test_add(self):
|
|
# start with the same children of node1 then add an item
|
|
node3 = Node(self.node1_children)
|
|
node3_added_child = ("c", 3)
|
|
# add() returns the added data
|
|
self.assertEqual(node3.add(node3_added_child, Node.default), node3_added_child)
|
|
# we added exactly one item, len() should reflect that
|
|
self.assertEqual(len(self.node1) + 1, len(node3))
|
|
self.assertEqual(str(node3), "(DEFAULT: ('a', 1), ('b', 2), ('c', 3))")
|
|
|
|
def test_add_eq_child_mixed_connector(self):
|
|
node = Node(["a", "b"], OR)
|
|
self.assertEqual(node.add("a", AND), "a")
|
|
self.assertEqual(node, Node([Node(["a", "b"], OR), "a"], AND))
|
|
|
|
def test_negate(self):
|
|
# negated is False by default
|
|
self.assertFalse(self.node1.negated)
|
|
self.node1.negate()
|
|
self.assertTrue(self.node1.negated)
|
|
self.node1.negate()
|
|
self.assertFalse(self.node1.negated)
|
|
|
|
def test_create(self):
|
|
SubNode = type("SubNode", (Node,), {})
|
|
|
|
a = SubNode([SubNode(["a", "b"], OR), "c"], AND)
|
|
b = SubNode.create(a.children, a.connector, a.negated)
|
|
self.assertEqual(a, b)
|
|
# Children lists are the same object, but equal.
|
|
self.assertIsNot(a.children, b.children)
|
|
self.assertEqual(a.children, b.children)
|
|
# Child Node objects are the same objects.
|
|
for a_child, b_child in zip(a.children, b.children):
|
|
if isinstance(a_child, Node):
|
|
self.assertIs(a_child, b_child)
|
|
self.assertEqual(a_child, b_child)
|
|
|
|
def test_copy(self):
|
|
a = Node([Node(["a", "b"], OR), "c"], AND)
|
|
b = copy.copy(a)
|
|
self.assertEqual(a, b)
|
|
# Children lists are the same object.
|
|
self.assertIs(a.children, b.children)
|
|
# Child Node objects are the same objects.
|
|
for a_child, b_child in zip(a.children, b.children):
|
|
if isinstance(a_child, Node):
|
|
self.assertIs(a_child, b_child)
|
|
self.assertEqual(a_child, b_child)
|
|
|
|
def test_deepcopy(self):
|
|
a = Node([Node(["a", "b"], OR), "c"], AND)
|
|
b = copy.deepcopy(a)
|
|
self.assertEqual(a, b)
|
|
# Children lists are not be the same object, but equal.
|
|
self.assertIsNot(a.children, b.children)
|
|
self.assertEqual(a.children, b.children)
|
|
# Child Node objects are not be the same objects.
|
|
for a_child, b_child in zip(a.children, b.children):
|
|
if isinstance(a_child, Node):
|
|
self.assertIsNot(a_child, b_child)
|
|
self.assertEqual(a_child, b_child)
|
|
|
|
def test_eq_children(self):
|
|
node = Node(self.node1_children)
|
|
self.assertEqual(node, self.node1)
|
|
self.assertNotEqual(node, self.node2)
|
|
|
|
def test_eq_connector(self):
|
|
new_node = Node(connector="NEW")
|
|
default_node = Node(connector="DEFAULT")
|
|
self.assertEqual(default_node, self.node2)
|
|
self.assertNotEqual(default_node, new_node)
|
|
|
|
def test_eq_negated(self):
|
|
node = Node(negated=False)
|
|
negated = Node(negated=True)
|
|
self.assertNotEqual(negated, node)
|