diff -r 6641e941ef1e -r ff1a9aa48cfd app/django/utils/tree.py --- a/app/django/utils/tree.py Tue Oct 14 12:36:55 2008 +0000 +++ b/app/django/utils/tree.py Tue Oct 14 16:00:59 2008 +0000 @@ -29,6 +29,22 @@ self.subtree_parents = [] self.negated = negated + # We need this because of django.db.models.query_utils.Q. Q. __init__() is + # problematic, but it is a natural Node subclass in all other respects. + def _new_instance(cls, children=None, connector=None, negated=False): + """ + This is called to create a new instance of this class when we need new + Nodes (or subclasses) in the internal code in this class. Normally, it + just shadows __init__(). However, subclasses with an __init__ signature + that is not an extension of Node.__init__ might need to implement this + method to allow a Node to create a new instance of them (if they have + any extra setting up to do). + """ + obj = Node(children, connector, negated) + obj.__class__ = cls + return obj + _new_instance = classmethod(_new_instance) + def __str__(self): if self.negated: return '(NOT (%s: %s))' % (self.connector, ', '.join([str(c) for c @@ -71,7 +87,7 @@ Otherwise, the whole tree is pushed down one level and a new root connector is created, connecting the existing tree and the new node. """ - if node in self.children: + if node in self.children and conn_type == self.connector: return if len(self.children) < 2: self.connector = conn_type @@ -82,7 +98,8 @@ else: self.children.append(node) else: - obj = Node(self.children, self.connector, self.negated) + obj = self._new_instance(self.children, self.connector, + self.negated) self.connector = conn_type self.children = [obj, node] @@ -96,7 +113,8 @@ Interpreting the meaning of this negate is up to client code. This method is useful for implementing "not" arrangements. """ - self.children = [Node(self.children, self.connector, not self.negated)] + self.children = [self._new_instance(self.children, self.connector, + not self.negated)] self.connector = self.default def start_subtree(self, conn_type): @@ -108,12 +126,13 @@ if len(self.children) == 1: self.connector = conn_type elif self.connector != conn_type: - self.children = [Node(self.children, self.connector, self.negated)] + self.children = [self._new_instance(self.children, self.connector, + self.negated)] self.connector = conn_type self.negated = False - self.subtree_parents.append(Node(self.children, self.connector, - self.negated)) + self.subtree_parents.append(self.__class__(self.children, + self.connector, self.negated)) self.connector = self.default self.negated = False self.children = [] @@ -126,7 +145,7 @@ the current instances state to be the parent. """ obj = self.subtree_parents.pop() - node = Node(self.children, self.connector) + node = self.__class__(self.children, self.connector) self.connector = obj.connector self.negated = obj.negated self.children = obj.children