[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() | |||||