plugins: reworked the framework using inheritance + added active_filters
[myslice.git] / manifold / util / predicate.py
index c9e2856..aa09379 100644 (file)
@@ -1,34 +1,41 @@
+from types import StringTypes
+
 from operator import (
     and_, or_, inv, add, mul, sub, mod, truediv, lt, le, ne, gt, ge, eq, neg
     )
-from manifold.util.misc import contains
-from types import StringTypes
+
+# Define the inclusion operators
+class contains(type): pass
+class included(type): pass
+
 
 # New modifier: { contains 
 class Predicate:
 
     operators = {
-        "=="       : eq,
-        "!="       : ne,
-        "<"        : lt,
-        "<="       : le,
-        ">"        : gt,
-        ">="       : ge,
-        "&&"       : and_,
-        "||"       : or_,
-        "contains" : contains
+        '=='       : eq,
+        '!='       : ne,
+        '<'        : lt,
+        '<='       : le,
+        '>'        : gt,
+        '>='       : ge,
+        '&&'       : and_,
+        '||'       : or_,
+        'CONTAINS' : contains,
+        'INCLUDED' : included
     }
 
     operators_short = {
-        "=" : eq,
-        "~" : ne,
-        "<" : lt,
-        "[" : le,
-        ">" : gt,
-        "]" : ge,
-        "&" : and_,
-        "|" : or_,
-        "}" : contains
+        '=' : eq,
+        '~' : ne,
+        '<' : lt,
+        '[' : le,
+        '>' : gt,
+        ']' : ge,
+        '&' : and_,
+        '|' : or_,
+        '}' : contains,
+        '{' : included
     }
 
     def __init__(self, *args, **kwargs):
@@ -48,28 +55,60 @@ class Predicate:
         elif len(args) == 1 and isinstance(args[0], Predicate):
             key, op, value = args[0].get_tuple()
         else:
-            raise Exception, "Bad initializer for Predicate"
+            raise Exception, "Bad initializer for Predicate (args=%r)" % args
+
+        assert not isinstance(value, (frozenset, dict, set)), "Invalid value type (the only valid containers are tuples and lists) (type = %r)" % type(value)
+        if isinstance(value, list):
+            value = tuple(value)
+
         self.key = key
+        if isinstance(op, StringTypes):
+            op = op.upper()
         if op in self.operators.keys():
             self.op = self.operators[op]
         elif op in self.operators_short.keys():
             self.op = self.operators_short[op]
         else:
             self.op = op
-        if isinstance(value, (list, set)):
+
+        if isinstance(value, list):
             self.value = tuple(value)
         else:
             self.value = value
 
     def __str__(self):
-        return "Pred(%s, %s, %s)" % self.get_str_tuple()
+        key, op, value = self.get_str_tuple()
+        if isinstance(value, (tuple, list, set, frozenset)):
+            value = [repr(v) for v in value]
+            value = "[%s]" % ", ".join(value)
+        return "%s %s %r" % (key, op, value) 
 
     def __repr__(self):
-        return self.__str__() 
+        return "Predicate<%s %s %r>" % self.get_str_tuple()
 
     def __hash__(self):
         return hash(self.get_tuple())
 
+    def __eq__(self, predicate):
+        if not predicate:
+            return False
+        return self.get_tuple() == predicate.get_tuple()
+
+    def get_key(self):
+        return self.key
+    
+    def set_key(self, key):
+        self.key = key
+
+    def get_op(self):
+        return self.op
+
+    def get_value(self):
+        return self.value
+
+    def set_value(self, value):
+        self.value = value
+
     def get_tuple(self):
         return (self.key, self.op, self.value)
 
@@ -130,8 +169,10 @@ class Predicate:
         elif self.op == contains:
             method, subfield = self.key.split('.', 1)
             return not not [ x for x in dic[method] if x[subfield] == self.value] 
+        elif self.op == included:
+            return dic[self.key] in self.value
         else:
-            raise Exception, "Unexpected table format: %r", dic
+            raise Exception, "Unexpected table format: %r" % dic
 
     def filter(self, dic):
         """
@@ -171,3 +212,14 @@ class Predicate:
             print "----"
             return dic if self.match(dic) else None
 
+    def get_field_names(self):
+        if isinstance(self.key, (list, tuple, set, frozenset)):
+            return set(self.key)
+        else:
+            return set([self.key])
+
+    def get_value_names(self):
+        if isinstance(self.value, (list, tuple, set, frozenset)):
+            return set(self.value)
+        else:
+            return set([self.value])