#!/usr/bin/python -O # # baseClient.py # Description: A basic client for baseserver. Unless you need to do # something special, you should not need to write your # own client for your server. This client automagically # knows what commands the server offers and lets the user # call them. It is currently limited to four args for # the server functions, so if you need more, either # make a class that inherits this one and make a member # function there (easy), or hack Client to allow more # args. BTW - this was not my choice... python's scoping # sucks with lambdas. # # Requires: xmlrpc # # # Copyright: LGPL # Created: March 20, 2001 # Author: Chris Jensen - chris@sourcelight.com # # Last Update: 04/25/2001 # ##################################################################################### import xmlrpc LOG_LEVEL = 0 ClientError = 'ClientError' ERR_CLOSE = 'Connection is closed. Call reconnect.' NONE = [] # Client # # Client(host, port, timeout) # Constructor. host and port are the server to connect to. timeout is the # maximum time you should wait for the server to procedd your request. A # value less than 0 means block until the server responds. # # reconnect() # Reconnect to the server if the connection is lost. # # The rest of the callable functions are provided by the server. To get a command # list, call the usage function, which SHOULD return a complete list of functions # and thier usage. Obviously, if you write the server, you know what's there. # class Client: def __init__(self, host, port, timeout=-1.0): self.host = host # host self.port = port # server port self.timeout = timeout # xmlrpc timeout self.client = xmlrpc.client(host, port) xmlrpc.setLogLevel(LOG_LEVEL) self.cmds = self.__talk__('getclient') if not self.cmds: raise ClientError, 'could not get command list' def __getattr__(self, fn): if fn not in self.cmds: raise AttributeError, '%s instance has no attribute %s' % ( self.__class__, fn) return (lambda a1=NONE,a2=NONE,a3=NONE,a4=NONE,x=fn,y=self.__talk__: y(x, a1, a2, a3, a4)) ### ## special commands. ## # kill the server # def kill(self): if not self.client: raise ClientError, ERR_CLOSE self.timeout = 1.0 try: self.__talk__('kill') except: pass self.client = None # disconnect from the server # def leave(self): self.__talk__('leave') self.client = None # reconnect to the server # def reconnect(self): self.client = xmlrpc.client(self.host, self.port) ### ## helper functions ## # do a send and receive with the server # def __talk__(self, command, *args): args = filter(lambda x,y=NONE: (x is not y), args) if not self.client: raise ClientError, ERR_CLOSE try: return self.client.execute(command, args, timeout=self.timeout) except: self.client = xmlrpc.client(self.host, self.port) return self.client.execute(command, args, timeout=self.timeout)