Logo Search packages:      
Sourcecode: kayali version File versions  Download package

socketengine.py

import socket
import re
import os
import sys
import atexit

from configuration import config

import logging
l = logging.getLogger(__name__)

TIMEOUT = 20

class TIMEOUTERROR(Exception):
    pass

class Engine:

    def __init__(self):
        port = config["maximaport"]
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        keeptrying = True
        fail = False
        while keeptrying:
            try:
                self.sock.bind(('localhost', port))
            except socket.error, inst:
                l.debug( "socket error")
                l.debug( repr(inst))
                a,b = inst.args
                l.debug( "a is"+ repr(a) + "b is" + repr(b))
                if a != 98 and a!=10048:
                    # ie error is not "socket in use"
                    keeptrying = False
                    fail = True
                port += 1
            except Exception:
                keeptrying = False
                fail = True
            else:
                keeptrying = False

        if fail == True:
            l.debug( "cannot open socket! Exiting....")
            sys.exit()
            
        self.sock.listen(5)
        l.debug("start maxima")
        if sys.platform in ["win32","nt"]:
            maximabatLocation = os.path.join(config["kayalidir"],"maximab.bat")
            self.maximapid = os.spawnl(os.P_NOWAIT,maximabatLocation,"maximab.bat",str(port))
            l.debug("maxima pid is %s" % self.maximapid)
        else:
            self.maximapid = os.spawnlp(os.P_NOWAIT,"maxima","maxima","--server=" + str(port))
        
        l.debug( "maxima started")
        self.conn, self.addr = self.sock.accept()

        self.conn.settimeout(0.5)
        l.debug( "connect received: %s %s" % (repr(self.conn),repr(self.addr)))
        # for the first output there is no %O marker
        self.setMatches(["(?P<maximaout>(.*))" + r"\(%I(?P<lineno>[0-9]+)\)"])
        self.sendInput("display2d:false")
        self.getOutput()
        self.sendInput("inchar:%I")
        self.getOutput()
        self.sendInput("outchar:%O")
        PROMPT_INPUT = r"\(%I([0-9]+)\)"
        PROMPT_OUTPUT = r"\(%O[0-9]+\)"

        self.setMatches([r"\(%O[0-9]+\)" + "(?P<maximaout>(.*))" + r"\(%I(?P<lineno>[0-9]+)\)",\
                         "Incorrect syntax(?P<maximaout>(.*))" + PROMPT_INPUT,\
                    "(?P<maximaout>Wrong number of arguments)",\
                     "Maxima encountered(?P<maximaout>(.*))"+PROMPT_INPUT, \
                    "Bad Range(?P<maximaout>(.*))"+PROMPT_INPUT,\
                    "Is(?P<maximaout>(.*))zero or nonzero.*\r\n\r\n\r",\
                    PROMPT_INPUT + "(?P<maximaout>(.*))To debug.*" + PROMPT_INPUT,\
                    "Is(?P<maximaout>(.*))zero or nonzero.*\r\n\r\n\r"])
        self.getOutput()

    def getPromptLetters(self):
        return ("%I","%O")

    def sendInput(self,data):
        l.debug( "sending " + data)
        self.conn.sendall(data + ';\n')

    def setMatches(self, matches):
        self.matches = matches
        # compiled matches
        self.cmatches = []
        for r in self.matches:
            #print "compile",repr(r)
            # ignore case and match newlines with the dot
            self.cmatches.append(re.compile(r,re.I + re.S))

    def getOutput(self):
        totalWait = 0
        totalData = ""
        while True:
            data = ""
            #print "loop"
            try:
                data = self.conn.recv(1024)
            except:
                totalWait += 0.5
                if totalWait >=TIMEOUT:
                    raise TIMEOUTERROR
            l.debug( "data read in" + repr(data))
            totalData += data
            l.debug( "data so far" + repr(totalData))
            #print "check against matches"
            for index in range(len(self.cmatches)):
                c = self.cmatches[index]
                #print "check",c.pattern
                res = c.search(totalData)
                if res:
                    #print "match!", totalData
                    m = res.group('maximaout')
                    lineno = res.group('lineno')
                    m = self.strip(m)
                    self.out = m
                    #print "matched data is <" + m + ">"
                    self.eatRemainingOutput()
                    return index, int(lineno)
            if not data:
                l.debug( "waiting")

                
    def eatRemainingOutput(self):
        # clear maxima output of any remaining detritus (like extra input prompts etc)
        # this won't be necessary when maxima is fixed
        moredata = True
        while moredata:
            data = ""
            l.debug( "detritus loop")
            try:
                data = self.conn.recv(1024)
            except:
                pass
            if data == "":
                moredata = False
            

    def strip(self,input):
        # strip input of \t,\r and \n
        input = input.replace('\r','')
        input = input.replace('\n','')
        input = input.replace('\t','')
        input = input.replace(' ','')
        return input

    def evaluateInput(self,input):
        output = ""
        
        l.debug( "input is " + repr(input))
        #input = self.strip(input)
        self.sendInput(input)
        
        ret,lineno = self.getOutput()
        self.out = self.strip(self.out)
        
        #if ret == 1:
        #    QMessageBox.information(self.calcwindow,"Kayali","Timeout")
        #    print "Timeout"
        #    return None,ret,index
        if ret == 1:
            #QMessageBox.information(self.calcwindow,"Kayali","Syntax Error")
            l.debug( "Syntax Error")
            return None,ret,lineno
        if ret == 2:
            #QMessageBox.information(self.calcwindow,"Kayali","Number of Arguments Error")
            l.debug( "Num Args Error")
            return None,ret,lineno
        if ret == 3:
            #QMessageBox.information(self.calcwindow,"Kayali","Maxima Internal Lisp Error")
            l.debug("Internal Lisp Error")
            return None,ret,lineno
        if ret == 4:
            #QMessageBox.information(self.calcwindow,"Kayali","Bad Range")
            l.debug("Bad Range Error")
            return None,ret,lineno
        if ret == 5:
            error = self.out
            #QMessageBox.information(self.calcwindow,"Kayali",error)
            l.debug( "Maxima Error",error)
            return None,ret,lineno

        return (self.out,ret,lineno)

    def close(self):
        self.conn.close()
        os.system("kill " + str(self.maximapid))
            


Generated by  Doxygen 1.6.0   Back to index