Sharing a little programming know-how…

Archive for July, 2011

Name That Theorem

I exercised this theorem recently for a conditional statement in python. I wanted the opposite of:
if A and B:
so I came up with:
if not (A and B):
That worked fine, but I thought it would be easier to read as:
if not A or not B:

Can you name the theorem that allowed me to distribute the “not”?


Fun with XML-RPC and Introspection

You can use introspection to write a generic XML-RPC client. Introspection is not part of the “core” XML-RPC specification, but is a popular feature supported by most implementations of XML-RPC. I developed this code to interact with the Apache XML-RPC implementation specified here.

My ultimate goal in creating this client was to provide for rapid prototyping and limit the amount of client coding (I was already spending enough time implementing the server component). The concept is fairly simple. I wanted a client that I could run again-and-again and handle changes to the server’s available methods “on-the-fly”. I chose Python to write the client because Python is a dynamically typed language and great for fast-prototyping. It also helped that it has support for XML-RPC “baked in”.

I used the “listMethods” call to validate the input and use the “methodSignature” call to handle the output. My first instinct was to use the built-in getattr function in Python to obtain the appropriate method from the ServerProxy object. This worked great for methods with zero-length arguments. But what if I need to provide one or more parameters? I fumbled around a bit trying to pass the arguments as an array, then a tuple. No go in either instance. I finally decided to forgo getattr all together in favor of eval. This allowed me to dynamically build the method call to the XML-RPC server on the fly. Check out the code!


import xmlrpclib
import os, sys
import subprocess
import argparse
import logging

def initArgParser():
	description = 'XML-RPC client for MTA Server.'
	parser = argparse.ArgumentParser(description=description)
	parser.add_argument('method',help='The method you wish to invoke.')
	parser.add_argument('parameters',nargs='*',help='The parameters for the method.')
	return parser

def handleResponse(response,signature):
	if signature[0][0] == 'array':
		for item in response:
			print item
	else:
		print response

def callMethod(methodname,parameters):
	serverproxy = xmlrpclib.ServerProxy('YOUR SERVER URL HERE')
	methods = serverproxy.system.listMethods()
	if methodname not in methods:
		for method in methods:
			fqcn = method.__str__()
			if fqcn[len(fqcn) - len(methodname):] == methodname:
				methodname = fqcn
				break
	try:
		signature = serverproxy.system.methodSignature(methodname)
		if len(parameters) == len(signature[0])-1:
			if len(parameters) == 0:
				method = getattr(serverproxy,methodname)
				response = method()
			else:
				statement = 'serverproxy.' + methodname + '('
				index = 1
				for param in parameters:
					if signature[0][index] == 'string':
						statement+= '"' + param + '",'
					else:
						statement+= param + ','
					index+=1
				statement = statement[:len(statement)-1] + ')'
				response = eval(statement)
			return (response,signature)
		else:
			response = []
			response.add("Invalid number of arguments for" + methodname)
			response.add("Requires" + signature[0])
			signature[0][0] = 'array'
			return (response,signature)
	except AttributeError:
		print "Invalid method name."
		sys.exit(1)
		
if __name__ == "__main__":
	parser = initArgParser()
	args = parser.parse_args()
	response,signature = callMethod(args.method,args.parameters)
	handleResponse(response,signature)