예제 #1
0
    def __init__(self, builder=None, slave_limit=-1, debug=False):
        '''
        This Pengine object is used to run one or more queries of the
        Prolog Knowledge base set in the PengineBuilder.  builder::None ||
        PengineBuilder  Uses a new PengineBuilder with default settings,
        otherwise use the supplied PengineBuilder initialized with the
        desired settings.  A deepcopy is performed to preserve state.
        slave_limit::Int Sets limits on the number of slaves that this
        pengine can have.
        '''
        self.availOutput = None
        self.currentQuery = None
        self.state = State("not_created")

        # Initialize debug value, defaulting to False.
        self.debug = debug

        # Handle the builder logic.
        if builder is None:
            self.po = PengineBuilder()
        else:
            self.po = copy.deepcopy(builder)

        # self.create() gets pengineID
        self.slave_limit = slave_limit
        try:
            self.pengineID = self.create()
        except PengineNotReadyException:
            self.state.current_state = "destroy"
            raise PengineNotReadyException("Pengine could not be created!!")

        if self.debug:
            print("Initialization complete.")
        return None
예제 #2
0
    def test_member(self):
        """

        """
        q = "member(X,[1,2,3])"
        factory = PengineBuilder(urlserver="http://localhost:4242",
                                 destroy=False,
                                 ask=q)
        pengine = Pengine(builder=factory)
        results = pengine.currentQuery.availProofs
        print(results)
        self.assertTrue(len(results) == 3)
        self.assertTrue({'X': 1} in results)
        self.assertTrue({'X': 2} in results)
        self.assertTrue({'X': 3} in results)
예제 #3
0
    def query(self, q, select=None, endpoint=None):
        """
        Query a sparqlprog endpoint

        Returns:
        iterator
        """
        P = TermGenerator()
        opts = []
        if self.rules is not None:
            # force a tuple
            opts = [P.rule( (r,) ) for r in self.rules]
        opts_str = self.renderer.render(opts)
        if select is None:
            select = q
        if select is not str:
            select = self.renderer.render(select)
        if type(q) is not str:
            q = self.renderer.render(q)
        if endpoint is None:
            endpoint = self.endpoint
        if endpoint is not None:
            q = f"'??'({endpoint}, ({q}), ({select}), {opts_str})"
        logging.info(f"Query={q}")
        logging.info(f"Program={self.program}")
        builder = PengineBuilder(urlserver=self.server,
                                 destroy=False,
                                 srctext=self.program,
                                 ask=q)
        
        pengine = Pengine(builder=builder, debug=False)

        # note: may be rewritten after this is fixed and pushed to pypi:
        # https://github.com/ian-andrich/PythonPengines/issues/14
        if pengine.currentQuery is not None:
            for r in pengine.currentQuery.availProofs:
                yield self._translate(r)
            pengine.currentQuery.availProofs = [] # reset
        n=0
        while pengine.currentQuery is not None and pengine.currentQuery.hasMore:
            n += 1
            logging.info(f"Next chunk={n}")
            pengine.doNext(pengine.currentQuery)
            if pengine.currentQuery is not None:
                for r in pengine.currentQuery.availProofs:
                    yield self._translate(r)
                pengine.currentQuery.availProofs = [] # reset
예제 #4
0
def test_src():
    """
    
    """
    src = "foo(a).\nfoo(b).\nfoo(c)."
    q = "foo(X)"
    factory = PengineBuilder(urlserver="http://localhost:4242",
                             destroy=False,
                             srctext=src,
                             ask=q)
    pengine = Pengine(builder=factory, debug=True)
    results = pengine.currentQuery.availProofs
    print(results)
    assert len(results) == 3
    assert ({'X': 'a'} in results)
    assert ({'X': 'b'} in results)
    assert ({'X': 'c'} in results)
예제 #5
0
    def test_iterator(self):
        """

        """
        q = "member(X,[1,2,3,4,5,6,7,8,9,10])"
        chunk_sizes = [1, 2, 3, 4, 100]

        for chunk in chunk_sizes:
            factory = PengineBuilder(urlserver="http://localhost:4242",
                                     destroy=False,
                                     chunk=chunk,
                                     ask=q)
            pengine = Pengine(builder=factory)
            results = []
            for r in pengine.currentQuery:
                print('ITER={}'.format(r))
                results.append(r)

            self.assertTrue(len(results) == 10)
            self.assertTrue({'X': 1} in results)
            self.assertTrue({'X': 2} in results)
            self.assertTrue({'X': 3} in results)
예제 #6
0
    def test_chunk(self):
        """

        """
        src = "foo(a).\nfoo(b).\nfoo(c)."
        q = "foo(X)"
        factory = PengineBuilder(urlserver="http://localhost:4242",
                                 destroy=False,
                                 srctext=src,
                                 chunk=1,
                                 ask=q)
        pengine = Pengine(builder=factory)
        all_results = []
        results = pengine.currentQuery.availProofs
        print('INIT Results={}'.format(results))
        self.assertTrue(len(results) == 1)
        while pengine.currentQuery.hasMore:
            pengine.doNext(pengine.currentQuery)
            results = pengine.currentQuery.availProofs
            print('NEXT Results={}'.format(results))
        self.assertTrue({'X': 'a'} in results)
        self.assertTrue({'X': 'b'} in results)
        self.assertTrue({'X': 'c'} in results)
        self.assertEquals(len(results), 3)
예제 #7
0
class Pengine(object):
    def __init__(self, builder=None, slave_limit=-1, debug=False):
        '''
        This Pengine object is used to run one or more queries of the
        Prolog Knowledge base set in the PengineBuilder.  builder::None ||
        PengineBuilder  Uses a new PengineBuilder with default settings,
        otherwise use the supplied PengineBuilder initialized with the
        desired settings.  A deepcopy is performed to preserve state.
        slave_limit::Int Sets limits on the number of slaves that this
        pengine can have.
        '''
        self.availOutput = None
        self.currentQuery = None
        self.state = State("not_created")

        # Initialize debug value, defaulting to False.
        self.debug = debug

        # Handle the builder logic.
        if builder is None:
            self.po = PengineBuilder()
        else:
            self.po = copy.deepcopy(builder)

        # self.create() gets pengineID
        self.slave_limit = slave_limit
        try:
            self.pengineID = self.create()
        except PengineNotReadyException:
            self.state.current_state = "destroy"
            raise PengineNotReadyException("Pengine could not be created!!")

        if self.debug:
            print("Initialization complete.")
        return None

    def ask(self, query):
        '''
        Parameters:
            query::str -> The prolog query as a string.

        Return:
            query::pengine.Query.Query() object.

        Errors:
            IOError raised if query cannot be created, or server cannot be
            contacted
        '''
        if self.debug:
            print("Starting the call to ask.")
            print("Current state is {}".format(self.state.current_state))
        self.currentQuery = Query(self, query, False)
        print("Call to ask is complete")
        return self.currentQuery

    def doAsk(self, query):
        # Check to make sure state is idle and can handle queries.
        if self.state.current_state != "idle":
            raise PengineNotReadyException("Not in a state to handle queries")
        # Begin running query.
        if self.currentQuery is None:
            self.currentQuery = query

        # Set pengine state to "ask", process response.
        self.state.current_state = "ask"
        answer = self.penginePost(
            self.po.getActualURL("send", self.pengineID),
            "application/x-prolog; charset=UTF-8",
            self.po.getRequestBodyAsk(query.ask, self.getID()))
        self.handleAnswer(answer)

    def create(self):
        '''
        Configures the Pengine object.  Returns a pengine id string.

        Modifies state -- to "idle" if created successfully.  Else "destroy"
        '''
        assert self.state.current_state == "not_created"
        if self.debug:
            print("Starting call.")
        # Post the create request.
        url = self.po.getActualURL("create")
        contentType = "application/json"
        body = self.po.getRequestBodyCreate()
        if self.debug:
            print("Starting post request with URL {0}, content_type: {1}"\
                  ", and body: {2}".format(url, contentType, body))
        response = self.penginePost(url, contentType, body)
        if self.debug:
            print(response)

        # Begin setting various attributes.

        # Set the event state to destroy if request failed, or idle and waiting
        # for a query.
        event_string = response["event"]
        if event_string == "destroy":
            self.state.current_state = "destroy"
        elif event_string == "create":
            self.state.current_state = "idle"
        else:
            err_msg = "Create request event was {}, but must be create or"\
                "destroy".format(event_string)
            raise CouldNotCreateException(err_msg)

        # Handle setting ask.
        if self.po.ask is not None:
            # If a query is present, immediately handle it.
            self.currentQuery = Query.Query(self, self.po.getAsk(), False)
            self.state.current_state = "ask"

        # Handle "answer" key
        if "answer" in response:
            self.handleAnswer(response["answer"])

        # Handle "id" key
        id_ = response["id"]
        if id_ is None:
            raise CouldNotCreateException("No pengine id in create message")
        return id_

    def destroy(self):
        pass

    def doNext(self, query):
        '''
        This method asks the Pengine object to request the next proof from the
        server.

        Parameters:
            query :: Query the query object to continue providing data to.
        '''
        if self.debug:
            print("pengines.Pengine().doNext is firing with query ", query)
        # ToDo assert self.state.current_state == "ask"
        if query != self.currentQuery:
            raise PengineNotReadyException(
                "Cannot advance more than one query -\
                                           finish one before starting next.")

        url = self.po.getActualURL("send", self.getID())
        contentType = "application/x-prolog; charset=UTF-8"
        body = self.po.getRequestBodyNext()
        if self.debug:
            print("url: {0}; body: {2}; contentType: {1}".format(
                url, contentType, body))
        string_response_object = self.penginePost(url, contentType, body)
        self.handleAnswer(string_response_object)

    def doPullResponse(self):
        '''
        Returns a string off the server, if it has one to give.
            Otherwise, returns None.

        @raises PengineNotReadyExceptioni
        '''
        # Check it is in the correct state.
        if self.state.current_state != "idle" and \
                self.state.current_state != "ask":
            return None

        # Initialize Post request
        url = self.po.getActualURL("pull_response", self.getID())
        content_type = "application/x-prolog; charset=UTF-8"
        body_response = self.po.getRequestBodyPullResponse()
        response = self.penginePost(url, content_type, body_response)
        # Pass the response the handler
        self.handleAnswer(response)
        raise TypeError("doPullNot implemented exception")

    def doStop(self):
        '''Raises PengineNotReadyException'''
        assert self.state.current_state == "ask"
        respObject = self.penginePost(
            self.po.getActualURL("send", self.getID()),
            "application/x-prolog; charset=UTF-8",
            self.po.getRequestBodyStop())
        self.handleAnswer(respObject)
        pass

    def dumpStateDebug(self):
        pass

    def iAmFinished(self, query):
        '''
        Query won't use pengine again.

        query:: Query() : The query we are through with
        '''
        if self.currentQuery == query:
            self.currentQuery = None

        if self.state.current_state == "ask":
            self.state.current_state = "idle"

    def penginePost(self, url, contentType, body):
        '''
        Posts body to the Pengine.
        url:: String of url
        contentType :: String -> Value of Content-Type header
        body :: String -> Body of POST request

        Return: response_dict::dict -> A dict representing the JSON encoded response.
        Errors: IOError -> If there is a problem posting, an IOError is raised.
        '''
        if self.debug:
            print("Starting Post request.")
        # Set up request header
        header = dict()
        header["User-Agent"] = "PythonPengine"
        header["Accept"] = "application/json"
        header["Accept-Language"] = "en-us,en;q=0.5"
        header["Content-type"] = contentType

        # Make sure body is utf-8
        if isinstance(body, bytes):
            body_utf8 = body
        elif isinstance(body, str):
            body_utf8 = body.encode("utf-8")
        else:
            raise TypeError("Don't know how to handle body parameter of type\
                            {}").format(type(body))

        if self.debug:
            print("URL is: ", url)
            print("Data (body) : ", body_utf8)
            print("Headers: ", header)
        try:
            # Send Post Request -- catch errors and close
            request_object = Request(url, data=body_utf8, headers=header)
            response = urlopen(request_object)
            response_string_utf8 = response.readall()
            response_string = response_string_utf8.decode("utf-8")
            if self.debug:
                print("response_string is :", response_string)
            response_dict = json.JSONDecoder().decode(response_string)
            # Catch bad status codes
            status = response.status
            if status < 200 or status > 299:
                err_msg = "Bad response code: {}  If query 500 was invalid?\
                    query threw Prolog exception".format(status)
                raise IOError(err_msg)
            return response_dict
        except IOError as e:
            self.destroy()
            raise e

    def handleAnswer(self, answer):
        '''
        answer::json The JSON response from the initial post to the server

        Exceptions:
            json.JSONDecodeError
            SyntaxError
        '''
        if self.debug:
            print("pengines.Pengine().handleAnswer({})".format(answer))
        try:
            if "event" in answer:
                event_val = answer["event"]
                if self.debug:
                    print("pengine.Pengine().handleAnswer reports {}".format(
                        event_val))
                # Handle "success" switch
                if event_val == "success":
                    if "data" in answer:
                        # answer["data"] should be a list
                        self.currentQuery.addNewData(answer["data"])
                    if "more" in answer:
                        self.currentQuery.hasMore = answer["more"]

                # Handle "destroy" switch
                elif event_val == "destroy":
                    if "data" in answer:
                        self.handleAnswer(answer["data"])
                    if self.currentQuery is not None:
                        self.currentQuery.noMore()
                        self.state.current_state = "destroyed"

                # Handle "failure" switch
                elif event_val == "failure":
                    self.currentQuery.noMore()

                # Handle "stop" switch
                elif event_val == "stop":
                    self.currentQuery.noMore()

                # Handle "error" switch
                elif event_val == "error":
                    raise SyntaxError("Error - probably invalid Prolog query?")

                # Handle "died" switch
                elif event_val == "died":
                    self.state.current_state = "destroyed"

                # Default to raising a syntax error.
                else:
                    raise SyntaxError("Bad event in answer")
        except PengineNotReadyException:
            raise SyntaxError

    def getID(self):
        '''
        Getter method for the getID attribute.
        @return :: pengineID String
        @raises :: Assertion Error if current state not "ask" or "idle"
        '''
        current_state = self.state.current_state
        assert current_state == "ask" or current_state == "idle"
        return self.pengineID
예제 #8
0
from pengines.Builder import PengineBuilder
from pengines.Pengine import Pengine

factory = PengineBuilder(urlserver="http://localhost:4242", destroy=False)
pengine = Pengine(builder=factory, debug=True)
# Start query.
pengine.ask("member(X, [1,2,3])")
pengine.doAsk(pengine.currentQuery)
print()
print(pengine.currentQuery.availProofs, "Has More? ", pengine.currentQuery.hasMore)
print()
# Get next query.
print(pengine.state.current_state)
while pengine.currentQuery.hasMore:
    pengine.doNext(pengine.currentQuery)
    print(pengine.currentQuery.availProofs)
예제 #9
0
from pengines.Builder import PengineBuilder
from pengines.Pengine import Pengine
query = "wd ?? continent(X)"
pengine_builder = PengineBuilder(urlserver="http://localhost:9083",
                                 destroy=False,
                                 ask=query)
pengine = Pengine(builder=pengine_builder, debug=True)
#pengine.create()
#query = "member(X, [1,2,3])"
#pengine.ask(query)
#pengine.doAsk(pengine.currentQuery)
#print()
print(pengine.currentQuery.availProofs, "Has More? ",
      pengine.currentQuery.hasMore)
#print()
# Get next query.
#print(pengine.state.current_state)
while pengine.currentQuery.hasMore:
    pengine.doNext(pengine.currentQuery)
print(pengine.currentQuery.availProofs)
예제 #10
0
 def __init__(self):
     self.pengine_builder = PengineBuilder(
         urlserver="http://localhost:5051", application="virus")
from pengines.Builder import PengineBuilder
from pengines.Pengine import Pengine

pengine_builder = PengineBuilder(urlserver="http://localhost:4242")

pengine = Pengine(builder=pengine_builder)
pengine.create()

#query = "member(X, [1,2,3])"
#pengine.ask(query)
#print(pengine.currentQuery.availProofs)

#while pengine.currentQuery.hasMore:
#    pengine.doNext(pengine.currentQuery)
#    print(pengine.currentQuery.availProofs)

예제 #12
0
"""
Requires a neoplasmer service to run

See README.md
"""
import sys
from pengines.Builder import PengineBuilder
from pengines.Pengine import Pengine
from prologterms import TermGenerator, PrologRenderer, Program, Var
    
P = TermGenerator()
MatchID = Var('MatchID')
Score = Var('Score')
Prefix = Var('Prefix')
R = PrologRenderer()

#terms = ['neoplasm', 'glioma', 'astrocytoma']
terms = sys.argv[1:]

for t in terms:
    q = P.term_best_match(t, MatchID, Score, Prefix)
    
    factory = PengineBuilder(urlserver="http://localhost:9055",
                             ask=R.render(q))
    pengine = Pengine(builder=factory, debug=False)
    while pengine.currentQuery.hasMore:
        pengine.doNext(pengine.currentQuery)
    for p in pengine.currentQuery.availProofs:
        print('Term: {} Match: {}  {}'.format(t, p[MatchID.name], p[Score.name]))

예제 #13
0
from pengines.Builder import PengineBuilder
from pengines.Pengine import Pengine
from prologterms import TermGenerator, PrologRenderer, Program, Var

P = TermGenerator()
X = Var('X')
Y = Var('Y')
Z = Var('Z')
R = PrologRenderer()

p = Program(
    P.ancestor(X,Y) <= (P.parent(X,Z), P.ancestor(Z,Y)),
    P.ancestor(X,Y) <= P.parent(X,Y),
    P.parent('a','b'),
    P.parent('b','c'),
    P.parent('c','d')
)

q = P.ancestor(X,Y)

factory = PengineBuilder(urlserver="http://localhost:4242",
                         srctext=R.render(p),
                         ask=R.render(q))
pengine = Pengine(builder=factory, debug=True)
while pengine.currentQuery.hasMore:
    pengine.doNext(pengine.currentQuery)
for p in pengine.currentQuery.availProofs:
    print('{} <- {}'.format(p[X.name], p[Y.name]))