diff options
Diffstat (limited to 'src/IvyCpy.py')
-rw-r--r-- | src/IvyCpy.py | 646 |
1 files changed, 646 insertions, 0 deletions
diff --git a/src/IvyCpy.py b/src/IvyCpy.py new file mode 100644 index 0000000..f83d432 --- /dev/null +++ b/src/IvyCpy.py @@ -0,0 +1,646 @@ +# -*- coding: iso-8859-1 -*- +REVISION = "$Id: " + +# import +import threading +import ivycpy +import sys +import traceback +import re +import os + +## +# class Ivy +# this class is an Object oriented interface for the Ivy-c Library +# +class Ivy: + + ## + # __init__() + # initialisation method + # this method creates an Ivy Object and initializes an ivybus + # @param name: name of the application to connect + # @param message: the message displayed on connection + # @param aIvyApplicationListener: the reference to the object used to treat connection / disconnection event for applications + # + def __init__(self, name, message, aIvyApplicationListener): + self.lIvyApplicationlisteners=[] + self.dIvyClient={} + self.addApplicationListener(aIvyApplicationListener) + self.sReadyMessage=message + self.sAppName=name + self.dRegexp={} + self.lBindListeners=[] + self.sendToSelf = False + self.selfIvyClient = Ivy.SelfIvyClient(self) + self.dIvyClient[str(self.selfIvyClient)] = self.selfIvyClient + ivycpy.IvyInit(name, + message, + 0, + self._appliCallback, + self._die) + + ## + # method called on instruction Ivy() + # this method creates and starts a thread listening for ivy events + # + def __call__(self): + self.theThread=threading.Thread(target=self.mainloop) + self.theThread.setDaemon(1) + self.theThread.start() + + ## + # this method returns the IvyClient associated to an ivy-c client + # @param ivyclient: the reference of the ivy-c client in the local database + # @return the Ivy.IvyClient object corresponding to the ivyclient identifier + # + def getIvyClient(self, ivyclient): + ivyClient = None + if not self.dIvyClient.has_key(str(ivyclient)): + ivyClient = Ivy.IvyClient(ivyclient) + self.dIvyClient[str(ivyclient)] = ivyClient + else: + ivyClient = self.dIvyClient[str(ivyclient)] + return ivyClient + + ## + # getter of self Ivy client attribute + # @return this IvyClient object + # + def getSelfIvyClient(self): + return self.selfIvyClient + + ## + # getter of an Ivy client using his name + # @param name: name of the client + # @return the reference of the Ivy.IvyClient with the given name + # + def getIvyClientsByName(self, name): + ivyclient = ivycpy.IvyGetApplication(name) + return self.getIvyClient(ivyclient) + + ## + # method returning the ivy-c clients connected to the ivybus + # @return the list of Ivy.IvyClient connected to the ivybus + # + def getIvyClients(self): + lIvyClient = [ self.getIvyClientsByName(client) + for client in ivycpy.IvyGetApplicationList(",").split(",")] + # suppression du dernier element car element vide + lIvyClient.pop() + return lIvyClient + + ## + # methods starting the connection to ivybus + # @param sdomainbus: address used for braodcast + # + def start(self, sdomainbus): + #a partir de la chaine de caracteres + addr, port = sdomainbus.split(":") + self.sDomainBus= Ivy.Domain(addr, port) + ivycpy.IvySetBindCallback(self._bindCallback) + ivycpy.IvyBindDirectMsg(self._directMessage) + ivycpy.IvyStart(sdomainbus) + + ## + # methods stopping the connection to ivybus + # + def stop(self): + ivycpy.IvyStop() + + ## + # method launching the ivy mainloop in charge of listening events on the ivybus + # + def mainloop(self): + ivycpy.IvyMainLoop() + + ## + # method adding a ivy binding event listener to database + # @param aBindListener: listener for ivy event + # + def addBindListener(self, aBindListener): + self.lBindListeners.append(aBindListener) + + ## + # method removing an ivy binding event listener from database + # @param aBindListener: the listener to remove + # + def removeBindListener(self, aBindListener): + self.lBindListeners.remove(aBindListener) + + ## + # method adding application listener to database + # @param aApplicationListener: the listener to application connection + # + def addApplicationListener(self, aApplicationListener): + self.lIvyApplicationlisteners.append(aApplicationListener) + + ## + # method removing application listener from database + # @param aApplicationListener: the listener to remove + # + def removeApplicationListener(self, aApplicationListener): + try: + self.lIvyApplicationlisteners.remove(aApplicationListener) + except ValueError, x: + IvyException(str(x))() + + ## + # protected method called on bindings events + # @param client: reference to the ivy-c subscribing client + # @param id : unique id of the binding + # @param regexp: regular expression to match + # @param event: binding or removal of an existing binding + # + def _bindCallback(self, client, id, regexp, event): + if (event == ivycpy.IvyAddBind ): + for bl in self.lBindListeners: + bl.bindPerformed(client, id, regexp) + elif (event == ivycpy.IvyRemoveBind ): + for bl in self.lBindListeners: + bl.unbindPerformed(client, id, regexp) + + ## + # method called on applications connection + # @param ivyclient: reference to the client connected or disconnected + # @param connected: connection or disconnection + # + def _appliCallback(self, ivyclient, connected): + ivyClient = self.getIvyClient(ivyclient) + if connected == ivycpy.IvyApplicationConnected: + self._connect(ivyClient) + else: + self._disconnect(ivyClient) + + ## + # method calling the connect method of the applications listeners + # @param arg: anything + # + def _connect(self, *arg): + for listener in self.lIvyApplicationlisteners: + listener.connect(*arg) + + ## + # method calling the disconnect method of the applications listeners + # @param arg: anything + # + def _disconnect(self, *arg): + for listener in self.lIvyApplicationlisteners: + listener.disconnect(*arg) + + ## + # method called on die message + # @param ivyclient: reference to the client to kill + # @param id: id of the message + # + def _die(self, ivyclient, id): + ivyClient = self.getIvyClient(ivyclient) + for listener in self.lIvyApplicationlisteners: + listener.die(ivyClient, id) + + ## + # method called on direct message + # @param ivyclient: reference of the client + # @param id: id of the message + # @param msg: the message + # + def _directMessage(self, ivyclient, id, msg): + ivyClient = self.getIvyClient(ivyclient) + for listener in self.lIvyApplicationlisteners: + listener.directMessage(ivyClient, id, msg) + + ## + # method which binds message for application + # @param regexp: the regular expression to match + # @param aIvyMessageListener: the listener to call on reception + # @return the id of the subscription + # + def bindMsg(self, regexp, aIvyMessageListener): + id = ivycpy.IvyBindMsg(aIvyMessageListener.receive,regexp) + self.dRegexp[regexp] = id + self.selfIvyClient.bindMsg(regexp,aIvyMessageListener,id) + return id + + ## + # method which unbinds message for client + # @param param: regexp or id of the message to unbind + # + def unBindMsg(self, param): + if type(param) == type(1): + ivycpy.IvyUnBindMsg(param) + self.selfIvyClient.unbindMsg(param) + else: + if self.dRegexp.has_key(param): + self.selfIvyClient.unbindMsg(param) + id=self.dRegexp[param] + ivycpy.IvyUnBindMsg(id) + else: + IvyException("This expression did not exist")() + + ## + # method sending message on the ivybus + # @param message: the message to send + # @return the result of the operation 0 if error, 1 if ok + # + def sendMsg(self, message): + if self.getSendToSelf() is True: + self.selfIvyClient.sendMsg(message) + return ivycpy.IvySendMsg(message) + + ## + # method sending a die message to the ivy-c client + # @param ivyclient : ivy-c client to kill + # + def sendDie(self, ivyclient): + if type(ivyclient) == type(self.selfIvyClient): + self.selfIvyClient.sendDie() + else: + ivycpy.IvySendDieMsg(ivyclient) + + ## + # methods sending a message directly to a client + # @param ivyclient : the ivy-c client to contact + # @param id : id with no real meanings + # @param message : the message to send + # + def sendDirectMsg(self, ivyclient, id, message): + if type(ivyclient) == type(self.selfIvyClient): + self.selfIvyClient.sendDirectMsg(id, message) + else : + ivycpy.IvySendDirectMsg(ivyclient,id,message) + + ## + # methods sending an error message directly to a client + # @param ivyclient : the ivy-c client to contact + # @param id : id with no real meanings + # @param error : the message to send + # + def sendError(self, ivyclient, id, error): + if type(ivyclient) == type(self.selfIvyClient): + self.selfIvyClient.sendError(id, error) + else: + ivycpy.IvySendError(ivyclient,id,error) + + ## + # method launching a timer + # @param nbticks : number of ticks + # @param delay: delay before launching + # @param callback: method to call at the end + # @return the id of the timer + # + def timer_repeat(self, nbticks, delay, callback): + try: + timerid = ivycpy.IvyTimerRepeatAfter(nbticks, long(delay), callback) + except: + IvyException("An error occurred in IvyTimerRepeatAfter")() + timerid = None + + return (timerid) + + ## + # method modifying the timer + # @param timerid: id of the timer to modify + # @param newdelay: waiting delay + # + def timer_modify(self, timerid, newdelay): + ivycpy.IvyTimerModify(timerid, long(newdelay)) + + ## + # method removing timer + # @param timerid: id of the timer to remove + # + def timer_remove(self, timerid): + ivycpy.IvyTimerRemove(timerid) + + ## + # method setting the value of boolean sendToSelf + # @param value : boolean representing the falg sendToSelf + # + def setSendToSelf(self, value): + self.sendToSelf = value + + ## + # method returning the value of the flag sendToSelf + # @return boolean representing the value of the flag sendToSelf + # + def getSendToSelf(self): + return self.sendToSelf + + ## + # class IvyClient + # this class encapsulates an ivy-c client and gives methodes to access this client + # + class IvyClient: + + ## + # initialisation of the IvyClient + # @param ptr: (ivy-c client) pointer on the ivy-c client + # + def __init__(self, ptr): + self.ptr = ptr + + ## + # getter of the ivy-c client attribute + # @return a pointer on an ivy-c client + # + def getPtr(self): + return self.ptr + + ## + # getter of the ivy-c client name + # @return a string representing the name of the ivy-c client + # + def getName(self): + return ivycpy.IvyGetApplicationName(self.ptr) + + ## + # getter of the ivy-c client host + # @return a string representing the host of the ivy-c client + # + def getHost(self): + return ivycpy.IvyGetApplicationHost(self.ptr) + + ## + # getter of the ivy-c client messages bindings + # @return a table of strings representing the message for this ivy-c client + # + def getMessages(self): + return ivycpy.IvyGetApplicationMessages(self.ptr) + + ## + # method sending a die message to the ivy-c client + # @param ivyclient : ivy-c client to kill + # + def sendDie(self): + ivycpy.IvySendDieMsg(self.ptr) + + ## + # methods sending a message directly to a client + # @param ivyclient : the ivy-c client to contact + # @param id : id with no real meanings + # @param message : the message to send + # + def sendDirectMsg(self, id, message): + ivycpy.IvySendDirectMsg(self.ptr,id,message) + + ## + # methods sending an error message directly to a client + # @param ivyclient : the ivy-c client to contact + # @param id : id with no real meanings + # @param error : the message to send + # + def sendError(self, id, error): + ivycpy.IvySendError(self.ptr,id,error) + + ## + # class SelfIvyClient + # this class works like an IvyClient class but represents the application client + # + class SelfIvyClient(IvyClient): + + ## + # initialization of the SelfIvyClient + # @param ptr: pointer on the Ivy object + # + def __init__(self, ptr): + self.ptr = ptr + self.dBindings = {} + self.dId2Regexp = {} + self.dRegexp2Id = {} + + ## + # getter of the ptr attribute + # @return a pointer on an Ivy object + # + def getPtr(self): + return self.ptr + + ## + # getter of the self Client name + # @return a string representing the name of the selfclient + # + def getName(self): + return self.ptr.sAppName + + ## + # getter of the self Client host + # @return a string representing the host of the selfclient + # + def getHost(self): + return os.uname()[1] + + ## + # getter of the self Client messages bindings + # @return a tuple of strings representing the message for this selfIvyClient + # + def getMessages(self): + return tuple(self.ptr.dRegexp.keys()) + + ## + # method sending a die message to the self Client + # + def sendDie(self): + self.ptr._die(self,0) + + ## + # methods sending a message directly to self Client + # @param id : id with no real meanings + # @param message : the message to send + # + def sendDirectMsg(self, id, message): + self.ptr._directMessage(self,id,message) + + ## + # methods sending an error message directly to self Client + # @param id : id with no real meanings + # @param error : the message to send + # + def sendError(self, id, error): + self.ptr._directMessage(self,id,error) + + ## + # method sending a message to self + # @param message : string representing the message to send + # + def sendMsg(self,message): + for regexp in self.dBindings.keys(): + r = re.compile(regexp) + captures = r.match(message) + if captures: + captures=captures.groups() + if len(captures)==0: + captures='' + self.dBindings[regexp](message) + + ## + # method in charge of treating bindings + # @param regexp : String representing the regular expression to match + # @param aIvyMessageListener : the reference to object to call on reception + # @param id : id with no real meanings + # + def bindMsg(self, regexp, aIvyMessageListener, id): + self.dId2Regexp[id] = regexp + self.dRegexp2Id[regexp] = id + self.dBindings[regexp] = aIvyMessageListener.receive + + ## + # method sending a message to self + # @param message : id or regexp to delete + # + def unbindMsg(self, param): + if type(param) == type(1): + regexp = self.dId2Regexp.pop(param) + self.dRegexp2Id.pop(regexp) + self.dBindings.pop(regexp) + else: + if self.dRegexp.has_key(param): + id = self.dRegexp2Id.pop(param) + self.dRegexp2Id.pop(id) + self.dBindings.pop(param) + else: + IvyException("This expression did not exist")() + + ## + # class domain + # this class contains and allows access to ivybus properties + # + class Domain: + ## + # initialisation method + # @param domainaddr: Ip adress for broadcast + # @param port: port for braodcast + # + def __init__(self, domainaddr, port): + self.domainaddr=domainaddr + self.port=port + + ## + # method call on print + # display address and port used by ivybus + # @return the string to print + # + def __str__(self): + return self.domainaddr+":"+self.port + + ## + # getter of broadcast Ip adress + # @return the IP address + # + def getDomainaddr(self): + return self.domainaddr + + ## + # getter of broadcast port + # @return the IP port + # + def getPort(self): + return self.port + + +## +# IvyApplicationAdapter +# Classe d'objets abstraite definissant l'interface des objets a fournir a l'objet de classe Ivy +# lors de son initialisation et par les methodes addApplicationListener et removeApplicationListener +# +class IvyApplicationAdapter : + + ## + # abstract method called on application connection + # @param client: name of the client + # + def connect(self,client): + pass + + ## + # abstract method called on application disconnection + # @param client: name of the client + # + def disconnect(self,client): + pass + + ## + # abstract method called on die message + # @param client: name of the client + # @param id: id of the message + # + def die(self,client, id): + pass + + ## + # abstract method called on direct message + # @param client: name of the client + # @param id: id of the client + # @param msg: message sent + # + def directMessage(self, client, id, msg): + pass + +## +# IvyBindAdapter +# Classe d'objets abstraite definissant l'interface des objets +# a fournir a l'objet de classe Ivy +# via addBindListener et removeBindListener +# +class IvyBindAdapter : + + ## + # invoked when a Ivy Client performs a bind + # @param client: name of the client + # @param id: id of the client + # @param regexp: regular expression to match + # + def bindPerformed(self,client, id, regexp): + pass + + ## + # invoked when a Ivy Client performs a unbind + # @param client: name of the client + # @param id: id of the client + # @param regexp: regular expression to match + # + def unbindPerformed(self,client, id, regexp): + pass + + +## +# class IvyMessageAdapter +# classe abstraite definissant l'interface a fournir à la classe Ivy +# pour la reception de message +# +class IvyMessageAdapter: + + ## + # invoked when a message matching regexp is send on the bus + # @param client: name of the sender + # @param arg: message received + # + def receive(self, client, *arg): + pass + + +## +# classe gerant les exceptions Ivy +# +class IvyException : + + ## + # on error send an IvyException + # + def __call__(self): + raise self + + ## + # print the message of the exception + # @return the message to print + # + def __str__(self): + return self.message + + ## + # initialisation method + # @param message : the message to print + # + def __init__(self, message): + self.message=message + + |