Started work on new Q-object implementation

This commit is contained in:
Harry Marr
2010-10-03 21:08:28 +01:00
parent 556eed0151
commit 62388cb740
2 changed files with 133 additions and 4 deletions

View File

@@ -15,6 +15,7 @@ REPR_OUTPUT_SIZE = 20
class DoesNotExist(Exception):
pass
class MultipleObjectsReturned(Exception):
pass
@@ -26,12 +27,123 @@ class InvalidQueryError(Exception):
class OperationError(Exception):
pass
class InvalidCollectionError(Exception):
pass
RE_TYPE = type(re.compile(''))
class QNodeVisitor(object):
def visit_combination(self, combination):
return combination
def visit_query(self, query):
return query
class SimplificationVisitor(QNodeVisitor):
def visit_combination(self, combination):
if combination.operation != combination.AND:
return combination
if any(not isinstance(node, NewQ) for node in combination.children):
return combination
query_ops = set()
query = {}
for node in combination.children:
ops = set(node.query.keys())
intersection = ops.intersection(query_ops)
if intersection:
msg = 'Duplicate query contitions: '
raise InvalidQueryError(msg + ', '.join(intersection))
query_ops.update(ops)
query.update(copy.deepcopy(node.query))
return NewQ(**query)
class QueryCompilerVisitor(QNodeVisitor):
def __init__(self, document):
self.document = document
def visit_combination(self, combination):
if combination.operation == combination.OR:
return combination
return combination
def visit_query(self, query):
return QuerySet._transform_query(self.document, **query.query)
class QNode(object):
AND = 0
OR = 1
def to_query(self, document):
query = self.accept(SimplificationVisitor())
query = query.accept(QueryCompilerVisitor(document))
return query
def accept(self, visitor):
raise NotImplementedError
def _combine(self, other, operation):
if other.empty:
return self
if self.empty:
return other
return QCombination(operation, [self, other])
@property
def empty(self):
return False
def __or__(self, other):
return self._combine(other, self.OR)
def __and__(self, other):
return self._combine(other, self.AND)
class QCombination(QNode):
def __init__(self, operation, children):
self.operation = operation
self.children = children
def accept(self, visitor):
for i in range(len(self.children)):
self.children[i] = self.children[i].accept(visitor)
return visitor.visit_combination(self)
@property
def empty(self):
return not bool(self.query)
class NewQ(QNode):
def __init__(self, **query):
self.query = query
def accept(self, visitor):
return visitor.visit_query(self)
@property
def empty(self):
return not bool(self.query)
class Q(object):
OR = '||'