#!/usr/bin/python # # A wrapper for the python module _xmlrpc (which was written in C) # # Copyright (C) 2001, Shilad Sen, Sourcelight Technologies, Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 # # The author can be reached at: # # shilad.sen@sourcelight.com # # Shilad Sen # Sourcelight Technologies, Inc. # 906 University Place, Suite B-211 # Evanston, IL 60201 # # Thanks to Chris Jensen for the windows port and Pat Szuta for DateTime # and Base64 objects. # # import sys import _xmlrpc VERSION = _xmlrpc.VERSION LIBRARY = _xmlrpc.LIBRARY ACT_INPUT = _xmlrpc.ACT_INPUT ACT_OUTPUT = _xmlrpc.ACT_OUTPUT ACT_EXCEPT = _xmlrpc.ACT_EXCEPT ONERR_KEEP_DEF = _xmlrpc.ONERR_KEEP_DEF ONERR_KEEP_WORK = _xmlrpc.ONERR_KEEP_WORK DATE_FORMAT_US = _xmlrpc.DATE_FORMAT_US DATE_FORMAT_EUROPE = _xmlrpc.DATE_FORMAT_EUROPE # An xmlrpc server object # # addMethods(dict): # "Registers" commands. Commands take a dictionary where # keys are command names and values are the functions to call. # Each function must take 4 args (serv, src, uri, method, params) # and return the value to be returned to the client. If an error # is raised, a fault response is created, and the client will (in # this client implementation) raise the same error. Note that the # the server can delay responding until a later time by raising # a xmlrpc.postpone error. See queueResponse and queueFault. # # activeFds(): # Returns a 3-tuple of the active file descriptor sets for # They are: (input_fds, output_fds, exception_fds) # # bindAndListen(port, queue=DEF_QUEUE): # Bind the server to a port and start listening. This function # takes the port to bind to and an optional queue size. # # setOnErr(onErr): # Set an error handler for server errors. (For example, for bad # requests). Each error handler should take the server and the # source that caused the error. Error handlers must return an # integer, that is composed of the following values bitwise # or'ed together: # ONERR_KEEP_DEF: do default error handling # (consists of printing traceback and # dropping the client) # ONERR_KEEP_WORK: don't raise this exception any higher # # work(timeout=-1.0): # Process requests for some period of time # All internal errors (such as bad requests) are raised here. # You should set an error handler using server.setOnErr() if # this is not your desired behavior # # setFdAndListen(port, queue=5): # The same as bindAndListen, but uses a supplied socket fd. # Useful mainly for inetd servers inheriting a socket through # stdin. # # setAuth(authFunc): # Set a handler used for basic authentication. The handler # will get three arguments: (uri, name, password) and return # a two-tuple of a 1 or 0 (1 indicating success) and the # domain the authentication should apply to. Note that the # domain is not currently used. # # addSource(src): # Monitor a source into the server's file descriptor event loop. # # delSource(src): # Remove a source from the server's file descriptor event loop. # # queueResponse(src, result): # This function is only useful if the response has been delayed # by raising a xmlrpc.postpone exception. This function will # complete the response to the given client (source). # # queueFault(src, faultCode, faultString): # Same as queueResponse but raises a fault. # class server: def __init__(self): self._o = _xmlrpc.server() self.comtab = {} def addMethods(self, dict): d = {} for (name, func) in dict.items(): d[name] = self.dispatch self.comtab[name] = func self._o.addMethods(d) def dispatch(self, serv, src, uri, method, params): return self.comtab[method](self, src, uri, method, params) def bindAndListen(self, port, queue=5): self._o.bindAndListen(port, queue) def close(self): self._o.close() def setFdAndListen(self, fd, queue=5): self._o.setFdAndListen(fd, queue) def work(self, timeout=-1.0): self._o.work(timeout) def exit(self): self._o.exit() def activeFds(self): return self._o.activeFds() def setAuth(self, authFunc): self._o.setAuth(authFunc) def setOnErr(self, onErr): self._o.setOnErr(onErr) def addSource(self, src): self._o.addSource(src._o) def delSource(self, src): self._o.delSource(src._o) def queueResponse(self, src, response): self._o.queueResponse(src, response) def queueFault(self, src, faultCode, faultString): self._o.queueFault(src, faultCode, faultString) # An xmlrpc client class # # activeFds(): # Returns a 3-tuple of the active file descriptor sets for # They are: (input_fds, output_fds, exception_fds) # # close(): # Free any file descriptors associated with the client # # execute(method, params, timeout=-1.0): # Execute a command on a remote host that has been connected to. # If the server generates a fault response, an exception is # raised. # # nbExecute(method, params, pyfunc, extArgs): # Queue up a command for execution when "work()" is called. # # setOnErr(onErr): # Set an error handler for internal client errors (i.e. read # failed). This is only if you use nbExecute. Each error # handler should take the server and the source that caused the # error. Error handlers must return an integer that is composed # of the following values bitwise or'ed together: # ONERR_KEEP_DEF: do default error handling # (consists of printing traceback and # dropping the client) # ONERR_KEEP_WORK: don't raise this exception any higher # # work(timeout=-1.0): # Process requests for some period of time # All internal errors (such as bad requests) are raised here. # You should set an error handler using client.setOnErr() if # this is not your desired behavior # class client: def __init__(self, host, port, url='/', serv=None): if serv: self._o = _xmlrpc.clientFromServer( host, port, url, serv._o) else: self._o = _xmlrpc.client(host, port, url) def activeFds(self): return self._o.activeFds() def close(self): self._o.close() def execute(self, method, params, timeout=-1.0, name=None, passw=None): return self._o.execute(method, params, timeout, name, passw) def fdState(self): return self._o.fdState() def nbExecute(self, method, params, pyfunc, extArgs=None, name=None, passw=None): self._o.nbexecute(method, params, self.nbDispatch, (pyfunc, extArgs), name, passw) def nbDispatch(self, src, response, (pyfunc, extArgs)): pyfunc(self, response, extArgs) def work(self, timeout=-1.0): self._o.work(timeout) def setOnErr(self, onErr): self._o.setOnErr(onErr) # An xmlrpc source. This is not documented yet. # # setOnErr(onErr): # Set an error handler for server errors. (For example, for bad # requests). Each error handler should take the server and the # source that caused the error. Error handlers must return an # integer, that is composed of the following values bitwise # or'ed together: # ONERR_KEEP_DEF: do default error handling # (consists of printing traceback and # dropping the client) # ONERR_KEEP_WORK: don't raise this exception any higher # class source: def __init__(self, fd): self._o = _xmlrpc.source(fd) def getDesc(self): return self._o.getDesc() def setDesc(self, desc): self._o.setDesc(desc) def setOnErr(self, onErr): self._o.setOnErr(onErr) def setCallback(self, func, actions, params): self._o.setCallback(self.marshaller, actions, params) self._func = func def marshaller(self, src, actions, args): return self._func(self, actions, args) # module wide definitions # def setLogLevel(level): _xmlrpc.setLogLevel(level) def setLogger(file): _xmlrpc.setLogger(file) def getDateFormat(): return _xmlrpc.getDateFormat() def setDateFormat(format): _xmlrpc.setDateFormat(format) # boolean data type; constructor takes 0 or 1; value can be used in logic exp # boolean = _xmlrpc.boolean booleanType = type(boolean(0)) # dateTime data type; constructor takes 6 tuple # dateTime = _xmlrpc.dateTime dateTimeType = type(dateTime(1,1,1,1,1,1)) # base64 data type; constructor takes binary sting # base64 = _xmlrpc.base64 base64Type = type(base64('')) # fault data type # fault = _xmlrpc.fault # A postpone error can be raised by a server's handler function to notify # the client that a response will be returned LATER # postpone = _xmlrpc.postpone # xml encode an xmlrpc data value # def encode(value): return _xmlrpc.encode(value) # decode xml representing an xmlrpc data value # returns a tuple of the value an any unused portion of the xml string # def decode(xml): return _xmlrpc.decode(xml) # build a string representing a xmlrpc request # method must be a string which is the name of the remote function # params must be a sequence of some sort # addInfo is a dictionary of additional header information # def buildRequest(uri, method, params, addInfo={}): return _xmlrpc.buildRequest(uri, method, params, addInfo) # build a string representing a xmlrpc response # result is the result object to be returned to the client # addInfo is a dictionary of additional header information # def buildResponse(result, addInfo={}): return _xmlrpc.buildResponse(result, addInfo) # build a string representing a xmlrpc fault # errCode is an integer representing the error # errStr is a string representing the error # addInfo is a dictionary of additional header information # def buildFault(errCode, errStr, addInfo={}): return _xmlrpc.buildFault(errCode, errStr, addInfo) # parse a string representing a xmlrpc response # a tuple of the result and any additional header info are included # if a fault page is parsed, a corresponding exception is raised # def parseResponse(response): return _xmlrpc.parseResponse(response) # parse a string representing a xmlrpc request # a tuple of the method name, params, and additional header info are included # def parseRequest(request): return _xmlrpc.parseRequest(request)