[git-p4: depot-paths = "//depot/": change = 1101]replace/b43bf02ddeddd088c0e6b94974ca1a46562eb3db
| @@ -0,0 +1,202 @@ | |||||
| """ | |||||
| ################################################################################ | |||||
| # Copyright (c) 2003, Pfizer | |||||
| # Copyright (c) 2001, Cayce Ullman. | |||||
| # Copyright (c) 2001, Brian Matthews. | |||||
| # | |||||
| # All rights reserved. | |||||
| # | |||||
| # Redistribution and use in source and binary forms, with or without | |||||
| # modification, are permitted provided that the following conditions are met: | |||||
| # Redistributions of source code must retain the above copyright notice, this | |||||
| # list of conditions and the following disclaimer. | |||||
| # | |||||
| # Redistributions in binary form must reproduce the above copyright notice, | |||||
| # this list of conditions and the following disclaimer in the documentation | |||||
| # and/or other materials provided with the distribution. | |||||
| # | |||||
| # Neither the name of actzero, inc. nor the names of its contributors may | |||||
| # be used to endorse or promote products derived from this software without | |||||
| # specific prior written permission. | |||||
| # | |||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
| # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | |||||
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| # | |||||
| ################################################################################ | |||||
| """ | |||||
| ident = '$Id: Config.py,v 1.9 2004/01/31 04:20:05 warnes Exp $' | |||||
| from version import __version__ | |||||
| import copy, socket | |||||
| from types import * | |||||
| from NS import NS | |||||
| ################################################################################ | |||||
| # Configuration class | |||||
| ################################################################################ | |||||
| class SOAPConfig: | |||||
| __readonly = ('SSLserver', 'SSLclient', 'GSIserver', 'GSIclient') | |||||
| def __init__(self, config = None, **kw): | |||||
| d = self.__dict__ | |||||
| if config: | |||||
| if not isinstance(config, SOAPConfig): | |||||
| raise AttributeError, \ | |||||
| "initializer must be SOAPConfig instance" | |||||
| s = config.__dict__ | |||||
| for k, v in s.items(): | |||||
| if k[0] != '_': | |||||
| d[k] = v | |||||
| else: | |||||
| # Setting debug also sets returnFaultInfo, | |||||
| # dumpHeadersIn, dumpHeadersOut, dumpSOAPIn, and dumpSOAPOut | |||||
| self.debug = 0 | |||||
| self.dumpFaultInfo = 1 | |||||
| # Setting namespaceStyle sets typesNamespace, typesNamespaceURI, | |||||
| # schemaNamespace, and schemaNamespaceURI | |||||
| self.namespaceStyle = '1999' | |||||
| self.strictNamespaces = 0 | |||||
| self.typed = 1 | |||||
| self.buildWithNamespacePrefix = 1 | |||||
| self.returnAllAttrs = 0 | |||||
| # Strict checking of range for floats and doubles | |||||
| self.strict_range = 0 | |||||
| # Default encoding for dictionary keys | |||||
| self.dict_encoding = 'ascii' | |||||
| # New argument name handling mechanism. See | |||||
| # README.MethodParameterNaming for details | |||||
| self.specialArgs = 1 | |||||
| # If unwrap_results=1 and there is only element in the struct, | |||||
| # SOAPProxy will assume that this element is the result | |||||
| # and return it rather than the struct containing it. | |||||
| # Otherwise SOAPproxy will return the struct with all the | |||||
| # elements as attributes. | |||||
| self.unwrap_results = 1 | |||||
| # Automatically convert SOAP complex types, and | |||||
| # (recursively) public contents into the corresponding | |||||
| # python types. (Private subobjects have names that start | |||||
| # with '_'.) | |||||
| # | |||||
| # Conversions: | |||||
| # - faultType --> raise python exception | |||||
| # - arrayType --> array | |||||
| # - compoundType --> dictionary | |||||
| # | |||||
| self.simplify_objects = 0 | |||||
| # Per-class authorization method. If this is set, before | |||||
| # calling a any class method, the specified authorization | |||||
| # method will be called. If it returns 1, the method call | |||||
| # will proceed, otherwise the call will throw with an | |||||
| # authorization error. | |||||
| self.authMethod = None | |||||
| # Globus Support if pyGlobus.io available | |||||
| try: | |||||
| from pyGlobus import io; | |||||
| d['GSIserver'] = 1 | |||||
| d['GSIclient'] = 1 | |||||
| except: | |||||
| d['GSIserver'] = 0 | |||||
| d['GSIclient'] = 0 | |||||
| # Server SSL support if M2Crypto.SSL available | |||||
| try: | |||||
| from M2Crypto import SSL | |||||
| d['SSLserver'] = 1 | |||||
| except: | |||||
| d['SSLserver'] = 0 | |||||
| # Client SSL support if socket.ssl available | |||||
| try: | |||||
| from socket import ssl | |||||
| d['SSLclient'] = 1 | |||||
| except: | |||||
| d['SSLclient'] = 0 | |||||
| for k, v in kw.items(): | |||||
| if k[0] != '_': | |||||
| setattr(self, k, v) | |||||
| def __setattr__(self, name, value): | |||||
| if name in self.__readonly: | |||||
| raise AttributeError, "readonly configuration setting" | |||||
| d = self.__dict__ | |||||
| if name in ('typesNamespace', 'typesNamespaceURI', | |||||
| 'schemaNamespace', 'schemaNamespaceURI'): | |||||
| if name[-3:] == 'URI': | |||||
| base, uri = name[:-3], 1 | |||||
| else: | |||||
| base, uri = name, 0 | |||||
| if type(value) == StringType: | |||||
| if NS.NSMAP.has_key(value): | |||||
| n = (value, NS.NSMAP[value]) | |||||
| elif NS.NSMAP_R.has_key(value): | |||||
| n = (NS.NSMAP_R[value], value) | |||||
| else: | |||||
| raise AttributeError, "unknown namespace" | |||||
| elif type(value) in (ListType, TupleType): | |||||
| if uri: | |||||
| n = (value[1], value[0]) | |||||
| else: | |||||
| n = (value[0], value[1]) | |||||
| else: | |||||
| raise AttributeError, "unknown namespace type" | |||||
| d[base], d[base + 'URI'] = n | |||||
| try: | |||||
| d['namespaceStyle'] = \ | |||||
| NS.STMAP_R[(d['typesNamespace'], d['schemaNamespace'])] | |||||
| except: | |||||
| d['namespaceStyle'] = '' | |||||
| elif name == 'namespaceStyle': | |||||
| value = str(value) | |||||
| if not NS.STMAP.has_key(value): | |||||
| raise AttributeError, "unknown namespace style" | |||||
| d[name] = value | |||||
| n = d['typesNamespace'] = NS.STMAP[value][0] | |||||
| d['typesNamespaceURI'] = NS.NSMAP[n] | |||||
| n = d['schemaNamespace'] = NS.STMAP[value][1] | |||||
| d['schemaNamespaceURI'] = NS.NSMAP[n] | |||||
| elif name == 'debug': | |||||
| d[name] = \ | |||||
| d['returnFaultInfo'] = \ | |||||
| d['dumpHeadersIn'] = \ | |||||
| d['dumpHeadersOut'] = \ | |||||
| d['dumpSOAPIn'] = \ | |||||
| d['dumpSOAPOut'] = value | |||||
| else: | |||||
| d[name] = value | |||||
| Config = SOAPConfig() | |||||
| @@ -0,0 +1,79 @@ | |||||
| """ | |||||
| ################################################################################ | |||||
| # | |||||
| # SOAPpy - Cayce Ullman (cayce@actzero.com) | |||||
| # Brian Matthews (blm@actzero.com) | |||||
| # Gregory Warnes (gregory_r_warnes@groton.pfizer.com) | |||||
| # Christopher Blunck (blunck@gst.com) | |||||
| # | |||||
| ################################################################################ | |||||
| # Copyright (c) 2003, Pfizer | |||||
| # Copyright (c) 2001, Cayce Ullman. | |||||
| # Copyright (c) 2001, Brian Matthews. | |||||
| # | |||||
| # All rights reserved. | |||||
| # | |||||
| # Redistribution and use in source and binary forms, with or without | |||||
| # modification, are permitted provided that the following conditions are met: | |||||
| # Redistributions of source code must retain the above copyright notice, this | |||||
| # list of conditions and the following disclaimer. | |||||
| # | |||||
| # Redistributions in binary form must reproduce the above copyright notice, | |||||
| # this list of conditions and the following disclaimer in the documentation | |||||
| # and/or other materials provided with the distribution. | |||||
| # | |||||
| # Neither the name of actzero, inc. nor the names of its contributors may | |||||
| # be used to endorse or promote products derived from this software without | |||||
| # specific prior written permission. | |||||
| # | |||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
| # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | |||||
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| # | |||||
| ################################################################################ | |||||
| """ | |||||
| ident = '$Id: Errors.py,v 1.4 2004/01/31 04:20:05 warnes Exp $' | |||||
| from version import __version__ | |||||
| import exceptions | |||||
| ################################################################################ | |||||
| # Exceptions | |||||
| ################################################################################ | |||||
| class Error(exceptions.Exception): | |||||
| def __init__(self, msg): | |||||
| self.msg = msg | |||||
| def __str__(self): | |||||
| return "<Error : %s>" % self.msg | |||||
| __repr__ = __str__ | |||||
| def __call__(self): | |||||
| return (msg,) | |||||
| class RecursionError(Error): | |||||
| pass | |||||
| class UnknownTypeError(Error): | |||||
| pass | |||||
| class HTTPError(Error): | |||||
| # indicates an HTTP protocol error | |||||
| def __init__(self, code, msg): | |||||
| self.code = code | |||||
| self.msg = msg | |||||
| def __str__(self): | |||||
| return "<HTTPError %s %s>" % (self.code, self.msg) | |||||
| __repr__ = __str__ | |||||
| def __call___(self): | |||||
| return (self.code, self.msg, ) | |||||
| class UnderflowError(exceptions.ArithmeticError): | |||||
| pass | |||||
| @@ -0,0 +1,104 @@ | |||||
| """ | |||||
| ################################################################################ | |||||
| # | |||||
| # SOAPpy - Cayce Ullman (cayce@actzero.com) | |||||
| # Brian Matthews (blm@actzero.com) | |||||
| # Gregory Warnes (gregory_r_warnes@groton.pfizer.com) | |||||
| # Christopher Blunck (blunck@gst.com) | |||||
| # | |||||
| ################################################################################ | |||||
| # Copyright (c) 2003, Pfizer | |||||
| # Copyright (c) 2001, Cayce Ullman. | |||||
| # Copyright (c) 2001, Brian Matthews. | |||||
| # | |||||
| # All rights reserved. | |||||
| # | |||||
| # Redistribution and use in source and binary forms, with or without | |||||
| # modification, are permitted provided that the following conditions are met: | |||||
| # Redistributions of source code must retain the above copyright notice, this | |||||
| # list of conditions and the following disclaimer. | |||||
| # | |||||
| # Redistributions in binary form must reproduce the above copyright notice, | |||||
| # this list of conditions and the following disclaimer in the documentation | |||||
| # and/or other materials provided with the distribution. | |||||
| # | |||||
| # Neither the name of actzero, inc. nor the names of its contributors may | |||||
| # be used to endorse or promote products derived from this software without | |||||
| # specific prior written permission. | |||||
| # | |||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
| # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | |||||
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| # | |||||
| ################################################################################ | |||||
| """ | |||||
| from __future__ import nested_scopes | |||||
| ident = '$Id: NS.py,v 1.3 2004/01/31 04:20:05 warnes Exp $' | |||||
| from version import __version__ | |||||
| ############################################################################## | |||||
| # Namespace Class | |||||
| ################################################################################ | |||||
| def invertDict(dict): | |||||
| d = {} | |||||
| for k, v in dict.items(): | |||||
| d[v] = k | |||||
| return d | |||||
| class NS: | |||||
| XML = "http://www.w3.org/XML/1998/namespace" | |||||
| ENV = "http://schemas.xmlsoap.org/soap/envelope/" | |||||
| ENC = "http://schemas.xmlsoap.org/soap/encoding/" | |||||
| XSD = "http://www.w3.org/1999/XMLSchema" | |||||
| XSD2 = "http://www.w3.org/2000/10/XMLSchema" | |||||
| XSD3 = "http://www.w3.org/2001/XMLSchema" | |||||
| XSD_L = [XSD, XSD2, XSD3] | |||||
| EXSD_L= [ENC, XSD, XSD2, XSD3] | |||||
| XSI = "http://www.w3.org/1999/XMLSchema-instance" | |||||
| XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance" | |||||
| XSI3 = "http://www.w3.org/2001/XMLSchema-instance" | |||||
| XSI_L = [XSI, XSI2, XSI3] | |||||
| URN = "http://soapinterop.org/xsd" | |||||
| # For generated messages | |||||
| XML_T = "xml" | |||||
| ENV_T = "SOAP-ENV" | |||||
| ENC_T = "SOAP-ENC" | |||||
| XSD_T = "xsd" | |||||
| XSD2_T= "xsd2" | |||||
| XSD3_T= "xsd3" | |||||
| XSI_T = "xsi" | |||||
| XSI2_T= "xsi2" | |||||
| XSI3_T= "xsi3" | |||||
| URN_T = "urn" | |||||
| NSMAP = {ENV_T: ENV, ENC_T: ENC, XSD_T: XSD, XSD2_T: XSD2, | |||||
| XSD3_T: XSD3, XSI_T: XSI, XSI2_T: XSI2, XSI3_T: XSI3, | |||||
| URN_T: URN} | |||||
| NSMAP_R = invertDict(NSMAP) | |||||
| STMAP = {'1999': (XSD_T, XSI_T), '2000': (XSD2_T, XSI2_T), | |||||
| '2001': (XSD3_T, XSI3_T)} | |||||
| STMAP_R = invertDict(STMAP) | |||||
| def __init__(self): | |||||
| raise Error, "Don't instantiate this" | |||||
| @@ -0,0 +1,620 @@ | |||||
| """ | |||||
| ################################################################################ | |||||
| # Copyright (c) 2003, Pfizer | |||||
| # Copyright (c) 2001, Cayce Ullman. | |||||
| # Copyright (c) 2001, Brian Matthews. | |||||
| # | |||||
| # All rights reserved. | |||||
| # | |||||
| # Redistribution and use in source and binary forms, with or without | |||||
| # modification, are permitted provided that the following conditions are met: | |||||
| # Redistributions of source code must retain the above copyright notice, this | |||||
| # list of conditions and the following disclaimer. | |||||
| # | |||||
| # Redistributions in binary form must reproduce the above copyright notice, | |||||
| # this list of conditions and the following disclaimer in the documentation | |||||
| # and/or other materials provided with the distribution. | |||||
| # | |||||
| # Neither the name of actzero, inc. nor the names of its contributors may | |||||
| # be used to endorse or promote products derived from this software without | |||||
| # specific prior written permission. | |||||
| # | |||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
| # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | |||||
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| # | |||||
| ################################################################################ | |||||
| """ | |||||
| ident = '$Id: SOAPBuilder.py,v 1.19 2004/04/10 04:28:46 irjudson Exp $' | |||||
| from version import __version__ | |||||
| import cgi | |||||
| import copy | |||||
| from wstools.XMLname import toXMLname, fromXMLname | |||||
| import fpconst | |||||
| # SOAPpy modules | |||||
| from Config import Config | |||||
| from NS import NS | |||||
| from Types import * | |||||
| # Test whether this Python version has Types.BooleanType | |||||
| # If it doesn't have it, then False and True are serialized as integers | |||||
| try: | |||||
| BooleanType | |||||
| pythonHasBooleanType = 1 | |||||
| except NameError: | |||||
| pythonHasBooleanType = 0 | |||||
| ################################################################################ | |||||
| # SOAP Builder | |||||
| ################################################################################ | |||||
| class SOAPBuilder: | |||||
| _xml_top = '<?xml version="1.0"?>\n' | |||||
| _xml_enc_top = '<?xml version="1.0" encoding="%s"?>\n' | |||||
| _env_top = '%(ENV_T)s:Envelope %(ENV_T)s:encodingStyle="%(ENC)s"' % \ | |||||
| NS.__dict__ | |||||
| _env_bot = '</%(ENV_T)s:Envelope>\n' % NS.__dict__ | |||||
| # Namespaces potentially defined in the Envelope tag. | |||||
| _env_ns = {NS.ENC: NS.ENC_T, NS.ENV: NS.ENV_T, | |||||
| NS.XSD: NS.XSD_T, NS.XSD2: NS.XSD2_T, NS.XSD3: NS.XSD3_T, | |||||
| NS.XSI: NS.XSI_T, NS.XSI2: NS.XSI2_T, NS.XSI3: NS.XSI3_T} | |||||
| def __init__(self, args = (), kw = {}, method = None, namespace = None, | |||||
| header = None, methodattrs = None, envelope = 1, encoding = 'UTF-8', | |||||
| use_refs = 0, config = Config, noroot = 0): | |||||
| # Test the encoding, raising an exception if it's not known | |||||
| if encoding != None: | |||||
| ''.encode(encoding) | |||||
| self.args = args | |||||
| self.kw = kw | |||||
| self.envelope = envelope | |||||
| self.encoding = encoding | |||||
| self.method = method | |||||
| self.namespace = namespace | |||||
| self.header = header | |||||
| self.methodattrs= methodattrs | |||||
| self.use_refs = use_refs | |||||
| self.config = config | |||||
| self.out = [] | |||||
| self.tcounter = 0 | |||||
| self.ncounter = 1 | |||||
| self.icounter = 1 | |||||
| self.envns = {} | |||||
| self.ids = {} | |||||
| self.depth = 0 | |||||
| self.multirefs = [] | |||||
| self.multis = 0 | |||||
| self.body = not isinstance(args, bodyType) | |||||
| self.noroot = noroot | |||||
| def build(self): | |||||
| if Config.debug: print "In build." | |||||
| ns_map = {} | |||||
| # Cache whether typing is on or not | |||||
| typed = self.config.typed | |||||
| if self.header: | |||||
| # Create a header. | |||||
| self.dump(self.header, "Header", typed = typed) | |||||
| self.header = None # Wipe it out so no one is using it. | |||||
| if self.body: | |||||
| # Call genns to record that we've used SOAP-ENV. | |||||
| self.depth += 1 | |||||
| body_ns = self.genns(ns_map, NS.ENV)[0] | |||||
| self.out.append("<%sBody>\n" % body_ns) | |||||
| if self.method: | |||||
| self.depth += 1 | |||||
| a = '' | |||||
| if self.methodattrs: | |||||
| for (k, v) in self.methodattrs.items(): | |||||
| a += ' %s="%s"' % (k, v) | |||||
| if self.namespace: # Use the namespace info handed to us | |||||
| methodns, n = self.genns(ns_map, self.namespace) | |||||
| else: | |||||
| methodns, n = '', '' | |||||
| self.out.append('<%s%s%s%s%s>\n' % ( | |||||
| methodns, self.method, n, a, self.genroot(ns_map))) | |||||
| try: | |||||
| if type(self.args) != TupleType: | |||||
| args = (self.args,) | |||||
| else: | |||||
| args = self.args | |||||
| for i in args: | |||||
| self.dump(i, typed = typed, ns_map = ns_map) | |||||
| if hasattr(self.config, "argsOrdering") and self.config.argsOrdering.has_key(self.method): | |||||
| for k in self.config.argsOrdering.get(self.method): | |||||
| self.dump(self.kw.get(k), k, typed = typed, ns_map = ns_map) | |||||
| else: | |||||
| for (k, v) in self.kw.items(): | |||||
| self.dump(v, k, typed = typed, ns_map = ns_map) | |||||
| except RecursionError: | |||||
| if self.use_refs == 0: | |||||
| # restart | |||||
| b = SOAPBuilder(args = self.args, kw = self.kw, | |||||
| method = self.method, namespace = self.namespace, | |||||
| header = self.header, methodattrs = self.methodattrs, | |||||
| envelope = self.envelope, encoding = self.encoding, | |||||
| use_refs = 1, config = self.config) | |||||
| return b.build() | |||||
| raise | |||||
| if self.method: | |||||
| self.out.append("</%s%s>\n" % (methodns, self.method)) | |||||
| self.depth -= 1 | |||||
| if self.body: | |||||
| # dump may add to self.multirefs, but the for loop will keep | |||||
| # going until it has used all of self.multirefs, even those | |||||
| # entries added while in the loop. | |||||
| self.multis = 1 | |||||
| for obj, tag in self.multirefs: | |||||
| self.dump(obj, tag, typed = typed, ns_map = ns_map) | |||||
| self.out.append("</%sBody>\n" % body_ns) | |||||
| self.depth -= 1 | |||||
| if self.envelope: | |||||
| e = map (lambda ns: ' xmlns:%s="%s"' % (ns[1], ns[0]), | |||||
| self.envns.items()) | |||||
| self.out = ['<', self._env_top] + e + ['>\n'] + \ | |||||
| self.out + \ | |||||
| [self._env_bot] | |||||
| if self.encoding != None: | |||||
| self.out.insert(0, self._xml_enc_top % self.encoding) | |||||
| return ''.join(self.out).encode(self.encoding) | |||||
| self.out.insert(0, self._xml_top) | |||||
| return ''.join(self.out) | |||||
| def gentag(self): | |||||
| if Config.debug: print "In gentag." | |||||
| self.tcounter += 1 | |||||
| return "v%d" % self.tcounter | |||||
| def genns(self, ns_map, nsURI): | |||||
| if nsURI == None: | |||||
| return ('', '') | |||||
| if type(nsURI) == TupleType: # already a tuple | |||||
| if len(nsURI) == 2: | |||||
| ns, nsURI = nsURI | |||||
| else: | |||||
| ns, nsURI = None, nsURI[0] | |||||
| else: | |||||
| ns = None | |||||
| if ns_map.has_key(nsURI): | |||||
| return (ns_map[nsURI] + ':', '') | |||||
| if self._env_ns.has_key(nsURI): | |||||
| ns = self.envns[nsURI] = ns_map[nsURI] = self._env_ns[nsURI] | |||||
| return (ns + ':', '') | |||||
| if not ns: | |||||
| ns = "ns%d" % self.ncounter | |||||
| self.ncounter += 1 | |||||
| ns_map[nsURI] = ns | |||||
| if self.config.buildWithNamespacePrefix: | |||||
| return (ns + ':', ' xmlns:%s="%s"' % (ns, nsURI)) | |||||
| else: | |||||
| return ('', ' xmlns="%s"' % (nsURI)) | |||||
| def genroot(self, ns_map): | |||||
| if self.noroot: | |||||
| return '' | |||||
| if self.depth != 2: | |||||
| return '' | |||||
| ns, n = self.genns(ns_map, NS.ENC) | |||||
| return ' %sroot="%d"%s' % (ns, not self.multis, n) | |||||
| # checkref checks an element to see if it needs to be encoded as a | |||||
| # multi-reference element or not. If it returns None, the element has | |||||
| # been handled and the caller can continue with subsequent elements. | |||||
| # If it returns a string, the string should be included in the opening | |||||
| # tag of the marshaled element. | |||||
| def checkref(self, obj, tag, ns_map): | |||||
| if self.depth < 2: | |||||
| return '' | |||||
| if not self.ids.has_key(id(obj)): | |||||
| n = self.ids[id(obj)] = self.icounter | |||||
| self.icounter = n + 1 | |||||
| if self.use_refs == 0: | |||||
| return '' | |||||
| if self.depth == 2: | |||||
| return ' id="i%d"' % n | |||||
| self.multirefs.append((obj, tag)) | |||||
| else: | |||||
| if self.use_refs == 0: | |||||
| raise RecursionError, "Cannot serialize recursive object" | |||||
| n = self.ids[id(obj)] | |||||
| if self.multis and self.depth == 2: | |||||
| return ' id="i%d"' % n | |||||
| self.out.append('<%s href="#i%d"%s/>\n' % | |||||
| (tag, n, self.genroot(ns_map))) | |||||
| return None | |||||
| # dumpers | |||||
| def dump(self, obj, tag = None, typed = 1, ns_map = {}): | |||||
| if Config.debug: print "In dump.", "obj=", obj | |||||
| ns_map = ns_map.copy() | |||||
| self.depth += 1 | |||||
| if type(tag) not in (NoneType, StringType, UnicodeType): | |||||
| raise KeyError, "tag must be a string or None" | |||||
| try: | |||||
| meth = getattr(self, "dump_" + type(obj).__name__) | |||||
| except AttributeError: | |||||
| if type(obj) == LongType: | |||||
| obj_type = "integer" | |||||
| elif pythonHasBooleanType and type(obj) == BooleanType: | |||||
| obj_type = "boolean" | |||||
| else: | |||||
| obj_type = type(obj).__name__ | |||||
| self.out.append(self.dumper(None, obj_type, obj, tag, typed, | |||||
| ns_map, self.genroot(ns_map))) | |||||
| else: | |||||
| meth(obj, tag, typed, ns_map) | |||||
| self.depth -= 1 | |||||
| # generic dumper | |||||
| def dumper(self, nsURI, obj_type, obj, tag, typed = 1, ns_map = {}, | |||||
| rootattr = '', id = '', | |||||
| xml = '<%(tag)s%(type)s%(id)s%(attrs)s%(root)s>%(data)s</%(tag)s>\n'): | |||||
| if Config.debug: print "In dumper." | |||||
| if nsURI == None: | |||||
| nsURI = self.config.typesNamespaceURI | |||||
| tag = tag or self.gentag() | |||||
| tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding | |||||
| a = n = t = '' | |||||
| if typed and obj_type: | |||||
| ns, n = self.genns(ns_map, nsURI) | |||||
| ins = self.genns(ns_map, self.config.schemaNamespaceURI)[0] | |||||
| t = ' %stype="%s%s"%s' % (ins, ns, obj_type, n) | |||||
| try: a = obj._marshalAttrs(ns_map, self) | |||||
| except: pass | |||||
| try: data = obj._marshalData() | |||||
| except: | |||||
| if (obj_type != "string"): # strings are already encoded | |||||
| data = cgi.escape(str(obj)) | |||||
| else: | |||||
| data = obj | |||||
| return xml % {"tag": tag, "type": t, "data": data, "root": rootattr, | |||||
| "id": id, "attrs": a} | |||||
| def dump_float(self, obj, tag, typed = 1, ns_map = {}): | |||||
| if Config.debug: print "In dump_float." | |||||
| tag = tag or self.gentag() | |||||
| tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding | |||||
| if Config.strict_range: | |||||
| doubleType(obj) | |||||
| if fpconst.isPosInf(obj): | |||||
| obj = "INF" | |||||
| elif fpconst.isNegInf(obj): | |||||
| obj = "-INF" | |||||
| elif fpconst.isNaN(obj): | |||||
| obj = "NaN" | |||||
| else: | |||||
| obj = str(obj) | |||||
| # Note: python 'float' is actually a SOAP 'double'. | |||||
| self.out.append(self.dumper(None, "double", obj, tag, typed, ns_map, | |||||
| self.genroot(ns_map))) | |||||
| def dump_string(self, obj, tag, typed = 0, ns_map = {}): | |||||
| if Config.debug: print "In dump_string." | |||||
| tag = tag or self.gentag() | |||||
| tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding | |||||
| id = self.checkref(obj, tag, ns_map) | |||||
| if id == None: | |||||
| return | |||||
| try: data = obj._marshalData() | |||||
| except: data = obj | |||||
| self.out.append(self.dumper(None, "string", cgi.escape(data), tag, | |||||
| typed, ns_map, self.genroot(ns_map), id)) | |||||
| dump_str = dump_string # For Python 2.2+ | |||||
| dump_unicode = dump_string | |||||
| def dump_None(self, obj, tag, typed = 0, ns_map = {}): | |||||
| if Config.debug: print "In dump_None." | |||||
| tag = tag or self.gentag() | |||||
| tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding | |||||
| ns = self.genns(ns_map, self.config.schemaNamespaceURI)[0] | |||||
| self.out.append('<%s %snull="1"%s/>\n' % | |||||
| (tag, ns, self.genroot(ns_map))) | |||||
| dump_NoneType = dump_None # For Python 2.2+ | |||||
| def dump_list(self, obj, tag, typed = 1, ns_map = {}): | |||||
| if Config.debug: print "In dump_list.", "obj=", obj | |||||
| tag = tag or self.gentag() | |||||
| tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding | |||||
| if type(obj) == InstanceType: | |||||
| data = obj.data | |||||
| else: | |||||
| data = obj | |||||
| id = self.checkref(obj, tag, ns_map) | |||||
| if id == None: | |||||
| return | |||||
| try: | |||||
| sample = data[0] | |||||
| empty = 0 | |||||
| except: | |||||
| # preserve type if present | |||||
| if getattr(obj,"_typed",None) and getattr(obj,"_type",None): | |||||
| if getattr(obj, "_complexType", None): | |||||
| sample = typedArrayType(typed=obj._type, | |||||
| complexType = obj._complexType) | |||||
| sample._typename = obj._type | |||||
| obj._ns = NS.URN | |||||
| else: | |||||
| sample = typedArrayType(typed=obj._type) | |||||
| else: | |||||
| sample = structType() | |||||
| empty = 1 | |||||
| # First scan list to see if all are the same type | |||||
| same_type = 1 | |||||
| if not empty: | |||||
| for i in data[1:]: | |||||
| if type(sample) != type(i) or \ | |||||
| (type(sample) == InstanceType and \ | |||||
| sample.__class__ != i.__class__): | |||||
| same_type = 0 | |||||
| break | |||||
| ndecl = '' | |||||
| if same_type: | |||||
| if (isinstance(sample, structType)) or \ | |||||
| type(sample) == DictType or \ | |||||
| (isinstance(sample, anyType) and \ | |||||
| (getattr(sample, "_complexType", None) and \ | |||||
| sample._complexType)): # force to urn struct | |||||
| try: | |||||
| tns = obj._ns or NS.URN | |||||
| except: | |||||
| tns = NS.URN | |||||
| ns, ndecl = self.genns(ns_map, tns) | |||||
| try: | |||||
| typename = sample._typename | |||||
| except: | |||||
| typename = "SOAPStruct" | |||||
| t = ns + typename | |||||
| elif isinstance(sample, anyType): | |||||
| ns = sample._validNamespaceURI(self.config.typesNamespaceURI, | |||||
| self.config.strictNamespaces) | |||||
| if ns: | |||||
| ns, ndecl = self.genns(ns_map, ns) | |||||
| t = ns + sample._type | |||||
| else: | |||||
| t = 'ur-type' | |||||
| else: | |||||
| typename = type(sample).__name__ | |||||
| # For Python 2.2+ | |||||
| if type(sample) == StringType: typename = 'string' | |||||
| # HACK: python 'float' is actually a SOAP 'double'. | |||||
| if typename=="float": typename="double" | |||||
| t = self.genns(ns_map, self.config.typesNamespaceURI)[0] + \ | |||||
| typename | |||||
| else: | |||||
| t = self.genns(ns_map, self.config.typesNamespaceURI)[0] + \ | |||||
| "ur-type" | |||||
| try: a = obj._marshalAttrs(ns_map, self) | |||||
| except: a = '' | |||||
| ens, edecl = self.genns(ns_map, NS.ENC) | |||||
| ins, idecl = self.genns(ns_map, self.config.schemaNamespaceURI) | |||||
| self.out.append( | |||||
| '<%s %sarrayType="%s[%d]" %stype="%sArray"%s%s%s%s%s%s>\n' % | |||||
| (tag, ens, t, len(data), ins, ens, ndecl, edecl, idecl, | |||||
| self.genroot(ns_map), id, a)) | |||||
| typed = not same_type | |||||
| try: elemsname = obj._elemsname | |||||
| except: elemsname = "item" | |||||
| for i in data: | |||||
| self.dump(i, elemsname, typed, ns_map) | |||||
| self.out.append('</%s>\n' % tag) | |||||
| dump_tuple = dump_list | |||||
| def dump_dictionary(self, obj, tag, typed = 1, ns_map = {}): | |||||
| if Config.debug: print "In dump_dictionary." | |||||
| tag = tag or self.gentag() | |||||
| tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding | |||||
| id = self.checkref(obj, tag, ns_map) | |||||
| if id == None: | |||||
| return | |||||
| try: a = obj._marshalAttrs(ns_map, self) | |||||
| except: a = '' | |||||
| self.out.append('<%s%s%s%s>\n' % | |||||
| (tag, id, a, self.genroot(ns_map))) | |||||
| for (k, v) in obj.items(): | |||||
| if k[0] != "_": | |||||
| self.dump(v, k, 1, ns_map) | |||||
| self.out.append('</%s>\n' % tag) | |||||
| dump_dict = dump_dictionary # For Python 2.2+ | |||||
| def dump_instance(self, obj, tag, typed = 1, ns_map = {}): | |||||
| if Config.debug: print "In dump_instance.", "obj=", obj, "tag=", tag | |||||
| if not tag: | |||||
| # If it has a name use it. | |||||
| if isinstance(obj, anyType) and obj._name: | |||||
| tag = obj._name | |||||
| else: | |||||
| tag = self.gentag() | |||||
| tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding | |||||
| if isinstance(obj, arrayType): # Array | |||||
| self.dump_list(obj, tag, typed, ns_map) | |||||
| return | |||||
| if isinstance(obj, faultType): # Fault | |||||
| cns, cdecl = self.genns(ns_map, NS.ENC) | |||||
| vns, vdecl = self.genns(ns_map, NS.ENV) | |||||
| self.out.append('''<%sFault %sroot="1"%s%s> | |||||
| <faultcode>%s</faultcode> | |||||
| <faultstring>%s</faultstring> | |||||
| ''' % (vns, cns, vdecl, cdecl, obj.faultcode, obj.faultstring)) | |||||
| if hasattr(obj, "detail"): | |||||
| self.dump(obj.detail, "detail", typed, ns_map) | |||||
| self.out.append("</%sFault>\n" % vns) | |||||
| return | |||||
| r = self.genroot(ns_map) | |||||
| try: a = obj._marshalAttrs(ns_map, self) | |||||
| except: a = '' | |||||
| if isinstance(obj, voidType): # void | |||||
| self.out.append("<%s%s%s></%s>\n" % (tag, a, r, tag)) | |||||
| return | |||||
| id = self.checkref(obj, tag, ns_map) | |||||
| if id == None: | |||||
| return | |||||
| if isinstance(obj, structType): | |||||
| # Check for namespace | |||||
| ndecl = '' | |||||
| ns = obj._validNamespaceURI(self.config.typesNamespaceURI, | |||||
| self.config.strictNamespaces) | |||||
| if ns: | |||||
| ns, ndecl = self.genns(ns_map, ns) | |||||
| tag = ns + tag | |||||
| self.out.append("<%s%s%s%s%s>\n" % (tag, ndecl, id, a, r)) | |||||
| keylist = obj.__dict__.keys() | |||||
| # first write out items with order information | |||||
| if hasattr(obj, '_keyord'): | |||||
| for i in range(len(obj._keyord)): | |||||
| self.dump(obj._aslist(i), obj._keyord[i], 1, ns_map) | |||||
| keylist.remove(obj._keyord[i]) | |||||
| # now write out the rest | |||||
| for k in keylist: | |||||
| if (k[0] != "_"): | |||||
| self.dump(getattr(obj,k), k, 1, ns_map) | |||||
| if isinstance(obj, bodyType): | |||||
| self.multis = 1 | |||||
| for v, k in self.multirefs: | |||||
| self.dump(v, k, typed = typed, ns_map = ns_map) | |||||
| self.out.append('</%s>\n' % tag) | |||||
| elif isinstance(obj, anyType): | |||||
| t = '' | |||||
| if typed: | |||||
| ns = obj._validNamespaceURI(self.config.typesNamespaceURI, | |||||
| self.config.strictNamespaces) | |||||
| if ns: | |||||
| ons, ondecl = self.genns(ns_map, ns) | |||||
| ins, indecl = self.genns(ns_map, | |||||
| self.config.schemaNamespaceURI) | |||||
| t = ' %stype="%s%s"%s%s' % \ | |||||
| (ins, ons, obj._type, ondecl, indecl) | |||||
| self.out.append('<%s%s%s%s%s>%s</%s>\n' % | |||||
| (tag, t, id, a, r, obj._marshalData(), tag)) | |||||
| else: # Some Class | |||||
| self.out.append('<%s%s%s>\n' % (tag, id, r)) | |||||
| for (k, v) in obj.__dict__.items(): | |||||
| if k[0] != "_": | |||||
| self.dump(v, k, 1, ns_map) | |||||
| self.out.append('</%s>\n' % tag) | |||||
| ################################################################################ | |||||
| # SOAPBuilder's more public interface | |||||
| ################################################################################ | |||||
| def buildSOAP(args=(), kw={}, method=None, namespace=None, header=None, | |||||
| methodattrs=None,envelope=1,encoding='UTF-8',config=Config,noroot = 0): | |||||
| t = SOAPBuilder(args=args,kw=kw, method=method, namespace=namespace, | |||||
| header=header, methodattrs=methodattrs,envelope=envelope, | |||||
| encoding=encoding, config=config,noroot=noroot) | |||||
| return t.build() | |||||
| @@ -0,0 +1,178 @@ | |||||
| """ | |||||
| ################################################################################ | |||||
| # Copyright (c) 2003, Pfizer | |||||
| # Copyright (c) 2001, Cayce Ullman. | |||||
| # Copyright (c) 2001, Brian Matthews. | |||||
| # | |||||
| # All rights reserved. | |||||
| # | |||||
| # Redistribution and use in source and binary forms, with or without | |||||
| # modification, are permitted provided that the following conditions are met: | |||||
| # Redistributions of source code must retain the above copyright notice, this | |||||
| # list of conditions and the following disclaimer. | |||||
| # | |||||
| # Redistributions in binary form must reproduce the above copyright notice, | |||||
| # this list of conditions and the following disclaimer in the documentation | |||||
| # and/or other materials provided with the distribution. | |||||
| # | |||||
| # Neither the name of actzero, inc. nor the names of its contributors may | |||||
| # be used to endorse or promote products derived from this software without | |||||
| # specific prior written permission. | |||||
| # | |||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||||
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||
| # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR | |||||
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |||||
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
| # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||||
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| # | |||||
| ################################################################################ | |||||
| """ | |||||
| ident = '$Id: Utilities.py,v 1.4 2004/01/31 04:20:06 warnes Exp $' | |||||
| from version import __version__ | |||||
| import exceptions | |||||
| import copy | |||||
| import re | |||||
| import string | |||||
| import sys | |||||
| from types import * | |||||
| # SOAPpy modules | |||||
| from Errors import * | |||||
| ################################################################################ | |||||
| # Utility infielders | |||||
| ################################################################################ | |||||
| def collapseWhiteSpace(s): | |||||
| return re.sub('\s+', ' ', s).strip() | |||||
| def decodeHexString(data): | |||||
| conv = { | |||||
| '0': 0x0, '1': 0x1, '2': 0x2, '3': 0x3, '4': 0x4, | |||||
| '5': 0x5, '6': 0x6, '7': 0x7, '8': 0x8, '9': 0x9, | |||||
| 'a': 0xa, 'b': 0xb, 'c': 0xc, 'd': 0xd, 'e': 0xe, | |||||
| 'f': 0xf, | |||||
| 'A': 0xa, 'B': 0xb, 'C': 0xc, 'D': 0xd, 'E': 0xe, | |||||
| 'F': 0xf, | |||||
| } | |||||
| ws = string.whitespace | |||||
| bin = '' | |||||
| i = 0 | |||||
| while i < len(data): | |||||
| if data[i] not in ws: | |||||
| break | |||||
| i += 1 | |||||
| low = 0 | |||||
| while i < len(data): | |||||
| c = data[i] | |||||
| if c in string.whitespace: | |||||
| break | |||||
| try: | |||||
| c = conv[c] | |||||
| except KeyError: | |||||
| raise ValueError, \ | |||||
| "invalid hex string character `%s'" % c | |||||
| if low: | |||||
| bin += chr(high * 16 + c) | |||||
| low = 0 | |||||
| else: | |||||
| high = c | |||||
| low = 1 | |||||
| i += 1 | |||||
| if low: | |||||
| raise ValueError, "invalid hex string length" | |||||
| while i < len(data): | |||||
| if data[i] not in string.whitespace: | |||||
| raise ValueError, \ | |||||
| "invalid hex string character `%s'" % c | |||||
| i += 1 | |||||
| return bin | |||||
| def encodeHexString(data): | |||||
| h = '' | |||||
| for i in data: | |||||
| h += "%02X" % ord(i) | |||||
| return h | |||||
| def leapMonth(year, month): | |||||
| return month == 2 and \ | |||||
| year % 4 == 0 and \ | |||||
| (year % 100 != 0 or year % 400 == 0) | |||||
| def cleanDate(d, first = 0): | |||||
| ranges = (None, (1, 12), (1, 31), (0, 23), (0, 59), (0, 61)) | |||||
| months = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) | |||||
| names = ('year', 'month', 'day', 'hours', 'minutes', 'seconds') | |||||
| if len(d) != 6: | |||||
| raise ValueError, "date must have 6 elements" | |||||
| for i in range(first, 6): | |||||
| s = d[i] | |||||
| if type(s) == FloatType: | |||||
| if i < 5: | |||||
| try: | |||||
| s = int(s) | |||||
| except OverflowError: | |||||
| if i > 0: | |||||
| raise | |||||
| s = long(s) | |||||
| if s != d[i]: | |||||
| raise ValueError, "%s must be integral" % names[i] | |||||
| d[i] = s | |||||
| elif type(s) == LongType: | |||||
| try: s = int(s) | |||||
| except: pass | |||||
| elif type(s) != IntType: | |||||
| raise TypeError, "%s isn't a valid type" % names[i] | |||||
| if i == first and s < 0: | |||||
| continue | |||||
| if ranges[i] != None and \ | |||||
| (s < ranges[i][0] or ranges[i][1] < s): | |||||
| raise ValueError, "%s out of range" % names[i] | |||||
| if first < 6 and d[5] >= 61: | |||||
| raise ValueError, "seconds out of range" | |||||
| if first < 2: | |||||
| leap = first < 1 and leapMonth(d[0], d[1]) | |||||
| if d[2] > months[d[1]] + leap: | |||||
| raise ValueError, "day out of range" | |||||
| def debugHeader(title): | |||||
| s = '*** ' + title + ' ' | |||||
| print s + ('*' * (72 - len(s))) | |||||
| def debugFooter(title): | |||||
| print '*' * 72 | |||||
| sys.stdout.flush() | |||||
| @@ -0,0 +1,15 @@ | |||||
| ident = '$Id: __init__.py,v 1.9 2004/01/31 04:20:06 warnes Exp $' | |||||
| from version import __version__ | |||||
| from Client import * | |||||
| from Config import * | |||||
| from Errors import * | |||||
| from NS import * | |||||
| from Parser import * | |||||
| from SOAPBuilder import * | |||||
| from Server import * | |||||
| from Types import * | |||||
| from Utilities import * | |||||
| import wstools | |||||
| import WSDL | |||||
| @@ -0,0 +1,2 @@ | |||||
| __version__="0.11.6" | |||||
| @@ -0,0 +1,92 @@ | |||||
| #! /usr/bin/env python | |||||
| """Namespace module, so you don't need PyXML | |||||
| """ | |||||
| try: | |||||
| from xml.ns import SOAP, SCHEMA, WSDL, XMLNS, DSIG, ENCRYPTION | |||||
| except: | |||||
| class SOAP: | |||||
| ENV = "http://schemas.xmlsoap.org/soap/envelope/" | |||||
| ENC = "http://schemas.xmlsoap.org/soap/encoding/" | |||||
| ACTOR_NEXT = "http://schemas.xmlsoap.org/soap/actor/next" | |||||
| class SCHEMA: | |||||
| XSD1 = "http://www.w3.org/1999/XMLSchema" | |||||
| XSD2 = "http://www.w3.org/2000/10/XMLSchema" | |||||
| XSD3 = "http://www.w3.org/2001/XMLSchema" | |||||
| XSD_LIST = [ XSD1, XSD2, XSD3 ] | |||||
| XSI1 = "http://www.w3.org/1999/XMLSchema-instance" | |||||
| XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance" | |||||
| XSI3 = "http://www.w3.org/2001/XMLSchema-instance" | |||||
| XSI_LIST = [ XSI1, XSI2, XSI3 ] | |||||
| BASE = XSD3 | |||||
| class WSDL: | |||||
| BASE = "http://schemas.xmlsoap.org/wsdl/" | |||||
| BIND_HTTP = "http://schemas.xmlsoap.org/wsdl/http/" | |||||
| BIND_MIME = "http://schemas.xmlsoap.org/wsdl/mime/" | |||||
| BIND_SOAP = "http://schemas.xmlsoap.org/wsdl/soap/" | |||||
| class XMLNS: | |||||
| BASE = "http://www.w3.org/2000/xmlns/" | |||||
| XML = "http://www.w3.org/XML/1998/namespace" | |||||
| HTML = "http://www.w3.org/TR/REC-html40" | |||||
| class DSIG: | |||||
| BASE = "http://www.w3.org/2000/09/xmldsig#" | |||||
| C14N = "http://www.w3.org/TR/2000/CR-xml-c14n-20010315" | |||||
| C14N_COMM = "http://www.w3.org/TR/2000/CR-xml-c14n-20010315#WithComments" | |||||
| C14N_EXCL = "http://www.w3.org/2001/10/xml-exc-c14n#" | |||||
| DIGEST_MD2 = "http://www.w3.org/2000/09/xmldsig#md2" | |||||
| DIGEST_MD5 = "http://www.w3.org/2000/09/xmldsig#md5" | |||||
| DIGEST_SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1" | |||||
| ENC_BASE64 = "http://www.w3.org/2000/09/xmldsig#base64" | |||||
| ENVELOPED = "http://www.w3.org/2000/09/xmldsig#enveloped-signature" | |||||
| HMAC_SHA1 = "http://www.w3.org/2000/09/xmldsig#hmac-sha1" | |||||
| SIG_DSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#dsa-sha1" | |||||
| SIG_RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" | |||||
| XPATH = "http://www.w3.org/TR/1999/REC-xpath-19991116" | |||||
| XSLT = "http://www.w3.org/TR/1999/REC-xslt-19991116" | |||||
| class ENCRYPTION: | |||||
| BASE = "http://www.w3.org/2001/04/xmlenc#" | |||||
| BLOCK_3DES = "http://www.w3.org/2001/04/xmlenc#des-cbc" | |||||
| BLOCK_AES128 = "http://www.w3.org/2001/04/xmlenc#aes128-cbc" | |||||
| BLOCK_AES192 = "http://www.w3.org/2001/04/xmlenc#aes192-cbc" | |||||
| BLOCK_AES256 = "http://www.w3.org/2001/04/xmlenc#aes256-cbc" | |||||
| DIGEST_RIPEMD160 = "http://www.w3.org/2001/04/xmlenc#ripemd160" | |||||
| DIGEST_SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256" | |||||
| DIGEST_SHA512 = "http://www.w3.org/2001/04/xmlenc#sha512" | |||||
| KA_DH = "http://www.w3.org/2001/04/xmlenc#dh" | |||||
| KT_RSA_1_5 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5" | |||||
| KT_RSA_OAEP = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" | |||||
| STREAM_ARCFOUR = "http://www.w3.org/2001/04/xmlenc#arcfour" | |||||
| WRAP_3DES = "http://www.w3.org/2001/04/xmlenc#kw-3des" | |||||
| WRAP_AES128 = "http://www.w3.org/2001/04/xmlenc#kw-aes128" | |||||
| WRAP_AES192 = "http://www.w3.org/2001/04/xmlenc#kw-aes192" | |||||
| WRAP_AES256 = "http://www.w3.org/2001/04/xmlenc#kw-aes256" | |||||
| class WSSE: | |||||
| BASE = "http://schemas.xmlsoap.org/ws/2002/04/secext" | |||||
| class WSU: | |||||
| BASE = "http://schemas.xmlsoap.org/ws/2002/04/utility" | |||||
| UTILITY = "http://schemas.xmlsoap.org/ws/2002/07/utility" | |||||
| class WSR: | |||||
| PROPERTIES = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties" | |||||
| LIFETIME = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime" | |||||
| class WSA: | |||||
| ADDRESS = "http://schemas.xmlsoap.org/ws/2003/03/addressing" | |||||
| ADDRESS2004 = "http://schemas.xmlsoap.org/ws/2004/03/addressing" | |||||
| ANONYMOUS = "%s/role/anonymous" %ADDRESS | |||||
| ANONYMOUS2004 = "%s/role/anonymous" %ADDRESS2004 | |||||
| FAULT = "http://schemas.xmlsoap.org/ws/2004/03/addressing/fault" | |||||
| class WSP: | |||||
| POLICY = "http://schemas.xmlsoap.org/ws/2002/12/policy" | |||||
| @@ -0,0 +1,179 @@ | |||||
| """Based on code from timeout_socket.py, with some tweaks for compatibility. | |||||
| These tweaks should really be rolled back into timeout_socket, but it's | |||||
| not totally clear who is maintaining it at this point. In the meantime, | |||||
| we'll use a different module name for our tweaked version to avoid any | |||||
| confusion. | |||||
| The original timeout_socket is by: | |||||
| Scott Cotton <scott@chronis.pobox.com> | |||||
| Lloyd Zusman <ljz@asfast.com> | |||||
| Phil Mayes <pmayes@olivebr.com> | |||||
| Piers Lauder <piers@cs.su.oz.au> | |||||
| Radovan Garabik <garabik@melkor.dnp.fmph.uniba.sk> | |||||
| """ | |||||
| ident = "$Id: TimeoutSocket.py,v 1.2 2003/05/20 21:10:12 warnes Exp $" | |||||
| import string, socket, select, errno | |||||
| WSAEINVAL = getattr(errno, 'WSAEINVAL', 10022) | |||||
| class TimeoutSocket: | |||||
| """A socket imposter that supports timeout limits.""" | |||||
| def __init__(self, timeout=20, sock=None): | |||||
| self.timeout = float(timeout) | |||||
| self.inbuf = '' | |||||
| if sock is None: | |||||
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |||||
| self.sock = sock | |||||
| self.sock.setblocking(0) | |||||
| self._rbuf = '' | |||||
| self._wbuf = '' | |||||
| def __getattr__(self, name): | |||||
| # Delegate to real socket attributes. | |||||
| return getattr(self.sock, name) | |||||
| def connect(self, *addr): | |||||
| timeout = self.timeout | |||||
| sock = self.sock | |||||
| try: | |||||
| # Non-blocking mode | |||||
| sock.setblocking(0) | |||||
| apply(sock.connect, addr) | |||||
| sock.setblocking(timeout != 0) | |||||
| return 1 | |||||
| except socket.error,why: | |||||
| if not timeout: | |||||
| raise | |||||
| sock.setblocking(1) | |||||
| if len(why.args) == 1: | |||||
| code = 0 | |||||
| else: | |||||
| code, why = why | |||||
| if code not in ( | |||||
| errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK | |||||
| ): | |||||
| raise | |||||
| r,w,e = select.select([],[sock],[],timeout) | |||||
| if w: | |||||
| try: | |||||
| apply(sock.connect, addr) | |||||
| return 1 | |||||
| except socket.error,why: | |||||
| if len(why.args) == 1: | |||||
| code = 0 | |||||
| else: | |||||
| code, why = why | |||||
| if code in (errno.EISCONN, WSAEINVAL): | |||||
| return 1 | |||||
| raise | |||||
| raise TimeoutError('socket connect() timeout.') | |||||
| def send(self, data, flags=0): | |||||
| total = len(data) | |||||
| next = 0 | |||||
| while 1: | |||||
| r, w, e = select.select([],[self.sock], [], self.timeout) | |||||
| if w: | |||||
| buff = data[next:next + 8192] | |||||
| sent = self.sock.send(buff, flags) | |||||
| next = next + sent | |||||
| if next == total: | |||||
| return total | |||||
| continue | |||||
| raise TimeoutError('socket send() timeout.') | |||||
| def recv(self, amt, flags=0): | |||||
| if select.select([self.sock], [], [], self.timeout)[0]: | |||||
| return self.sock.recv(amt, flags) | |||||
| raise TimeoutError('socket recv() timeout.') | |||||
| buffsize = 4096 | |||||
| handles = 1 | |||||
| def makefile(self, mode="r", buffsize=-1): | |||||
| self.handles = self.handles + 1 | |||||
| self.mode = mode | |||||
| return self | |||||
| def close(self): | |||||
| self.handles = self.handles - 1 | |||||
| if self.handles == 0 and self.sock.fileno() >= 0: | |||||
| self.sock.close() | |||||
| def read(self, n=-1): | |||||
| if not isinstance(n, type(1)): | |||||
| n = -1 | |||||
| if n >= 0: | |||||
| k = len(self._rbuf) | |||||
| if n <= k: | |||||
| data = self._rbuf[:n] | |||||
| self._rbuf = self._rbuf[n:] | |||||
| return data | |||||
| n = n - k | |||||
| L = [self._rbuf] | |||||
| self._rbuf = "" | |||||
| while n > 0: | |||||
| new = self.recv(max(n, self.buffsize)) | |||||
| if not new: break | |||||
| k = len(new) | |||||
| if k > n: | |||||
| L.append(new[:n]) | |||||
| self._rbuf = new[n:] | |||||
| break | |||||
| L.append(new) | |||||
| n = n - k | |||||
| return "".join(L) | |||||
| k = max(4096, self.buffsize) | |||||
| L = [self._rbuf] | |||||
| self._rbuf = "" | |||||
| while 1: | |||||
| new = self.recv(k) | |||||
| if not new: break | |||||
| L.append(new) | |||||
| k = min(k*2, 1024**2) | |||||
| return "".join(L) | |||||
| def readline(self, limit=-1): | |||||
| data = "" | |||||
| i = self._rbuf.find('\n') | |||||
| while i < 0 and not (0 < limit <= len(self._rbuf)): | |||||
| new = self.recv(self.buffsize) | |||||
| if not new: break | |||||
| i = new.find('\n') | |||||
| if i >= 0: i = i + len(self._rbuf) | |||||
| self._rbuf = self._rbuf + new | |||||
| if i < 0: i = len(self._rbuf) | |||||
| else: i = i+1 | |||||
| if 0 <= limit < len(self._rbuf): i = limit | |||||
| data, self._rbuf = self._rbuf[:i], self._rbuf[i:] | |||||
| return data | |||||
| def readlines(self, sizehint = 0): | |||||
| total = 0 | |||||
| list = [] | |||||
| while 1: | |||||
| line = self.readline() | |||||
| if not line: break | |||||
| list.append(line) | |||||
| total += len(line) | |||||
| if sizehint and total >= sizehint: | |||||
| break | |||||
| return list | |||||
| def writelines(self, list): | |||||
| self.send(''.join(list)) | |||||
| def write(self, data): | |||||
| self.send(data) | |||||
| def flush(self): | |||||
| pass | |||||
| class TimeoutError(Exception): | |||||
| pass | |||||
| @@ -0,0 +1,99 @@ | |||||
| """ | |||||
| A more or less complete user-defined wrapper around tuple objects. | |||||
| Adapted version of the standard library's UserList. | |||||
| Taken from Stefan Schwarzer's ftputil library, available at | |||||
| <http://www.ndh.net/home/sschwarzer/python/python_software.html>, and used under this license: | |||||
| Copyright (C) 1999, Stefan Schwarzer | |||||
| All rights reserved. | |||||
| Redistribution and use in source and binary forms, with or without | |||||
| modification, are permitted provided that the following conditions are | |||||
| met: | |||||
| - Redistributions of source code must retain the above copyright | |||||
| notice, this list of conditions and the following disclaimer. | |||||
| - Redistributions in binary form must reproduce the above copyright | |||||
| notice, this list of conditions and the following disclaimer in the | |||||
| documentation and/or other materials provided with the distribution. | |||||
| - Neither the name of the above author nor the names of the | |||||
| contributors to the software may be used to endorse or promote | |||||
| products derived from this software without specific prior written | |||||
| permission. | |||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||||
| ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR | |||||
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||||
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||||
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |||||
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |||||
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||||
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||||
| """ | |||||
| # $Id: UserTuple.py,v 1.1 2003/07/21 14:18:54 warnes Exp $ | |||||
| #XXX tuple instances (in Python 2.2) contain also: | |||||
| # __class__, __delattr__, __getattribute__, __hash__, __new__, | |||||
| # __reduce__, __setattr__, __str__ | |||||
| # What about these? | |||||
| class UserTuple: | |||||
| def __init__(self, inittuple=None): | |||||
| self.data = () | |||||
| if inittuple is not None: | |||||
| # XXX should this accept an arbitrary sequence? | |||||
| if type(inittuple) == type(self.data): | |||||
| self.data = inittuple | |||||
| elif isinstance(inittuple, UserTuple): | |||||
| # this results in | |||||
| # self.data is inittuple.data | |||||
| # but that's ok for tuples because they are | |||||
| # immutable. (Builtin tuples behave the same.) | |||||
| self.data = inittuple.data[:] | |||||
| else: | |||||
| # the same applies here; (t is tuple(t)) == 1 | |||||
| self.data = tuple(inittuple) | |||||
| def __repr__(self): return repr(self.data) | |||||
| def __lt__(self, other): return self.data < self.__cast(other) | |||||
| def __le__(self, other): return self.data <= self.__cast(other) | |||||
| def __eq__(self, other): return self.data == self.__cast(other) | |||||
| def __ne__(self, other): return self.data != self.__cast(other) | |||||
| def __gt__(self, other): return self.data > self.__cast(other) | |||||
| def __ge__(self, other): return self.data >= self.__cast(other) | |||||
| def __cast(self, other): | |||||
| if isinstance(other, UserTuple): return other.data | |||||
| else: return other | |||||
| def __cmp__(self, other): | |||||
| return cmp(self.data, self.__cast(other)) | |||||
| def __contains__(self, item): return item in self.data | |||||
| def __len__(self): return len(self.data) | |||||
| def __getitem__(self, i): return self.data[i] | |||||
| def __getslice__(self, i, j): | |||||
| i = max(i, 0); j = max(j, 0) | |||||
| return self.__class__(self.data[i:j]) | |||||
| def __add__(self, other): | |||||
| if isinstance(other, UserTuple): | |||||
| return self.__class__(self.data + other.data) | |||||
| elif isinstance(other, type(self.data)): | |||||
| return self.__class__(self.data + other) | |||||
| else: | |||||
| return self.__class__(self.data + tuple(other)) | |||||
| # dir( () ) contains no __radd__ (at least in Python 2.2) | |||||
| def __mul__(self, n): | |||||
| return self.__class__(self.data*n) | |||||
| __rmul__ = __mul__ | |||||
| @@ -0,0 +1,839 @@ | |||||
| # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |||||
| # | |||||
| # This software is subject to the provisions of the Zope Public License, | |||||
| # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |||||
| # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |||||
| # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |||||
| # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |||||
| # FOR A PARTICULAR PURPOSE. | |||||
| ident = "$Id: Utility.py,v 1.15 2004/04/29 01:40:49 boverhof Exp $" | |||||
| import types | |||||
| import string, httplib, smtplib, urllib, socket, weakref | |||||
| import xml.dom.minidom | |||||
| from string import join, strip, split | |||||
| from UserDict import UserDict | |||||
| from StringIO import StringIO | |||||
| from TimeoutSocket import TimeoutSocket, TimeoutError | |||||
| from urlparse import urlparse | |||||
| from httplib import HTTPConnection, HTTPSConnection | |||||
| from exceptions import Exception | |||||
| try: | |||||
| from xml.dom.ext import SplitQName | |||||
| except: | |||||
| def SplitQName(qname): | |||||
| '''SplitQName(qname) -> (string, string) | |||||
| Split Qualified Name into a tuple of len 2, consisting | |||||
| of the prefix and the local name. | |||||
| (prefix, localName) | |||||
| Special Cases: | |||||
| xmlns -- (localName, 'xmlns') | |||||
| None -- (None, localName) | |||||
| ''' | |||||
| l = qname.split(':') | |||||
| if len(l) == 1: | |||||
| l.insert(0, None) | |||||
| elif len(l) == 2: | |||||
| if l[0] == 'xmlns': | |||||
| l.reverse() | |||||
| else: | |||||
| return | |||||
| return tuple(l) | |||||
| class RecursionError(Exception): | |||||
| """Used to indicate a HTTP redirect recursion.""" | |||||
| pass | |||||
| class HTTPResponse: | |||||
| """Captures the information in an HTTP response message.""" | |||||
| def __init__(self, response): | |||||
| self.status = response.status | |||||
| self.reason = response.reason | |||||
| self.headers = response.msg | |||||
| self.body = response.read() or None | |||||
| response.close() | |||||
| class TimeoutHTTP(HTTPConnection): | |||||
| """A custom http connection object that supports socket timeout.""" | |||||
| def __init__(self, host, port=None, timeout=20): | |||||
| HTTPConnection.__init__(self, host, port) | |||||
| self.timeout = timeout | |||||
| def connect(self): | |||||
| self.sock = TimeoutSocket(self.timeout) | |||||
| self.sock.connect((self.host, self.port)) | |||||
| class TimeoutHTTPS(HTTPSConnection): | |||||
| """A custom https object that supports socket timeout. Note that this | |||||
| is not really complete. The builtin SSL support in the Python socket | |||||
| module requires a real socket (type) to be passed in to be hooked to | |||||
| SSL. That means our fake socket won't work and our timeout hacks are | |||||
| bypassed for send and recv calls. Since our hack _is_ in place at | |||||
| connect() time, it should at least provide some timeout protection.""" | |||||
| def __init__(self, host, port=None, timeout=20, **kwargs): | |||||
| HTTPSConnection.__init__(self, str(host), port, **kwargs) | |||||
| self.timeout = timeout | |||||
| def connect(self): | |||||
| sock = TimeoutSocket(self.timeout) | |||||
| sock.connect((self.host, self.port)) | |||||
| realsock = getattr(sock.sock, '_sock', sock.sock) | |||||
| ssl = socket.ssl(realsock, self.key_file, self.cert_file) | |||||
| self.sock = httplib.FakeSocket(sock, ssl) | |||||
| def urlopen(url, timeout=20, redirects=None): | |||||
| """A minimal urlopen replacement hack that supports timeouts for http. | |||||
| Note that this supports GET only.""" | |||||
| scheme, host, path, params, query, frag = urlparse(url) | |||||
| if not scheme in ('http', 'https'): | |||||
| return urllib.urlopen(url) | |||||
| if params: path = '%s;%s' % (path, params) | |||||
| if query: path = '%s?%s' % (path, query) | |||||
| if frag: path = '%s#%s' % (path, frag) | |||||
| if scheme == 'https': | |||||
| # If ssl is not compiled into Python, you will not get an exception | |||||
| # until a conn.endheaders() call. We need to know sooner, so use | |||||
| # getattr. | |||||
| if hasattr(socket, 'ssl'): | |||||
| conn = TimeoutHTTPS(host, None, timeout) | |||||
| else: | |||||
| import M2Crypto | |||||
| ctx = M2Crypto.SSL.Context() | |||||
| ctx.set_session_timeout(timeout) | |||||
| conn = M2Crypto.httpslib.HTTPSConnection(host, ssl_context=ctx) | |||||
| #conn.set_debuglevel(1) | |||||
| else: | |||||
| conn = TimeoutHTTP(host, None, timeout) | |||||
| conn.putrequest('GET', path) | |||||
| conn.putheader('Connection', 'close') | |||||
| conn.endheaders() | |||||
| response = None | |||||
| while 1: | |||||
| response = conn.getresponse() | |||||
| if response.status != 100: | |||||
| break | |||||
| conn._HTTPConnection__state = httplib._CS_REQ_SENT | |||||
| conn._HTTPConnection__response = None | |||||
| status = response.status | |||||
| # If we get an HTTP redirect, we will follow it automatically. | |||||
| if status >= 300 and status < 400: | |||||
| location = response.msg.getheader('location') | |||||
| if location is not None: | |||||
| response.close() | |||||
| if redirects is not None and redirects.has_key(location): | |||||
| raise RecursionError( | |||||
| 'Circular HTTP redirection detected.' | |||||
| ) | |||||
| if redirects is None: | |||||
| redirects = {} | |||||
| redirects[location] = 1 | |||||
| return urlopen(location, timeout, redirects) | |||||
| raise HTTPResponse(response) | |||||
| if not (status >= 200 and status < 300): | |||||
| raise HTTPResponse(response) | |||||
| body = StringIO(response.read()) | |||||
| response.close() | |||||
| return body | |||||
| class DOM: | |||||
| """The DOM singleton defines a number of XML related constants and | |||||
| provides a number of utility methods for DOM related tasks. It | |||||
| also provides some basic abstractions so that the rest of the | |||||
| package need not care about actual DOM implementation in use.""" | |||||
| # Namespace stuff related to the SOAP specification. | |||||
| NS_SOAP_ENV_1_1 = 'http://schemas.xmlsoap.org/soap/envelope/' | |||||
| NS_SOAP_ENC_1_1 = 'http://schemas.xmlsoap.org/soap/encoding/' | |||||
| NS_SOAP_ENV_1_2 = 'http://www.w3.org/2001/06/soap-envelope' | |||||
| NS_SOAP_ENC_1_2 = 'http://www.w3.org/2001/06/soap-encoding' | |||||
| NS_SOAP_ENV_ALL = (NS_SOAP_ENV_1_1, NS_SOAP_ENV_1_2) | |||||
| NS_SOAP_ENC_ALL = (NS_SOAP_ENC_1_1, NS_SOAP_ENC_1_2) | |||||
| NS_SOAP_ENV = NS_SOAP_ENV_1_1 | |||||
| NS_SOAP_ENC = NS_SOAP_ENC_1_1 | |||||
| _soap_uri_mapping = { | |||||
| NS_SOAP_ENV_1_1 : '1.1', | |||||
| NS_SOAP_ENV_1_2 : '1.2', | |||||
| } | |||||
| SOAP_ACTOR_NEXT_1_1 = 'http://schemas.xmlsoap.org/soap/actor/next' | |||||
| SOAP_ACTOR_NEXT_1_2 = 'http://www.w3.org/2001/06/soap-envelope/actor/next' | |||||
| SOAP_ACTOR_NEXT_ALL = (SOAP_ACTOR_NEXT_1_1, SOAP_ACTOR_NEXT_1_2) | |||||
| def SOAPUriToVersion(self, uri): | |||||
| """Return the SOAP version related to an envelope uri.""" | |||||
| value = self._soap_uri_mapping.get(uri) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP envelope uri: %s' % uri | |||||
| ) | |||||
| def GetSOAPEnvUri(self, version): | |||||
| """Return the appropriate SOAP envelope uri for a given | |||||
| human-friendly SOAP version string (e.g. '1.1').""" | |||||
| attrname = 'NS_SOAP_ENV_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attrname, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP version: %s' % version | |||||
| ) | |||||
| def GetSOAPEncUri(self, version): | |||||
| """Return the appropriate SOAP encoding uri for a given | |||||
| human-friendly SOAP version string (e.g. '1.1').""" | |||||
| attrname = 'NS_SOAP_ENC_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attrname, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP version: %s' % version | |||||
| ) | |||||
| def GetSOAPActorNextUri(self, version): | |||||
| """Return the right special next-actor uri for a given | |||||
| human-friendly SOAP version string (e.g. '1.1').""" | |||||
| attrname = 'SOAP_ACTOR_NEXT_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attrname, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP version: %s' % version | |||||
| ) | |||||
| # Namespace stuff related to XML Schema. | |||||
| NS_XSD_99 = 'http://www.w3.org/1999/XMLSchema' | |||||
| NS_XSI_99 = 'http://www.w3.org/1999/XMLSchema-instance' | |||||
| NS_XSD_00 = 'http://www.w3.org/2000/10/XMLSchema' | |||||
| NS_XSI_00 = 'http://www.w3.org/2000/10/XMLSchema-instance' | |||||
| NS_XSD_01 = 'http://www.w3.org/2001/XMLSchema' | |||||
| NS_XSI_01 = 'http://www.w3.org/2001/XMLSchema-instance' | |||||
| NS_XSD_ALL = (NS_XSD_99, NS_XSD_00, NS_XSD_01) | |||||
| NS_XSI_ALL = (NS_XSI_99, NS_XSI_00, NS_XSI_01) | |||||
| NS_XSD = NS_XSD_01 | |||||
| NS_XSI = NS_XSI_01 | |||||
| _xsd_uri_mapping = { | |||||
| NS_XSD_99 : NS_XSI_99, | |||||
| NS_XSD_00 : NS_XSI_00, | |||||
| NS_XSD_01 : NS_XSI_01, | |||||
| } | |||||
| for key, value in _xsd_uri_mapping.items(): | |||||
| _xsd_uri_mapping[value] = key | |||||
| def InstanceUriForSchemaUri(self, uri): | |||||
| """Return the appropriate matching XML Schema instance uri for | |||||
| the given XML Schema namespace uri.""" | |||||
| return self._xsd_uri_mapping.get(uri) | |||||
| def SchemaUriForInstanceUri(self, uri): | |||||
| """Return the appropriate matching XML Schema namespace uri for | |||||
| the given XML Schema instance namespace uri.""" | |||||
| return self._xsd_uri_mapping.get(uri) | |||||
| # Namespace stuff related to WSDL. | |||||
| NS_WSDL_1_1 = 'http://schemas.xmlsoap.org/wsdl/' | |||||
| NS_WSDL_ALL = (NS_WSDL_1_1,) | |||||
| NS_WSDL = NS_WSDL_1_1 | |||||
| NS_SOAP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/' | |||||
| NS_HTTP_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/http/' | |||||
| NS_MIME_BINDING_1_1 = 'http://schemas.xmlsoap.org/wsdl/mime/' | |||||
| NS_SOAP_BINDING_ALL = (NS_SOAP_BINDING_1_1,) | |||||
| NS_HTTP_BINDING_ALL = (NS_HTTP_BINDING_1_1,) | |||||
| NS_MIME_BINDING_ALL = (NS_MIME_BINDING_1_1,) | |||||
| NS_SOAP_BINDING = NS_SOAP_BINDING_1_1 | |||||
| NS_HTTP_BINDING = NS_HTTP_BINDING_1_1 | |||||
| NS_MIME_BINDING = NS_MIME_BINDING_1_1 | |||||
| NS_SOAP_HTTP_1_1 = 'http://schemas.xmlsoap.org/soap/http' | |||||
| NS_SOAP_HTTP_ALL = (NS_SOAP_HTTP_1_1,) | |||||
| NS_SOAP_HTTP = NS_SOAP_HTTP_1_1 | |||||
| _wsdl_uri_mapping = { | |||||
| NS_WSDL_1_1 : '1.1', | |||||
| } | |||||
| def WSDLUriToVersion(self, uri): | |||||
| """Return the WSDL version related to a WSDL namespace uri.""" | |||||
| value = self._wsdl_uri_mapping.get(uri) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported SOAP envelope uri: %s' % uri | |||||
| ) | |||||
| def GetWSDLUri(self, version): | |||||
| attr = 'NS_WSDL_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLSoapBindingUri(self, version): | |||||
| attr = 'NS_SOAP_BINDING_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLHttpBindingUri(self, version): | |||||
| attr = 'NS_HTTP_BINDING_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLMimeBindingUri(self, version): | |||||
| attr = 'NS_MIME_BINDING_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| def GetWSDLHttpTransportUri(self, version): | |||||
| attr = 'NS_SOAP_HTTP_%s' % join(split(version, '.'), '_') | |||||
| value = getattr(self, attr, None) | |||||
| if value is not None: | |||||
| return value | |||||
| raise ValueError( | |||||
| 'Unsupported WSDL version: %s' % version | |||||
| ) | |||||
| # Other xml namespace constants. | |||||
| NS_XMLNS = 'http://www.w3.org/2000/xmlns/' | |||||
| def isElement(self, node, name, nsuri=None): | |||||
| """Return true if the given node is an element with the given | |||||
| name and optional namespace uri.""" | |||||
| if node.nodeType != node.ELEMENT_NODE: | |||||
| return 0 | |||||
| return node.localName == name and \ | |||||
| (nsuri is None or self.nsUriMatch(node.namespaceURI, nsuri)) | |||||
| def getElement(self, node, name, nsuri=None, default=join): | |||||
| """Return the first child of node with a matching name and | |||||
| namespace uri, or the default if one is provided.""" | |||||
| nsmatch = self.nsUriMatch | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| for child in node.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| if ((child.localName == name or name is None) and | |||||
| (nsuri is None or nsmatch(child.namespaceURI, nsuri)) | |||||
| ): | |||||
| return child | |||||
| if default is not join: | |||||
| return default | |||||
| raise KeyError, name | |||||
| def getElementById(self, node, id, default=join): | |||||
| """Return the first child of node matching an id reference.""" | |||||
| attrget = self.getAttr | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| for child in node.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| if attrget(child, 'id') == id: | |||||
| return child | |||||
| if default is not join: | |||||
| return default | |||||
| raise KeyError, name | |||||
| def getMappingById(self, document, depth=None, element=None, | |||||
| mapping=None, level=1): | |||||
| """Create an id -> element mapping of those elements within a | |||||
| document that define an id attribute. The depth of the search | |||||
| may be controlled by using the (1-based) depth argument.""" | |||||
| if document is not None: | |||||
| element = document.documentElement | |||||
| mapping = {} | |||||
| attr = element._attrs.get('id', None) | |||||
| if attr is not None: | |||||
| mapping[attr.value] = element | |||||
| if depth is None or depth > level: | |||||
| level = level + 1 | |||||
| ELEMENT_NODE = element.ELEMENT_NODE | |||||
| for child in element.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| self.getMappingById(None, depth, child, mapping, level) | |||||
| return mapping | |||||
| def getElements(self, node, name, nsuri=None): | |||||
| """Return a sequence of the child elements of the given node that | |||||
| match the given name and optional namespace uri.""" | |||||
| nsmatch = self.nsUriMatch | |||||
| result = [] | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| for child in node.childNodes: | |||||
| if child.nodeType == ELEMENT_NODE: | |||||
| if ((child.localName == name or name is None) and ( | |||||
| (nsuri is None) or nsmatch(child.namespaceURI, nsuri))): | |||||
| result.append(child) | |||||
| return result | |||||
| def hasAttr(self, node, name, nsuri=None): | |||||
| """Return true if element has attribute with the given name and | |||||
| optional nsuri. If nsuri is not specified, returns true if an | |||||
| attribute exists with the given name with any namespace.""" | |||||
| if nsuri is None: | |||||
| if node.hasAttribute(name): | |||||
| return True | |||||
| return False | |||||
| return node.hasAttributeNS(nsuri, name) | |||||
| def getAttr(self, node, name, nsuri=None, default=join): | |||||
| """Return the value of the attribute named 'name' with the | |||||
| optional nsuri, or the default if one is specified. If | |||||
| nsuri is not specified, an attribute that matches the | |||||
| given name will be returned regardless of namespace.""" | |||||
| if nsuri is None: | |||||
| result = node._attrs.get(name, None) | |||||
| if result is None: | |||||
| for item in node._attrsNS.keys(): | |||||
| if item[1] == name: | |||||
| result = node._attrsNS[item] | |||||
| break | |||||
| else: | |||||
| result = node._attrsNS.get((nsuri, name), None) | |||||
| if result is not None: | |||||
| return result.value | |||||
| if default is not join: | |||||
| return default | |||||
| return '' | |||||
| def getAttrs(self, node): | |||||
| """Return a Collection of all attributes | |||||
| """ | |||||
| attrs = {} | |||||
| for k,v in node._attrs.items(): | |||||
| attrs[k] = v.value | |||||
| return attrs | |||||
| def getElementText(self, node, preserve_ws=None): | |||||
| """Return the text value of an xml element node. Leading and trailing | |||||
| whitespace is stripped from the value unless the preserve_ws flag | |||||
| is passed with a true value.""" | |||||
| result = [] | |||||
| for child in node.childNodes: | |||||
| nodetype = child.nodeType | |||||
| if nodetype == child.TEXT_NODE or \ | |||||
| nodetype == child.CDATA_SECTION_NODE: | |||||
| result.append(child.nodeValue) | |||||
| value = join(result, '') | |||||
| if preserve_ws is None: | |||||
| value = strip(value) | |||||
| return value | |||||
| def findNamespaceURI(self, prefix, node): | |||||
| """Find a namespace uri given a prefix and a context node.""" | |||||
| attrkey = (self.NS_XMLNS, prefix) | |||||
| DOCUMENT_NODE = node.DOCUMENT_NODE | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| while 1: | |||||
| if node.nodeType != ELEMENT_NODE: | |||||
| node = node.parentNode | |||||
| continue | |||||
| result = node._attrsNS.get(attrkey, None) | |||||
| if result is not None: | |||||
| return result.value | |||||
| if hasattr(node, '__imported__'): | |||||
| raise DOMException('Value for prefix %s not found.' % prefix) | |||||
| node = node.parentNode | |||||
| if node.nodeType == DOCUMENT_NODE: | |||||
| raise DOMException('Value for prefix %s not found.' % prefix) | |||||
| def findDefaultNS(self, node): | |||||
| """Return the current default namespace uri for the given node.""" | |||||
| attrkey = (self.NS_XMLNS, 'xmlns') | |||||
| DOCUMENT_NODE = node.DOCUMENT_NODE | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| while 1: | |||||
| if node.nodeType != ELEMENT_NODE: | |||||
| node = node.parentNode | |||||
| continue | |||||
| result = node._attrsNS.get(attrkey, None) | |||||
| if result is not None: | |||||
| return result.value | |||||
| if hasattr(node, '__imported__'): | |||||
| raise DOMException('Cannot determine default namespace.') | |||||
| node = node.parentNode | |||||
| if node.nodeType == DOCUMENT_NODE: | |||||
| raise DOMException('Cannot determine default namespace.') | |||||
| def findTargetNS(self, node): | |||||
| """Return the defined target namespace uri for the given node.""" | |||||
| attrget = self.getAttr | |||||
| attrkey = (self.NS_XMLNS, 'xmlns') | |||||
| DOCUMENT_NODE = node.DOCUMENT_NODE | |||||
| ELEMENT_NODE = node.ELEMENT_NODE | |||||
| while 1: | |||||
| if node.nodeType != ELEMENT_NODE: | |||||
| node = node.parentNode | |||||
| continue | |||||
| result = attrget(node, 'targetNamespace', default=None) | |||||
| if result is not None: | |||||
| return result | |||||
| node = node.parentNode | |||||
| if node.nodeType == DOCUMENT_NODE: | |||||
| raise DOMException('Cannot determine target namespace.') | |||||
| def getTypeRef(self, element): | |||||
| """Return (namespaceURI, name) for a type attribue of the given | |||||
| element, or None if the element does not have a type attribute.""" | |||||
| typeattr = self.getAttr(element, 'type', default=None) | |||||
| if typeattr is None: | |||||
| return None | |||||
| parts = typeattr.split(':', 1) | |||||
| if len(parts) == 2: | |||||
| nsuri = self.findNamespaceURI(parts[0], element) | |||||
| else: | |||||
| nsuri = self.findDefaultNS(element) | |||||
| return (nsuri, parts[1]) | |||||
| def importNode(self, document, node, deep=0): | |||||
| """Implements (well enough for our purposes) DOM node import.""" | |||||
| nodetype = node.nodeType | |||||
| if nodetype in (node.DOCUMENT_NODE, node.DOCUMENT_TYPE_NODE): | |||||
| raise DOMException('Illegal node type for importNode') | |||||
| if nodetype == node.ENTITY_REFERENCE_NODE: | |||||
| deep = 0 | |||||
| clone = node.cloneNode(deep) | |||||
| self._setOwnerDoc(document, clone) | |||||
| clone.__imported__ = 1 | |||||
| return clone | |||||
| def _setOwnerDoc(self, document, node): | |||||
| node.ownerDocument = document | |||||
| for child in node.childNodes: | |||||
| self._setOwnerDoc(document, child) | |||||
| def nsUriMatch(self, value, wanted, strict=0, tt=type(())): | |||||
| """Return a true value if two namespace uri values match.""" | |||||
| if value == wanted or (type(wanted) is tt) and value in wanted: | |||||
| return 1 | |||||
| if not strict: | |||||
| wanted = type(wanted) is tt and wanted or (wanted,) | |||||
| value = value[-1:] != '/' and value or value[:-1] | |||||
| for item in wanted: | |||||
| if item == value or item[:-1] == value: | |||||
| return 1 | |||||
| return 0 | |||||
| def createDocument(self, nsuri, qname, doctype=None): | |||||
| """Create a new writable DOM document object.""" | |||||
| impl = xml.dom.minidom.getDOMImplementation() | |||||
| return impl.createDocument(nsuri, qname, doctype) | |||||
| def loadDocument(self, data): | |||||
| """Load an xml file from a file-like object and return a DOM | |||||
| document instance.""" | |||||
| return xml.dom.minidom.parse(data) | |||||
| def loadFromURL(self, url): | |||||
| """Load an xml file from a URL and return a DOM document.""" | |||||
| file = urlopen(url) | |||||
| try: result = self.loadDocument(file) | |||||
| finally: file.close() | |||||
| return result | |||||
| class DOMException(Exception): | |||||
| pass | |||||
| DOM = DOM() | |||||
| class Collection(UserDict): | |||||
| """Helper class for maintaining ordered named collections.""" | |||||
| default = lambda self,k: k.name | |||||
| def __init__(self, parent, key=None): | |||||
| UserDict.__init__(self) | |||||
| self.parent = weakref.ref(parent) | |||||
| self.list = [] | |||||
| self._func = key or self.default | |||||
| def __getitem__(self, key): | |||||
| if type(key) is type(1): | |||||
| return self.list[key] | |||||
| return self.data[key] | |||||
| def __setitem__(self, key, item): | |||||
| item.parent = weakref.ref(self) | |||||
| self.list.append(item) | |||||
| self.data[key] = item | |||||
| def keys(self): | |||||
| return map(lambda i: self._func(i), self.list) | |||||
| def items(self): | |||||
| return map(lambda i: (self._func(i), i), self.list) | |||||
| def values(self): | |||||
| return self.list | |||||
| class CollectionNS(UserDict): | |||||
| """Helper class for maintaining ordered named collections.""" | |||||
| default = lambda self,k: k.name | |||||
| def __init__(self, parent, key=None): | |||||
| UserDict.__init__(self) | |||||
| self.parent = weakref.ref(parent) | |||||
| self.targetNamespace = None | |||||
| self.list = [] | |||||
| self._func = key or self.default | |||||
| def __getitem__(self, key): | |||||
| self.targetNamespace = self.parent().targetNamespace | |||||
| if type(key) is types.IntType: | |||||
| return self.list[key] | |||||
| elif self.__isSequence(key): | |||||
| nsuri,name = key | |||||
| return self.data[nsuri][name] | |||||
| return self.data[self.parent().targetNamespace][key] | |||||
| def __setitem__(self, key, item): | |||||
| item.parent = weakref.ref(self) | |||||
| self.list.append(item) | |||||
| targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace) | |||||
| if not self.data.has_key(targetNamespace): | |||||
| self.data[targetNamespace] = {} | |||||
| self.data[targetNamespace][key] = item | |||||
| def __isSequence(self, key): | |||||
| return (type(key) in (types.TupleType,types.ListType) and len(key) == 2) | |||||
| def keys(self): | |||||
| keys = [] | |||||
| for tns in self.data.keys(): | |||||
| keys.append(map(lambda i: (tns,self._func(i)), self.data[tns].values())) | |||||
| return keys | |||||
| def items(self): | |||||
| return map(lambda i: (self._func(i), i), self.list) | |||||
| def values(self): | |||||
| return self.list | |||||
| # This is a runtime guerilla patch for pulldom (used by minidom) so | |||||
| # that xml namespace declaration attributes are not lost in parsing. | |||||
| # We need them to do correct QName linking for XML Schema and WSDL. | |||||
| # The patch has been submitted to SF for the next Python version. | |||||
| from xml.dom.pulldom import PullDOM, START_ELEMENT | |||||
| if 1: | |||||
| def startPrefixMapping(self, prefix, uri): | |||||
| if not hasattr(self, '_xmlns_attrs'): | |||||
| self._xmlns_attrs = [] | |||||
| self._xmlns_attrs.append((prefix or 'xmlns', uri)) | |||||
| self._ns_contexts.append(self._current_context.copy()) | |||||
| self._current_context[uri] = prefix or '' | |||||
| PullDOM.startPrefixMapping = startPrefixMapping | |||||
| def startElementNS(self, name, tagName , attrs): | |||||
| # Retrieve xml namespace declaration attributes. | |||||
| xmlns_uri = 'http://www.w3.org/2000/xmlns/' | |||||
| xmlns_attrs = getattr(self, '_xmlns_attrs', None) | |||||
| if xmlns_attrs is not None: | |||||
| for aname, value in xmlns_attrs: | |||||
| attrs._attrs[(xmlns_uri, aname)] = value | |||||
| self._xmlns_attrs = [] | |||||
| uri, localname = name | |||||
| if uri: | |||||
| # When using namespaces, the reader may or may not | |||||
| # provide us with the original name. If not, create | |||||
| # *a* valid tagName from the current context. | |||||
| if tagName is None: | |||||
| prefix = self._current_context[uri] | |||||
| if prefix: | |||||
| tagName = prefix + ":" + localname | |||||
| else: | |||||
| tagName = localname | |||||
| if self.document: | |||||
| node = self.document.createElementNS(uri, tagName) | |||||
| else: | |||||
| node = self.buildDocument(uri, tagName) | |||||
| else: | |||||
| # When the tagname is not prefixed, it just appears as | |||||
| # localname | |||||
| if self.document: | |||||
| node = self.document.createElement(localname) | |||||
| else: | |||||
| node = self.buildDocument(None, localname) | |||||
| for aname,value in attrs.items(): | |||||
| a_uri, a_localname = aname | |||||
| if a_uri == xmlns_uri: | |||||
| if a_localname == 'xmlns': | |||||
| qname = a_localname | |||||
| else: | |||||
| qname = 'xmlns:' + a_localname | |||||
| attr = self.document.createAttributeNS(a_uri, qname) | |||||
| node.setAttributeNodeNS(attr) | |||||
| elif a_uri: | |||||
| prefix = self._current_context[a_uri] | |||||
| if prefix: | |||||
| qname = prefix + ":" + a_localname | |||||
| else: | |||||
| qname = a_localname | |||||
| attr = self.document.createAttributeNS(a_uri, qname) | |||||
| node.setAttributeNodeNS(attr) | |||||
| else: | |||||
| attr = self.document.createAttribute(a_localname) | |||||
| node.setAttributeNode(attr) | |||||
| attr.value = value | |||||
| self.lastEvent[1] = [(START_ELEMENT, node), None] | |||||
| self.lastEvent = self.lastEvent[1] | |||||
| self.push(node) | |||||
| PullDOM.startElementNS = startElementNS | |||||
| # | |||||
| # This is a runtime guerilla patch for minidom so | |||||
| # that xmlns prefixed attributes dont raise AttributeErrors | |||||
| # during cloning. | |||||
| # | |||||
| # Namespace declarations can appear in any start-tag, must look for xmlns | |||||
| # prefixed attribute names during cloning. | |||||
| # | |||||
| # key (attr.namespaceURI, tag) | |||||
| # ('http://www.w3.org/2000/xmlns/', u'xsd') <xml.dom.minidom.Attr instance at 0x82227c4> | |||||
| # ('http://www.w3.org/2000/xmlns/', 'xmlns') <xml.dom.minidom.Attr instance at 0x8414b3c> | |||||
| # | |||||
| # xml.dom.minidom.Attr.nodeName = xmlns:xsd | |||||
| # xml.dom.minidom.Attr.value = = http://www.w3.org/2001/XMLSchema | |||||
| if 1: | |||||
| def _clone_node(node, deep, newOwnerDocument): | |||||
| """ | |||||
| Clone a node and give it the new owner document. | |||||
| Called by Node.cloneNode and Document.importNode | |||||
| """ | |||||
| if node.ownerDocument.isSameNode(newOwnerDocument): | |||||
| operation = xml.dom.UserDataHandler.NODE_CLONED | |||||
| else: | |||||
| operation = xml.dom.UserDataHandler.NODE_IMPORTED | |||||
| if node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE: | |||||
| clone = newOwnerDocument.createElementNS(node.namespaceURI, | |||||
| node.nodeName) | |||||
| for attr in node.attributes.values(): | |||||
| clone.setAttributeNS(attr.namespaceURI, attr.nodeName, attr.value) | |||||
| prefix, tag = xml.dom.minidom._nssplit(attr.nodeName) | |||||
| if prefix == 'xmlns': | |||||
| a = clone.getAttributeNodeNS(attr.namespaceURI, tag) | |||||
| elif prefix: | |||||
| a = clone.getAttributeNodeNS(attr.namespaceURI, tag) | |||||
| else: | |||||
| a = clone.getAttributeNodeNS(attr.namespaceURI, attr.nodeName) | |||||
| a.specified = attr.specified | |||||
| if deep: | |||||
| for child in node.childNodes: | |||||
| c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument) | |||||
| clone.appendChild(c) | |||||
| elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_FRAGMENT_NODE: | |||||
| clone = newOwnerDocument.createDocumentFragment() | |||||
| if deep: | |||||
| for child in node.childNodes: | |||||
| c = xml.dom.minidom._clone_node(child, deep, newOwnerDocument) | |||||
| clone.appendChild(c) | |||||
| elif node.nodeType == xml.dom.minidom.Node.TEXT_NODE: | |||||
| clone = newOwnerDocument.createTextNode(node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.CDATA_SECTION_NODE: | |||||
| clone = newOwnerDocument.createCDATASection(node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.PROCESSING_INSTRUCTION_NODE: | |||||
| clone = newOwnerDocument.createProcessingInstruction(node.target, | |||||
| node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.COMMENT_NODE: | |||||
| clone = newOwnerDocument.createComment(node.data) | |||||
| elif node.nodeType == xml.dom.minidom.Node.ATTRIBUTE_NODE: | |||||
| clone = newOwnerDocument.createAttributeNS(node.namespaceURI, | |||||
| node.nodeName) | |||||
| clone.specified = True | |||||
| clone.value = node.value | |||||
| elif node.nodeType == xml.dom.minidom.Node.DOCUMENT_TYPE_NODE: | |||||
| assert node.ownerDocument is not newOwnerDocument | |||||
| operation = xml.dom.UserDataHandler.NODE_IMPORTED | |||||
| clone = newOwnerDocument.implementation.createDocumentType( | |||||
| node.name, node.publicId, node.systemId) | |||||
| clone.ownerDocument = newOwnerDocument | |||||
| if deep: | |||||
| clone.entities._seq = [] | |||||
| clone.notations._seq = [] | |||||
| for n in node.notations._seq: | |||||
| notation = xml.dom.minidom.Notation(n.nodeName, n.publicId, n.systemId) | |||||
| notation.ownerDocument = newOwnerDocument | |||||
| clone.notations._seq.append(notation) | |||||
| if hasattr(n, '_call_user_data_handler'): | |||||
| n._call_user_data_handler(operation, n, notation) | |||||
| for e in node.entities._seq: | |||||
| entity = xml.dom.minidom.Entity(e.nodeName, e.publicId, e.systemId, | |||||
| e.notationName) | |||||
| entity.actualEncoding = e.actualEncoding | |||||
| entity.encoding = e.encoding | |||||
| entity.version = e.version | |||||
| entity.ownerDocument = newOwnerDocument | |||||
| clone.entities._seq.append(entity) | |||||
| if hasattr(e, '_call_user_data_handler'): | |||||
| e._call_user_data_handler(operation, n, entity) | |||||
| else: | |||||
| # Note the cloning of Document and DocumentType nodes is | |||||
| # implemenetation specific. minidom handles those cases | |||||
| # directly in the cloneNode() methods. | |||||
| raise xml.dom.NotSupportedErr("Cannot clone node %s" % repr(node)) | |||||
| # Check for _call_user_data_handler() since this could conceivably | |||||
| # used with other DOM implementations (one of the FourThought | |||||
| # DOMs, perhaps?). | |||||
| if hasattr(node, '_call_user_data_handler'): | |||||
| node._call_user_data_handler(operation, node, clone) | |||||
| return clone | |||||
| xml.dom.minidom._clone_node = _clone_node | |||||
| @@ -0,0 +1,88 @@ | |||||
| """Translate strings to and from SOAP 1.2 XML name encoding | |||||
| Implements rules for mapping application defined name to XML names | |||||
| specified by the w3 SOAP working group for SOAP version 1.2 in | |||||
| Appendix A of "SOAP Version 1.2 Part 2: Adjuncts", W3C Working Draft | |||||
| 17, December 2001, <http://www.w3.org/TR/soap12-part2/#namemap> | |||||
| Also see <http://www.w3.org/2000/xp/Group/xmlp-issues>. | |||||
| Author: Gregory R. Warnes <gregory_r_warnes@groton.pfizer.com> | |||||
| Date:: 2002-04-25 | |||||
| Version 0.9.0 | |||||
| """ | |||||
| ident = "$Id: XMLname.py,v 1.2 2003/05/20 21:10:14 warnes Exp $" | |||||
| from re import * | |||||
| def _NCNameChar(x): | |||||
| return x.isalpha() or x.isdigit() or x=="." or x=='-' or x=="_" | |||||
| def _NCNameStartChar(x): | |||||
| return x.isalpha() or x=="_" | |||||
| def _toUnicodeHex(x): | |||||
| hexval = hex(ord(x[0]))[2:] | |||||
| hexlen = len(hexval) | |||||
| # Make hexval have either 4 or 8 digits by prepending 0's | |||||
| if (hexlen==1): hexval = "000" + hexval | |||||
| elif (hexlen==2): hexval = "00" + hexval | |||||
| elif (hexlen==3): hexval = "0" + hexval | |||||
| elif (hexlen==4): hexval = "" + hexval | |||||
| elif (hexlen==5): hexval = "000" + hexval | |||||
| elif (hexlen==6): hexval = "00" + hexval | |||||
| elif (hexlen==7): hexval = "0" + hexval | |||||
| elif (hexlen==8): hexval = "" + hexval | |||||
| else: raise Exception, "Illegal Value returned from hex(ord(x))" | |||||
| return "_x"+ hexval + "_" | |||||
| def _fromUnicodeHex(x): | |||||
| return eval( r'u"\u'+x[2:-1]+'"' ) | |||||
| def toXMLname(string): | |||||
| """Convert string to a XML name.""" | |||||
| if string.find(':') != -1 : | |||||
| (prefix, localname) = string.split(':',1) | |||||
| else: | |||||
| prefix = None | |||||
| localname = string | |||||
| T = unicode(localname) | |||||
| N = len(localname) | |||||
| X = []; | |||||
| for i in range(N) : | |||||
| if i< N-1 and T[i]==u'_' and T[i+1]==u'x': | |||||
| X.append(u'_x005F_') | |||||
| elif i==0 and N >= 3 and \ | |||||
| ( T[0]==u'x' or T[0]==u'X' ) and \ | |||||
| ( T[1]==u'm' or T[1]==u'M' ) and \ | |||||
| ( T[2]==u'l' or T[2]==u'L' ): | |||||
| X.append(u'_xFFFF_' + T[0]) | |||||
| elif (not _NCNameChar(T[i])) or (i==0 and not _NCNameStartChar(T[i])): | |||||
| X.append(_toUnicodeHex(T[i])) | |||||
| else: | |||||
| X.append(T[i]) | |||||
| return u''.join(X) | |||||
| def fromXMLname(string): | |||||
| """Convert XML name to unicode string.""" | |||||
| retval = sub(r'_xFFFF_','', string ) | |||||
| def fun( matchobj ): | |||||
| return _fromUnicodeHex( matchobj.group(0) ) | |||||
| retval = sub(r'_x[0-9A-Za-z]+_', fun, retval ) | |||||
| return retval | |||||
| @@ -0,0 +1,36 @@ | |||||
| #! /usr/bin/env python | |||||
| """WSDL parsing services package for Web Services for Python.""" | |||||
| ident = "$Id: __init__.py,v 1.8 2004/09/09 23:32:09 boverhof Exp $" | |||||
| import WSDLTools | |||||
| import XMLname | |||||
| from logging import getLogger as _getLogger | |||||
| import logging.config as _config | |||||
| LOGGING = 'logging.txt' | |||||
| DEBUG = True | |||||
| # | |||||
| # If LOGGING configuration file is not found, turn off logging | |||||
| # and use _noLogger class because logging module's performance | |||||
| # is terrible. | |||||
| # | |||||
| try: | |||||
| _config.fileConfig(LOGGING) | |||||
| except: | |||||
| DEBUG = False | |||||
| class Base: | |||||
| def __init__(self, module=__name__): | |||||
| self.logger = _noLogger() | |||||
| if DEBUG is True: | |||||
| self.logger = _getLogger('%s-%s(%x)' %(module, self.__class__, id(self))) | |||||
| class _noLogger: | |||||
| def __init__(self, *args): pass | |||||
| def warning(self, *args): pass | |||||
| def debug(self, *args): pass | |||||
| def error(self, *args): pass | |||||
| @@ -0,0 +1,5 @@ | |||||
| #! /usr/bin/env python | |||||
| """wstools.WSDLTools.WSDLReader tests directory.""" | |||||
| import utils | |||||
| @@ -0,0 +1,20 @@ | |||||
| ############################################################################ | |||||
| # Joshua R. Boverhof, David W. Robertson, LBNL | |||||
| # See LBNLCopyright for copyright notice! | |||||
| ########################################################################### | |||||
| import unittest | |||||
| import test_wsdl | |||||
| import utils | |||||
| def makeTestSuite(): | |||||
| suite = unittest.TestSuite() | |||||
| suite.addTest(test_wsdl.makeTestSuite("services_by_file")) | |||||
| return suite | |||||
| def main(): | |||||
| loader = utils.MatchTestLoader(True, None, "makeTestSuite") | |||||
| unittest.main(defaultTest="makeTestSuite", testLoader=loader) | |||||
| if __name__ == "__main__" : main() | |||||
| @@ -0,0 +1,160 @@ | |||||
| #!/usr/bin/env python | |||||
| ############################################################################ | |||||
| # Joshua R. Boverhof, David W. Robertson, LBNL | |||||
| # See LBNLCopyright for copyright notice! | |||||
| ########################################################################### | |||||
| import sys, unittest | |||||
| import ConfigParser | |||||
| from ZSI.wstools.Utility import DOM | |||||
| from ZSI.wstools.WSDLTools import WSDLReader | |||||
| from ZSI.wstools.TimeoutSocket import TimeoutError | |||||
| class WSDLToolsTestCase(unittest.TestCase): | |||||
| def __init__(self, methodName='runTest'): | |||||
| unittest.TestCase.__init__(self, methodName) | |||||
| def setUp(self): | |||||
| self.path = nameGenerator.next() | |||||
| print self.path | |||||
| sys.stdout.flush() | |||||
| def __str__(self): | |||||
| teststr = unittest.TestCase.__str__(self) | |||||
| if hasattr(self, "path"): | |||||
| return "%s: %s" % (teststr, self.path ) | |||||
| else: | |||||
| return "%s" % (teststr) | |||||
| def checkWSDLCollection(self, tag_name, component, key='name'): | |||||
| if self.wsdl is None: | |||||
| return | |||||
| definition = self.wsdl.document.documentElement | |||||
| version = DOM.WSDLUriToVersion(definition.namespaceURI) | |||||
| nspname = DOM.GetWSDLUri(version) | |||||
| for node in DOM.getElements(definition, tag_name, nspname): | |||||
| name = DOM.getAttr(node, key) | |||||
| comp = component[name] | |||||
| self.failUnlessEqual(eval('comp.%s' %key), name) | |||||
| def checkXSDCollection(self, tag_name, component, node, key='name'): | |||||
| for cnode in DOM.getElements(node, tag_name): | |||||
| name = DOM.getAttr(cnode, key) | |||||
| component[name] | |||||
| def test_all(self): | |||||
| try: | |||||
| if self.path[:7] == 'http://': | |||||
| self.wsdl = WSDLReader().loadFromURL(self.path) | |||||
| else: | |||||
| self.wsdl = WSDLReader().loadFromFile(self.path) | |||||
| except TimeoutError: | |||||
| print "connection timed out" | |||||
| sys.stdout.flush() | |||||
| return | |||||
| except: | |||||
| self.path = self.path + ": load failed, unable to start" | |||||
| raise | |||||
| try: | |||||
| self.checkWSDLCollection('service', self.wsdl.services) | |||||
| except: | |||||
| self.path = self.path + ": wsdl.services" | |||||
| raise | |||||
| try: | |||||
| self.checkWSDLCollection('message', self.wsdl.messages) | |||||
| except: | |||||
| self.path = self.path + ": wsdl.messages" | |||||
| raise | |||||
| try: | |||||
| self.checkWSDLCollection('portType', self.wsdl.portTypes) | |||||
| except: | |||||
| self.path = self.path + ": wsdl.portTypes" | |||||
| raise | |||||
| try: | |||||
| self.checkWSDLCollection('binding', self.wsdl.bindings) | |||||
| except: | |||||
| self.path = self.path + ": wsdl.bindings" | |||||
| raise | |||||
| try: | |||||
| self.checkWSDLCollection('import', self.wsdl.imports, key='namespace') | |||||
| except: | |||||
| self.path = self.path + ": wsdl.imports" | |||||
| raise | |||||
| try: | |||||
| for key in self.wsdl.types.keys(): | |||||
| schema = self.wsdl.types[key] | |||||
| self.failUnlessEqual(key, schema.getTargetNamespace()) | |||||
| definition = self.wsdl.document.documentElement | |||||
| version = DOM.WSDLUriToVersion(definition.namespaceURI) | |||||
| nspname = DOM.GetWSDLUri(version) | |||||
| for node in DOM.getElements(definition, 'types', nspname): | |||||
| for snode in DOM.getElements(node, 'schema'): | |||||
| tns = DOM.findTargetNS(snode) | |||||
| schema = self.wsdl.types[tns] | |||||
| self.schemaAttributesDeclarations(schema, snode) | |||||
| self.schemaAttributeGroupDeclarations(schema, snode) | |||||
| self.schemaElementDeclarations(schema, snode) | |||||
| self.schemaTypeDefinitions(schema, snode) | |||||
| except: | |||||
| self.path = self.path + ": wsdl.types" | |||||
| raise | |||||
| if self.wsdl.extensions: | |||||
| print 'No check for WSDLTools(%s) Extensions:' %(self.wsdl.name) | |||||
| for ext in self.wsdl.extensions: print '\t', ext | |||||
| def schemaAttributesDeclarations(self, schema, node): | |||||
| self.checkXSDCollection('attribute', schema.attr_decl, node) | |||||
| def schemaAttributeGroupDeclarations(self, schema, node): | |||||
| self.checkXSDCollection('group', schema.attr_groups, node) | |||||
| def schemaElementDeclarations(self, schema, node): | |||||
| self.checkXSDCollection('element', schema.elements, node) | |||||
| def schemaTypeDefinitions(self, schema, node): | |||||
| self.checkXSDCollection('complexType', schema.types, node) | |||||
| self.checkXSDCollection('simpleType', schema.types, node) | |||||
| def setUpOptions(section): | |||||
| cp = ConfigParser.ConfigParser() | |||||
| cp.read('config.txt') | |||||
| if not cp.sections(): | |||||
| print 'fatal error: configuration file config.txt not present' | |||||
| sys.exit(0) | |||||
| if not cp.has_section(section): | |||||
| print '%s section not present in configuration file, exiting' % section | |||||
| sys.exit(0) | |||||
| return cp, len(cp.options(section)) | |||||
| def getOption(cp, section): | |||||
| for name, value in cp.items(section): | |||||
| yield value | |||||
| def makeTestSuite(section='services_by_file'): | |||||
| global nameGenerator | |||||
| cp, numTests = setUpOptions(section) | |||||
| nameGenerator = getOption(cp, section) | |||||
| suite = unittest.TestSuite() | |||||
| for i in range(0, numTests): | |||||
| suite.addTest(unittest.makeSuite(WSDLToolsTestCase, 'test_')) | |||||
| return suite | |||||
| def main(): | |||||
| unittest.main(defaultTest="makeTestSuite") | |||||
| if __name__ == "__main__" : main() | |||||
| @@ -0,0 +1,37 @@ | |||||
| #!/usr/bin/env python | |||||
| ############################################################################ | |||||
| # Joshua R. Boverhof, David W. Robertson, LBNL | |||||
| # See LBNLCopyright for copyright notice! | |||||
| ########################################################################### | |||||
| import unittest, tarfile, os, ConfigParser | |||||
| import test_wsdl | |||||
| SECTION='files' | |||||
| CONFIG_FILE = 'config.txt' | |||||
| def extractFiles(section, option): | |||||
| config = ConfigParser.ConfigParser() | |||||
| config.read(CONFIG_FILE) | |||||
| archives = config.get(section, option) | |||||
| archives = eval(archives) | |||||
| for file in archives: | |||||
| tar = tarfile.open(file) | |||||
| if not os.access(tar.membernames[0], os.R_OK): | |||||
| for i in tar.getnames(): | |||||
| tar.extract(i) | |||||
| def makeTestSuite(): | |||||
| suite = unittest.TestSuite() | |||||
| suite.addTest(test_wsdl.makeTestSuite("services_by_file")) | |||||
| return suite | |||||
| def main(): | |||||
| extractFiles(SECTION, 'archives') | |||||
| unittest.main(defaultTest="makeTestSuite") | |||||
| if __name__ == "__main__" : main() | |||||
| @@ -0,0 +1,20 @@ | |||||
| #!/usr/bin/env python | |||||
| ############################################################################ | |||||
| # Joshua R. Boverhof, David W. Robertson, LBNL | |||||
| # See LBNLCopyright for copyright notice! | |||||
| ########################################################################### | |||||
| import unittest | |||||
| import test_wsdl | |||||
| def makeTestSuite(): | |||||
| suite = unittest.TestSuite() | |||||
| suite.addTest(test_wsdl.makeTestSuite("services_by_http")) | |||||
| return suite | |||||
| def main(): | |||||
| unittest.main(defaultTest="makeTestSuite") | |||||
| if __name__ == "__main__" : main() | |||||