This post originated from an RSS feed registered with Python Buzz
by Andrew Dalke.
Original Post: XML-RPC in TurboGears
Feed Title: Andrew Dalke's writings
Feed URL: http://www.dalkescientific.com/writings/diary/diary-rss.xml
Feed Description: Writings from the software side of bioinformatics and chemical informatics, with a heaping of Python thrown in for good measure.
On-and-off I've looked for some way to get XML-RPC working in
TurboGears. There's a CherryPy
filter but I couldn't get it working. From what I've seen of the
examples it makes all functions available to XML-RPC, which isn't
something I wanted.
I finally gave up and rolled my own with xmlrpclib and using
SimpleXMLRPCServer.py as a guide. It was simpler than trying to
figure out the CherryPy mechanism, and simple enough that I'll list it
here more as a recipe than a reusable module.
import sys
import xmlrpclib
import cherrypy
import turbogears
from turbogears import controllers
class RPCRoot(controllers.Controller):
@turbogears.expose()
def index(self):
params, method = xmlrpclib.loads(cherrypy.request.body.read())
try:
if method == "index":
# prevent recursion
raise AssertionError("method cannot be 'index'")
# Get the function and make sure it's exposed.
method = getattr(self, method, None)
# Use the same error message to hide private method names
if method is None or not getattr(method, "exposed", False):
raise AssertionError("method does not exist")
# Call the method, convert it into a 1-element tuple
# as expected by dumps
response = method(*params)
response = xmlrpclib.dumps((response,), methodresponse=1)
except xmlrpclib.Fault, fault:
# Can't marshal the result
response = xmlrpclib.dumps(fault)
except:
# Some other error; send back some error info
response = xmlrpclib.dumps(
xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value))
)
cherrypy.response.headers["Content-Type"] = "text/xml"
return response
# User-defined functions must use cherrypy.expose; turbogears.expose
# does additional checking of the response type.
@cherrypy.expose
def add(self, a, b):
return a+b
class Root(controllers.RootController):
RPC2 = RPCRoot()
Speaking of recipe, also tried to list it in the Python Cookbook but
after several minutes waiting for the login to work I got the message
"We are currently experiencing technical issues. Please try again
shortly."