示例#1
0
 def __init__(self, *args, **kwargs):
     """
     An object just responsible for Keeping
     overlord queries and doing some serialization
     stuff if any ...
     """
     #some initialization stuff here ...
     fact_query = None
     if kwargs.has_key('fact_query'):
         fact_query = kwargs['fact_query']
     self.fact_query = fact_query or FuncLogicQuery()
示例#2
0
    def deserialize(self, q_list):
        """
        Method gets the lists that is sent from overlord (pure string or list)
        and converts into a FuncLogicQuery so facts can be pulled from prewritten
        modules...

        @type  q_list : list
        @param q_list : Query list 
        """
        q_result = self.__traverse_deserialize(q_list)
        if not self.fact_query:
            self.fact_query = FuncLogicQuery(q_result, self.pull_facts)
        else:
            if self.fact_query.q.connector == "OR":
                self.fact_query = self.fact_query | FuncLogicQuery(
                    q_result, self.pull_facts)
            else:
                self.fact_query = self.fact_query & FuncLogicQuery(
                    q_result, self.pull_facts)

        return q_result
示例#3
0
    def deserialize(self,q_list):
        """
        Method gets the lists that is sent from overlord (pure string or list)
        and converts into a FuncLogicQuery so facts can be pulled from prewritten
        modules...

        @type  q_list : list
        @param q_list : Query list
        """
        q_result = self.__traverse_deserialize(q_list)
        if not self.fact_query:
            self.fact_query = FuncLogicQuery(q_result,self.pull_facts)
        else:
            if self.fact_query.q.connector == "OR":
                self.fact_query = self.fact_query | FuncLogicQuery(q_result,self.pull_facts)
            else:
                self.fact_query = self.fact_query & FuncLogicQuery(q_result,self.pull_facts)

        return q_result
示例#4
0
class FactsMinion(object):
    """
    That class wil be responsible for:
        1. De-serialization of the query by converting
        it to a Q structure.
        
        2. Calling the ( prewritten ) 'facts' modules
    """
    VALID_QUERY_KEYS = ["AND", "OR", "NOT"]

    def __init__(self, fact_query=None, method_fact_list=None):
        """
        Constructor 

        @type  fact_query : FuncLogicQuery
        @param fact_query : FuncLogicQuery that will be produced from that class if
                            not given from constructor as it is here.
        @type  method_fact_list : list
        @param method_fact_list : List of prewritten 'facts' modules you can
                                  find them under facts/modules directory

        @return : None
        """
        self.fact_query = fact_query
        self.keyword_query = QueryKeyword()
        self.method_fact_list = method_fact_list

    def deserialize(self, q_list):
        """
        Method gets the lists that is sent from overlord (pure string or list)
        and converts into a FuncLogicQuery so facts can be pulled from prewritten
        modules...

        @type  q_list : list
        @param q_list : Query list 
        """
        q_result = self.__traverse_deserialize(q_list)
        if not self.fact_query:
            self.fact_query = FuncLogicQuery(q_result, self.pull_facts)
        else:
            if self.fact_query.q.connector == "OR":
                self.fact_query = self.fact_query | FuncLogicQuery(
                    q_result, self.pull_facts)
            else:
                self.fact_query = self.fact_query & FuncLogicQuery(
                    q_result, self.pull_facts)

        return q_result

    def exec_query(self, q_list, include_results=False):
        """
        The magic method which gives the final result of that
        query with values in it if requested. That is why we
        have include_results sometimes.

        @type  q_list : list
        @param q_list : Query list
        @type  include_results : boolean
        @param include_results : As it is known the main purpose 
                                 of facts is to return True or False
                                 but sometimes we need the real result
                                 also included.


        """
        self.deserialize(q_list)
        if not include_results:
            return self.fact_query.result
        else:
            return self.fact_query.exec_query_with_facts()

    def pull_facts(self, overlord_tuple):
        """
        Pull facts is kind of callback method which
        is called by FuncLogicQuery when does the logic
        query operation in its recursive traversing ...
        That way we dont put all the pulling operations in
        FuncLogicQuery but making it pluggable by calling from
        outside. That is the place where we actually call the 'fact'
        modules. If you need change in calling fact methods that is
        the place to go .

        @type  overlord_tuple : Tuple 
        @param overlord_tuple : A tuple in format of (factname__factoperation,compared_value)
        """
        keyword_tuple = overlord_tuple[0].split("__")
        overlord_value = overlord_tuple[1]

        if len(keyword_tuple) > 1:
            keyword = keyword_tuple[1]
        else:
            keyword = ""
        fact_name = keyword_tuple[0]

        if not self.method_fact_list.has_key(fact_name):
            raise MinionQueryError(
                "None existing Fact method or tag required %s " % fact_name)

        fact_value = self.method_fact_list[fact_name]()

        #we have the result with fact now it is time to resolve it
        logic_fact = self.keyword_query.resolve(keyword, overlord_value,
                                                fact_value)

        #the return part is a tuple (logic_Value which is True or False and fact_name and value dictionary )
        return (logic_fact, {fact_name: fact_value})

    def __traverse_deserialize(self, traverse_object):
        """
        The private recursive part that traverses
        the incoming overlord list (included with facts)
        and produces a Q object query object from it.
        **(heavy recursive code)Caution any change here 
        can make facts not tobe deserialized correctly so
        that will break the facts API.

        @type  : list
        @param : List of overlord incoming facts query
                 something like :[NOT,[AND,[a,TRUE,b,FALSE]]]
 
        @return : Q object returned
        """

        q_object = None
        #lets try divide and conquer :)
        #assume that it is [NOT,[AND,[a,TRUE,b,FALSE]]]

        #print "The traverse object at start is ",traverse_object
        tmp_negated = False
        tmp_connector = "AND"
        if type(traverse_object[0]) == str and traverse_object[0] == "NOT":
            tmp_negated = True
            #q_object.negated = ~q_object
            traverse_object = traverse_object[1:][0]
            #print "After NOT the traverse_object is ",traverse_object
            #raw_input()
        if type(traverse_object[0]) == str and traverse_object[0] in [
                "AND", "OR"
        ]:
            #q_object.connector = traverse_object[0]
            tmp_connector = traverse_object[0]
            traverse_object = traverse_object[1:][0]
            #print "After CONNETOR the traverse_object is ",traverse_object
            #raw_input()

        if type(traverse_object[0]
                ) == str and not traverse_object[0] in self.VALID_QUERY_KEYS:
            #print "In children : ",traverse_object
            for ch in xrange(0, len(traverse_object), 2):
                #q_object.add(Q(tuple(traverse_object[ch:ch+2])),q_object.connector)
                #print "We work on ",traverse_object[ch:ch+2]
                if not q_object:
                    q_object = Q(tuple(traverse_object[ch:ch + 2]))
                    q_object.connector = tmp_connector
                else:
                    if q_object.connector == "OR":
                        q_object = q_object | Q(
                            tuple(traverse_object[ch:ch + 2]))
                    else:
                        q_object = q_object & Q(
                            tuple(traverse_object[ch:ch + 2]))
            if tmp_negated:
                q_object = ~q_object

                #print "IN children Q object is ",q_object
            traverse_object = []
            #print "After CHILDREN the traverse_object is ",traverse_object
            #raw_input()

        if traverse_object:

            #print "The traverse object at end is ",traverse_object
            #raw_input()
            for t_o in traverse_object:
                #print "The traverse object at end is ",t_o
                #raw_input()

                tmp_q = self.__traverse_deserialize(t_o)
                #print "I ADD THAT TO THE ALL ",tmp_q
                #print "WILL BE ADDED TO  ",q_object
                if not q_object:
                    q_object = Q()
                    q_object.connector = tmp_connector
                #q_object.add(tmp_q,q_object.connector)
                if tmp_connector == "OR":
                    q_object = q_object | tmp_q
                else:
                    q_object = q_object & tmp_q
                    #print "AFTER ADDITION ",q_object
            if tmp_negated:
                q_object = ~q_object

        return q_object
示例#5
0
class FactsMinion(object):
    """
    That class wil be responsible for:
        1. De-serialization of the query by converting
        it to a Q structure.

        2. Calling the ( prewritten ) 'facts' modules
    """
    VALID_QUERY_KEYS = ["AND","OR","NOT"]

    def __init__(self,fact_query=None,method_fact_list=None):
        """
        Constructor

        @type  fact_query : FuncLogicQuery
        @param fact_query : FuncLogicQuery that will be produced from that class if
                            not given from constructor as it is here.
        @type  method_fact_list : list
        @param method_fact_list : List of prewritten 'facts' modules you can
                                  find them under facts/modules directory

        @return : None
        """
        self.fact_query = fact_query
        self.keyword_query = QueryKeyword()
        self.method_fact_list = method_fact_list

    def deserialize(self,q_list):
        """
        Method gets the lists that is sent from overlord (pure string or list)
        and converts into a FuncLogicQuery so facts can be pulled from prewritten
        modules...

        @type  q_list : list
        @param q_list : Query list
        """
        q_result = self.__traverse_deserialize(q_list)
        if not self.fact_query:
            self.fact_query = FuncLogicQuery(q_result,self.pull_facts)
        else:
            if self.fact_query.q.connector == "OR":
                self.fact_query = self.fact_query | FuncLogicQuery(q_result,self.pull_facts)
            else:
                self.fact_query = self.fact_query & FuncLogicQuery(q_result,self.pull_facts)

        return q_result

    def exec_query(self,q_list,include_results=False):
        """
        The magic method which gives the final result of that
        query with values in it if requested. That is why we
        have include_results sometimes.

        @type  q_list : list
        @param q_list : Query list
        @type  include_results : boolean
        @param include_results : As it is known the main purpose
                                 of facts is to return True or False
                                 but sometimes we need the real result
                                 also included.


        """
        self.deserialize(q_list)
        if not include_results:
            return self.fact_query.result
        else:
            return self.fact_query.exec_query_with_facts()

    def pull_facts(self,overlord_tuple):
        """
        Pull facts is kind of callback method which
        is called by FuncLogicQuery when does the logic
        query operation in its recursive traversing ...
        That way we dont put all the pulling operations in
        FuncLogicQuery but making it pluggable by calling from
        outside. That is the place where we actually call the 'fact'
        modules. If you need change in calling fact methods that is
        the place to go .

        @type  overlord_tuple : Tuple
        @param overlord_tuple : A tuple in format of (factname__factoperation,compared_value)
        """
        keyword_tuple = overlord_tuple[0].split("__")
        overlord_value = overlord_tuple[1]

        if len(keyword_tuple) > 1:
            keyword = keyword_tuple[1]
        else:
            keyword = ""
        fact_name = keyword_tuple[0]

        if not self.method_fact_list.has_key(fact_name):
            raise MinionQueryError("None existing Fact method or tag required %s "%fact_name)

        fact_value = self.method_fact_list[fact_name]()

        #we have the result with fact now it is time to resolve it
        logic_fact = self.keyword_query.resolve(keyword,overlord_value,fact_value)

        #the return part is a tuple (logic_Value which is True or False and fact_name and value dictionary )
        return (logic_fact,{fact_name:fact_value})

    def __traverse_deserialize(self,traverse_object):
        """
        The private recursive part that traverses
        the incoming overlord list (included with facts)
        and produces a Q object query object from it.
        **(heavy recursive code)Caution any change here
        can make facts not tobe deserialized correctly so
        that will break the facts API.

        @type  : list
        @param : List of overlord incoming facts query
                 something like :[NOT,[AND,[a,TRUE,b,FALSE]]]

        @return : Q object returned
        """

        q_object = None
        #lets try divide and conquer :)
        #assume that it is [NOT,[AND,[a,TRUE,b,FALSE]]]

        #print "The traverse object at start is ",traverse_object
        tmp_negated = False
        tmp_connector ="AND"
        if type(traverse_object[0]) == str and  traverse_object[0] == "NOT":
            tmp_negated = True
            #q_object.negated = ~q_object
            traverse_object = traverse_object[1:][0]
            #print "After NOT the traverse_object is ",traverse_object
            #raw_input()
        if type(traverse_object[0]) == str and traverse_object[0] in ["AND","OR"]:
            #q_object.connector = traverse_object[0]
            tmp_connector = traverse_object[0]
            traverse_object = traverse_object[1:][0]
            #print "After CONNETOR the traverse_object is ",traverse_object
            #raw_input()

        if type(traverse_object[0])==str and not traverse_object[0] in self.VALID_QUERY_KEYS:
            #print "In children : ",traverse_object
            for ch in xrange(0,len(traverse_object),2):
                #q_object.add(Q(tuple(traverse_object[ch:ch+2])),q_object.connector)
                #print "We work on ",traverse_object[ch:ch+2]
                if not q_object:
                    q_object = Q(tuple(traverse_object[ch:ch+2]))
                    q_object.connector = tmp_connector
                else:
                    if q_object.connector == "OR":
                        q_object = q_object | Q(tuple(traverse_object[ch:ch+2]))
                    else:
                        q_object = q_object & Q(tuple(traverse_object[ch:ch+2]))
            if tmp_negated:
                q_object =  ~q_object


                #print "IN children Q object is ",q_object
            traverse_object = []
            #print "After CHILDREN the traverse_object is ",traverse_object
            #raw_input()

        if traverse_object:

            #print "The traverse object at end is ",traverse_object
            #raw_input()
            for t_o in traverse_object:
                #print "The traverse object at end is ",t_o
                #raw_input()

                tmp_q = self.__traverse_deserialize(t_o)
                #print "I ADD THAT TO THE ALL ",tmp_q
                #print "WILL BE ADDED TO  ",q_object
                if not q_object:
                    q_object = Q()
                    q_object.connector = tmp_connector
                #q_object.add(tmp_q,q_object.connector)
                if tmp_connector== "OR":
                    q_object = q_object | tmp_q
                else:
                    q_object = q_object & tmp_q
                    #print "AFTER ADDITION ",q_object
            if tmp_negated:
                q_object = ~q_object

        return q_object
示例#6
0
 def setUp(self):
     self.q1 = FuncLogicQuery(Q(a=True, b=True))
     self.q2 = FuncLogicQuery(Q(a=False, b=True))
     self.q3 = FuncLogicQuery(Q(a=True, b=False))
     self.q4 = FuncLogicQuery(Q(a=False, b=False))
     self.q_negated = FuncLogicQuery(~Q(a=False, b=False))
示例#7
0
class TestFactsTree(object):
    def setUp(self):
        self.q1 = FuncLogicQuery(Q(a=True, b=True))
        self.q2 = FuncLogicQuery(Q(a=False, b=True))
        self.q3 = FuncLogicQuery(Q(a=True, b=False))
        self.q4 = FuncLogicQuery(Q(a=False, b=False))
        self.q_negated = FuncLogicQuery(~Q(a=False, b=False))

    def test_print_facts_tree(self):
        """
        You will see those only with -s option of
        nosetests
        """
        #print q.children
        #print q
        print self.q1
        print self.q2
        print self.q3
        print self.q4
        print self.q_negated

    def test_traverse_logic_tree(self):

        assert self.q1.result == True
        assert self.q2.result == False
        assert self.q3.result == False
        assert self.q4.result == False
        assert self.q_negated.result == True

        q1_q2_or = self.q3 | self.q1
        q1_q2_and = self.q1 & self.q2

        assert q1_q2_or.result == True
        assert q1_q2_and.result == False

        tmp = q1_q2_or | q1_q2_and
        tmp2 = q1_q2_or & q1_q2_and

        assert tmp.result == True
        assert tmp2.result == False

        #lets do sth more more complex :)
        very_tmp = tmp & tmp
        very_tmp2 = tmp2 | tmp2 & tmp
        assert very_tmp.result == True
        assert very_tmp2.result == False

    def test_filter(self):
        """
        Do some testing on filtering the stuff
        """

        tmp_q = self.q1.filter(c=False, e=True)
        assert tmp_q.result == False

        tmp_q = self.q1.filter(c=True, e=True)
        assert tmp_q.result == True

        tmp_q = self.q2.filter(c=False, e=True)
        assert tmp_q.result == False

        tmp_q = self.q3.filter(c=False, e=True)
        assert tmp_q.result == False

        tmp_q = self.q4.filter(c=False, e=True)
        assert tmp_q.result == False

    def test_exclude(self):
        """
        Test the negated situations
        """
        tmp_q = self.q1.exclude(c=False, e=True)
        assert tmp_q.result == True

    def test_complex(self):
        """
        The complex thing
        """

        #what it does is creates a Q on the
        #fly and ORs it with set_compexq

        tmp_q = self.q1.set_compexq((Q(a=True, b=True) | Q(c=False, d=True)),
                                    "OR")
        assert tmp_q.result == True

        tmp_q = self.q1.set_compexq((Q(a=True, b=False) | Q(c=False, d=False)),
                                    "AND")
        assert tmp_q.result == False
示例#8
0
 def setUp(self):
     self.q1 = FuncLogicQuery(Q(a=True,b=True))
     self.q2 = FuncLogicQuery(Q(a=False,b=True))
     self.q3 = FuncLogicQuery(Q(a=True,b=False))
     self.q4 = FuncLogicQuery(Q(a=False,b=False))
     self.q_negated = FuncLogicQuery(~Q(a=False,b=False))
示例#9
0
class TestFactsTree(object):

    def setUp(self):
        self.q1 = FuncLogicQuery(Q(a=True,b=True))
        self.q2 = FuncLogicQuery(Q(a=False,b=True))
        self.q3 = FuncLogicQuery(Q(a=True,b=False))
        self.q4 = FuncLogicQuery(Q(a=False,b=False))
        self.q_negated = FuncLogicQuery(~Q(a=False,b=False))

    def test_print_facts_tree(self):
        """
        You will see those only with -s option of
        nosetests
        """
        #print q.children
        #print q
        print self.q1
        print self.q2
        print self.q3
        print self.q4
        print self.q_negated



    def test_traverse_logic_tree(self):

        assert self.q1.result == True
        assert self.q2.result == False
        assert self.q3.result == False
        assert self.q4.result == False
        assert self.q_negated.result == True

        q1_q2_or = self.q3 | self.q1
        q1_q2_and = self.q1 & self.q2

        assert q1_q2_or.result == True
        assert q1_q2_and.result == False

        tmp = q1_q2_or | q1_q2_and
        tmp2 = q1_q2_or & q1_q2_and

        assert tmp.result == True
        assert tmp2.result == False

        #lets do sth more more complex :)
        very_tmp = tmp & tmp
        very_tmp2 = tmp2 | tmp2 & tmp
        assert very_tmp.result == True
        assert very_tmp2.result == False

    def test_filter(self):
        """
        Do some testing on filtering the stuff
        """

        tmp_q = self.q1.filter(c=False,e=True)
        assert tmp_q.result == False

        tmp_q = self.q1.filter(c=True,e=True)
        assert tmp_q.result == True


        tmp_q=self.q2.filter(c=False,e=True)
        assert tmp_q.result == False


        tmp_q=self.q3.filter(c=False,e=True)
        assert tmp_q.result == False


        tmp_q=self.q4.filter(c=False,e=True)
        assert tmp_q.result == False


    def test_exclude(self):
        """
        Test the negated situations
        """
        tmp_q = self.q1.exclude(c=False,e=True)
        assert tmp_q.result == True

    def test_complex(self):
        """
        The complex thing
        """

        #what it does is creates a Q on the
        #fly and ORs it with set_compexq

        tmp_q=self.q1.set_compexq(
                (Q(a=True,b=True)|
                Q(c=False,d=True)),
                "OR"
                )
        assert tmp_q.result == True

        tmp_q=self.q1.set_compexq(
                (Q(a=True,b=False)|
                Q(c=False,d=False)),
                "AND"
                )
        assert tmp_q.result == False