def __init__(self, doGzip): self.__buf = BytesIO() if doGzip: self.__gzip = gzip.GzipFile(mode='wb', fileobj=self.__buf) stm = self.__gzip else: stm = self.__buf self.__gzip = None self.xg = BeatBoxXmlGenerator(stm, "utf-8") self.xg.startDocument() self.__elems = []
class XmlWriter(object): """General purpose xml writer, does a bunch of useful stuff above & beyond XmlGenerator.""" def __init__(self, doGzip): self.__buf = BytesIO() if doGzip: self.__gzip = gzip.GzipFile(mode='wb', fileobj=self.__buf) stm = self.__gzip else: stm = self.__buf self.__gzip = None self.xg = BeatBoxXmlGenerator(stm, "utf-8") self.xg.startDocument() self.__elems = [] def startPrefixMapping(self, prefix, namespace): self.xg.startPrefixMapping(prefix, namespace) def endPrefixMapping(self, prefix): self.xg.endPrefixMapping(prefix) def startElement(self, namespace, name, attrs=_noAttrs): self.xg.startElementNS((namespace, name), name, attrs) self.__elems.append((namespace, name)) def writeStringElement(self, namespace, name, value, attrs=_noAttrs): """If value is a list, then it writes out repeating elements, one for each value""" if islst(value): for v in value: self.writeStringElement(namespace, name, v, attrs) else: self.startElement(namespace, name, attrs) self.characters(value) self.endElement() def endElement(self): e = self.__elems[-1] self.xg.endElementNS(e, e[1]) del self.__elems[-1] def characters(self, s): # todo base64 ? if isinstance(s, datetime.datetime): # todo, timezones s = s.isoformat() elif isinstance(s, datetime.date): # todo, try isoformat s = "%04d-%02d-%02d" % (s.year, s.month, s.day) elif isinstance(s, int): s = str(s) elif isinstance(s, float): s = str(s) self.xg.characters(s) def endDocument(self): self.xg.endDocument() if (self.__gzip is not None): self.__gzip.close() return self.__buf.getvalue()
def test_gzip(self): # note this doesn't use self.w as that's not configured to zip w = beatbox.XmlWriter(True) w.startPrefixMapping("q", "urn:test") w.startElement("urn:test", "root") w.writeStringElement("urn:test", "child", "text") w.endElement() zipped = w.endDocument() gz = gzip.GzipFile(fileobj=BytesIO(zipped)) xml = gz.read() self.assertEqual(b'<?xml version="1.0" encoding="utf-8"?>\n' b'<q:root xmlns:q="urn:test"><q:child>text</q:child></q:root>', xml)
def post(self, conn=None, alwaysReturnList=False): """Complete the envelope and send the request does all the grunt work, serializes the request, makes a http request, passes the response to tramp checks for soap fault todo: check for mU='1' headers returns the relevant result from the body child """ headers = { "User-Agent": "BeatBox/" + __version__, "SOAPAction": '""', "Content-Type": "text/xml; charset=utf-8" } if beatbox.gzipResponse: headers['accept-encoding'] = 'gzip' if beatbox.gzipRequest: headers['content-encoding'] = 'gzip' close = False (scheme, host, path, params, query, frag) = urlparse(self.serverUrl) if conn is None: conn = makeConnection(scheme, host) close = True rawRequest = self.makeEnvelope() # print(rawRequest) conn.request("POST", self.serverUrl, rawRequest, headers) response = conn.getresponse() rawResponse = response.read() if response.getheader('content-encoding', '') == 'gzip': rawResponse = gzip.GzipFile(fileobj=BytesIO(rawResponse)).read() if close: conn.close() tramp = xmltramp.parse(rawResponse) try: faultString = str(tramp[_tSoapNS.Body][_tSoapNS.Fault].faultstring) faultCode = str( tramp[_tSoapNS.Body][_tSoapNS.Fault].faultcode).split(':')[-1] raise SoapFaultError(faultCode, faultString) except KeyError: pass # first child of body is XXXXResponse result = tramp[_tSoapNS.Body][0] # it contains either a single child, or for a batch call multiple children if alwaysReturnList or len(result) > 1: return result[:] else: return result[0]