2 and_, or_, inv, add, mul, sub, mod, truediv, lt, le, ne, gt, ge, eq, neg
4 from manifold.util.misc import contains
5 from types import StringTypes
7 # New modifier: { contains
34 def __init__(self, *args, **kwargs):
36 \brief Build a predicate (left, operator, right)
38 - three args (left, operator, right)
39 - one argument (list or tuple) containing three elements (variable, operator, value)
40 "operator" is a String defined in operators or in operators_short and refers
41 tMao a binary operation.
42 "left" and "right" refers to a variable/constant involved in the Predicate.
46 elif len(args) == 1 and isinstance(args[0], (tuple,list)) and len(args[0]) == 3:
47 key, op, value = args[0]
48 elif len(args) == 1 and isinstance(args[0], Predicate):
49 key, op, value = args[0].get_tuple()
51 raise Exception, "Bad initializer for Predicate"
53 if op in self.operators.keys():
54 self.op = self.operators[op]
55 elif op in self.operators_short.keys():
56 self.op = self.operators_short[op]
59 if isinstance(value, (list, set)):
60 self.value = tuple(value)
65 return "Pred(%s, %s, %s)" % self.get_str_tuple()
71 return hash(self.get_tuple())
74 return (self.key, self.op, self.value)
77 op_str = [s for s, op in self.operators.iteritems() if op == self.op]
80 def get_str_tuple(self):
81 return (self.key, self.get_str_op(), self.value,)
83 def match(self, dic, ignore_missing=False):
84 if isinstance(self.key, tuple):
85 print "PREDICATE MATCH", self.key
87 print "-----------------------------"
90 if self.key not in dic:
94 if isinstance(self.value, list):
95 return (dic[self.key] in self.value) # array ?
97 return (dic[self.key] == self.value)
99 if isinstance(self.value, list):
100 return (dic[self.key] not in self.value) # array ?
102 return (dic[self.key] != self.value) # array ?
104 if isinstance(self.value, StringTypes):
106 return dic[self.key].startswith('%s.' % self.value)
108 return (dic[self.key] < self.value)
110 if isinstance(self.value, StringTypes):
111 return dic[self.key] == self.value or dic[self.key].startswith('%s.' % self.value)
113 return (dic[self.key] <= self.value)
115 if isinstance(self.value, StringTypes):
117 return self.value.startswith('%s.' % dic[self.key])
119 return (dic[self.key] > self.value)
121 if isinstance(self.value, StringTypes):
123 return dic[self.key] == self.value or self.value.startswith('%s.' % dic[self.key])
125 return (dic[self.key] >= self.value)
126 elif self.op == and_:
127 return (dic[self.key] & self.value) # array ?
129 return (dic[self.key] | self.value) # array ?
130 elif self.op == contains:
131 method, subfield = self.key.split('.', 1)
132 return not not [ x for x in dic[method] if x[subfield] == self.value]
134 raise Exception, "Unexpected table format: %r", dic
136 def filter(self, dic):
138 Filter dic according to the current predicate.
143 method, subfield = self.key.split('.', 1)
144 if not method in dic:
147 if isinstance(dic[method], dict):
148 # We have a 1..1 relationship: apply the same filter to the dict
149 subpred = Predicate(subfield, self.op, self.value)
150 match = subpred.match(dic[method])
151 return dic if match else None
153 elif isinstance(dic[method], (list, tuple)):
156 if self.op == contains:
157 return dic if self.match(dic) else None
159 subpred = Predicate(subfield, self.op, self.value)
160 dic[method] = subpred.filter(dic[method])
163 raise Exception, "Unexpected table format: %r", dic
167 # Individual field operations: this could be simplified, since we are now using operators_short !!
169 print "current predicate", self
170 print "matching", dic
172 return dic if self.match(dic) else None