More python magic stuff I ran into today. It's the most convoluted use of argument names to be amazingly flexible. It's a trick on how you can just flow down your init args down a set of factories and whatever. This is how the initial code looked.
class Worker(object): def __init__(self, name="", key=""): self.name = name self.key = key def __repr__(self): return "working %s <%s>" % (self.name, self.key) class Driver: def __init__(self, worker = Worker, **kw): self.worker = worker(**kw) def __repr__(self): return "drive a %s, mad" % (self.worker) class Master: def __init__(self, **kw): self.driver = Driver(**kw) def __repr__(self): return "I pay to %s" % (self.driver) print Master(name="Gopal", key="t3")I get the obvious output from the program: I pay to drive a working Gopal <t3>, mad.
So far, so good. But from now on, I need to grade my workers on the basis of the hardness of their work. So in a totally different module, I start writing the following code:
class GradedWorker(Worker): def __init__(self, hardness="very", name="", key=""): self.hardness = hardness self.name = name self.key = key def __repr__(self): return "%s working %s <%s>" % (self.hardness, self.name, self.key) print Master(worker=GradedWorker, name="Gopal", key="t3", hardness="very very")
Voila, you have Master invoking the right worker with the right args (hardness) with no change in the original codebase at all. Tell me, how many of you knew you could do something like this with python ?. Now let me explain why I ended up writing this code - or in what codebase I started writing this. I have this WSDL file full of some cool methods, but the methods are accessible only If the HTTP call contains a particular cookie. So I started looking around the internet for a solution.
Activestate aspn didn't have an answer - python lists didn't have answer, sourceforge had a pending patch - which wasn't there in the release. Finally after giving up all hope, I hit the #python irc channel in the hope of some help.
-ChanServ- [#python] Welcome to #python, a support channel for Python programmers! If you're new, please see http://twistedmatrix.com/wiki/python/WelcomeToPoundPython.
Oct 12 01:27:30 *t3rmin4t0r is banging his head on soappy all night
Oct 12 01:27:35 t3rmin4t0r anyone know of any sane python SOAP libs ?
Oct 12 01:29:20 t3rmin4t0r does anyone know of any python SOAP libs ?
Oct 12 01:29:28 t3rmin4t0r or I'm going back to doing it in javascript hell
Oct 12 01:29:58 Erwin t3rmin4t0r: t3rmin4t0r, meet Google. Google, meet t3rmin4t0r.
Oct 12 01:30:28 t3rmin4t0r none of them support cookies in their SOAP lib
Oct 12 01:30:59 t3rmin4t0r Erwin: it's not like I don't know how to search :)
Oct 12 01:30:33 t3rmin4t0r cannot use ClientCookie or something ...
Oct 12 01:31:25 * t3rmin4t0r realizes he didn't have to come here to hear RTFM ...
Oct 12 01:31:33 * You have left channel #python ("I feel insulted and violated ....")
So here's the solution for the problem ... I couldn't sleep till I figured it out.
import sys, os, string from SOAPpy import WSDL,HTTPTransport,Config,SOAPAddress import ClientCookie import urllib2 Config.cookieJar = ClientCookie.MozillaCookieJar() # Config.cookieJar.load("cookies.txt") class CookieTransport(HTTPTransport): def call(self, addr, data, namespace, soapaction = None, encoding = None, http_proxy = None, config = Config): if not isinstance(addr, SOAPAddress): addr = SOAPAddress(addr, config) cookie_cutter = ClientCookie.HTTPCookieProcessor(config.cookieJar) hh = ClientCookie.HTTPHandler() hh.set_http_debuglevel(1) # TODO proxy support opener = ClientCookie.build_opener(cookie_cutter, hh) t = 'text/xml'; if encoding != None: t += '; charset="%s"' % encoding opener.addheaders = [("Content-Type", t), ("Cookie", "Username=foobar"), ("SOAPAction" , "%s" % (soapaction))] response = opener.open(addr.proto + "://" + addr.host + addr.path, data) data = response.read() # get the new namespace if namespace is None: new_ns = None else: new_ns = self.getNS(namespace, data) print '\n' * 4 , '-'*50 # return response payload return data, new_ns # From xmethods.net wsdlURL = "http://www.doughughes.net/WebServices/fortune/fortune.cfc?wsdl" proxy = WSDL.Proxy(wsdlURL, transport = CookieTransport) print proxy.getFortune()
Sometimes, people just piss me off... But hopefully this should help someone somewhere use SOAPpy with cookie support.