3 from PyQt4.QtXml import QDomDocument
4 from sface.xmlwidget import XmlWindow, DomModel
11 def getAndPrint(self, rawOutput):
14 self.xmlrpcWindow.setData(self.xml)
15 if self.xml != "<debug></debug>":
16 # only popup the window if we have something to show
19 def store(self, rawOutput):
20 self.rawOutput = rawOutput
22 def parseMethodResponse(self, mr):
23 mr = str(mr) # PyQT supplies a QByteArray; make it a string
25 response = {"kind": "unknown"}
28 tree = etree.fromstring(mr)
29 except etree.XMLSyntaxError, e:
30 print "failed to parse XML response", str(e)
31 #file("badparse.xml","w").write(mr)
34 if tree.tag != "methodResponse" or (len(list(tree))==0):
37 # a fault should look like:
40 # faultString: "Register: Missing authority..."
42 faults = tree.xpath("//methodResponse/fault")
44 response["kind"] = "fault"
45 structs = fault.xpath("value/struct")
46 for struct in structs:
47 members = struct.xpath("member")
48 for member in members:
49 names = member.xpath("name")
50 values = member.xpath("value")
51 if (names) and (values):
54 if len(list(value))>0:
56 response[name.text] = data.text
57 # once we have the first fault, return
60 # whatever didn't fault must have succeeded?
61 response["kind"] = "success"
66 pttrnAsk = '<methodCall>.*?</methodCall>'
67 pttrnAns = '<methodResponse>.*?</methodResponse>'
68 answers = re.compile(pttrnAsk, re.DOTALL).findall(self.rawOutput)
69 replies = re.compile(pttrnAns, re.DOTALL).findall(self.rawOutput)
71 answers = [ x.replace('\\n','\n') for x in answers ]
72 replies = [ x.replace('\\n','\n').replace("'\nbody: '", '').replace("\"\nbody: '", '') for x in replies ]
73 replies.reverse() # so that I use pop() as popleft
74 # A well-formed XML document must have one, and only one, top-level element
81 # we could have less responses than calls, so guard the pop
83 replyXml = replies.pop()
85 self.responses.append(self.parseMethodResponse(replyXml))
87 # just in case somehow we ended up with more responses than calls
89 replyXml = replies.pop()
91 self.responses.append(self.parseMethodResponse(replyXml))
96 # statistics: round-trip time, size of the com
99 class XmlrpcTracker(XmlrpcReader):
101 XmlrpcReader.__init__(self)
102 self.xmlrpcWindow = XmlrpcWindow()
104 def getAndPrint(self, rawOutput):
105 self.store(rawOutput)
107 self.xmlrpcWindow.setData(self.xml)
108 if self.xml != "<debug></debug>":
109 # only popup the window if we have something to show
112 def showXmlrpc(self):
113 self.xmlrpcWindow.show()
114 self.xmlrpcWindow.resize(500, 640)
115 self.xmlrpcWindow.raise_()
116 self.xmlrpcWindow.activateWindow()
118 def extractXml(self):
119 self.xml = "<debug>" + XmlrpcReader.extractXml(self) + "</debug>"
121 class XmlrpcWindow(XmlWindow):
122 def __init__(self, parent=None):
123 # super __init__() calls updateView,
124 # which assumes you have some data
125 self.data = '<debug/>'
126 XmlWindow.__init__(self, parent, 'XMLRPC window')
128 def setData(self, XmlrpcCom):
129 self.data = XmlrpcCom
131 def updateView(self):
132 XmlWindow.updateView(self)
134 self.document.setContent(self.data)