from . import socket, AF_INET, SOCK_STREAM import pickle #from .signal import Signal, Status, Answer #from .signal import Query as Server_Query from . import Query, Status, Answer, Signal from . import DBUG,WARN,SPCE,SEVR,INFO from . import MplUnpickler from . import MyData debug = True class MplClient2(): def __init__(self): self.host,self.port = (None,None) # just a list of names self.currentRemoteData = [] def connect(self,con): self.host,self.port = con # give (IP,PORT) self.sock = socket(AF_INET,SOCK_STREAM) self.sock.connect(con) self.connected = True def disconnect(self): ''' shutdown socket. Warning: If server and client are local the client can not shut down the port because the server has still a handle on it''' print('closing the connection...') #~ self.sock.shutdown(socket.SHUT_WR) self.sock.close() self.connected = False print('closing the connection... DONE') def reset_connection(self,new_con = None): self.disconnect() if new_con is not None : self.connect(con) else : # try to use the old values if (self.host is not None) and (self.port is not None) : self.connect((self.host,self.port)) else : print('connection not initialized with correct values:') print('please provide host,port. currently host: ',self.host,' , port:',self.port) def send(self,sig): """ Sending a Type derived from Signal through the socket after 'pickling' it""" wf = self.sock.makefile(mode='wb') if debug: print('sending ',type(sig),' with content \"',sig.content,'\"') try : pickle.dump(sig,wf) except : return False wf.close() return True def waitForSignal(self): # wait for signal # unpickel rf = self.sock.makefile(mode='rb') try : unpickler = MplUnpickler(rf) response = unpickler.load() if debug and isinstance(response,Signal): print('CLIENT Received: {} with content \"{}\"'.format(type(response),response.content)) except EOFError : print('no answer received - or connection closed unexpectedly') response = None except : print('unknown error while waiting for response') response = None rf.close() if isinstance(response,Signal) : return response def testStatusSig(self,orgQuery,statusSig) : if isinstance(statusSig,Status) : if statusSig.value : if debug : print ('request type ',orgQuery.queryType,' successful' ) return True else : if debug : print('something went wrong on the server side handling request type',orgQuery.queryType) print(statusSig.content) return False else : print('request type ',orgQuery.queryType,' returned unknown status type') return False def readData(self,ioFunction, dataName, *args, **kwargs) : # create a Signal of type Query with arguments query = Query(Query.READDATA,{'func' : ioFunction, 'dataname' : dataName,'args' : args,'kwargs': kwargs}) status = self.send(query) if not status : print('something went wrong with the sending of readData request...') statusSig = self.waitForSignal() return self.testStatusSig(query,statusSig) def listRemoteData(self): """ The server retuns a list with the content of its G_RAWDATA """ query = Query(Query.LISTDATA,None) status = self.send(query) if not status : print('something went wrong with the sending of readData request...') answer = self.waitForSignal() if isinstance(answer,Answer) : return answer.content elif isinstance(answer,Status): print(answer.content) return None def getData(self, dataname) : """ The server returns the actual data known under "dataname" warning: this can possibly be HUGE """ query = Query(Query.GETDATA,dataname) status = self.send(query) if not status : print('something went wrong with the sending of readData request...') answer = self.waitForSignal() if isinstance(answer,Answer) : return answer.content elif isinstance(answer,Status): print(answer.content) return None def newSyncFigure(self, figname, dataname, *args, **kwargs) : ''' Send a query NEWSYNCFIGURE to the server wait for the status. if status ok then sync. ''' # create a Signal of type Query with args query = Query(Query.NEWSYNCFIGURE,{'figClassName' : figname.__name__, "dataName" : dataname, 'args' : args, 'kwargs' : kwargs}) status = self.send(query) if not status : print('something went wrong with the sending of newSincFigure request...') answer = self.waitForSignal() # try to create a figure of the same class on the client side if isinstance(answer,Answer) : print('trying to create a figure of the same class on the client side') fig = figname( dataname, *args, **kwargs) # Link the temporary Sync Figure fig.syncID = answer.content fig.client = self return fig elif isinstance(answer,Status) : self.testStatusSig(query,answer) return None else : print('an unknown error occured') return None def updateSyncFigure(self,syncID,kwargs) : ''' Send a UPDATE_SYNC_FIGURE query to the server. wait for the status if status ok then sync. ''' # create a signal with args query = Query(Query.UPDATESYNCFIGURE,(syncID,kwargs)) self.send(query) statusSig = self.waitForSignal() if statusSig.value : return True else: return False def deleteSyncFigure(self,syncID): ''' Send a DELETESYNCFIGURE query to the server. If the FigID is known delete it from G_FIGURES (server) wait for the confirmation status if status ok then proceed deletion. ''' # create a signal with syncID as content query = Query(Query.DELETESYNCFIGURE,syncID) status = self.send(query) statusSig = self.waitForSignal() if status and statusSig.value: return True else: print('The remote figure could not be deleted') print statusSig.content return False # SYNC FIGURE FORMAT RAWDATA --------------------------------------- def syncFigFormatRawData(self, syncID): ''' Send a FORMAT_SYNC_FIGURE query to the server. wait for the answer if answer not empty then set data to answer's value. ''' # Send the signal with syncID as content signal = Query(Query.SYNCFIGFORMATRAWDATA,syncID) status = self.send(signal) if debug: if not status: print(INFO+'Sent Signal') formatedData = self.waitForSignal() if not isinstance(formatedData,Answer) : print(WARN + 'The server could not format the rawdata.') if isinstance(formatedData,Status) : if formatedData.value : print('This should not happen') else : print('instead if answer a error was received') datas = (None,) else : # set the figure data to answerSig.value datas = formatedData.content return datas