[Zope-CVS] CVS: Packages/WebService - LICENSE.txt:1.1 PKG-INFO:1.1 SOAPCallInfo.py:1.1 SOAPMessage.py:1.1 SOAPReader.py:1.1 SOAPWriter.py:1.1 Serializer.py:1.1 ServiceProxy.py:1.1 TimeoutSocket.py:1.1 Transports.py:1.1 Utility.py:1.1 WSDLTools.py:1.1 XMLSchema.py:1.1 XMLWriter.py:1.1 __init__.py:1.1 setup.py:1.1 todo.txt:1.1

Brian Lloyd brian@digicool.com
Mon, 26 Nov 2001 11:18:24 -0500


Update of /cvs-repository/Packages/WebService
In directory cvs.zope.org:/tmp/cvs-serv23779/WebService

Added Files:
	LICENSE.txt PKG-INFO SOAPCallInfo.py SOAPMessage.py 
	SOAPReader.py SOAPWriter.py Serializer.py ServiceProxy.py 
	TimeoutSocket.py Transports.py Utility.py WSDLTools.py 
	XMLSchema.py XMLWriter.py __init__.py setup.py todo.txt 
Log Message:
Initial commit of web services package.


=== Added File Packages/WebService/LICENSE.txt ===
Zope Public License (ZPL) Version 2.0
-----------------------------------------------

This software is Copyright (c) Zope Corporation (tm) and
Contributors. All rights reserved.

This license has been certified as open source. It has also
been designated as GPL compatible by the Free Software
Foundation (FSF).

Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the
following conditions are met:

1. Redistributions in source code must retain the above
   copyright notice, this list of conditions, and the following
   disclaimer.

2. 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.

3. The name Zope Corporation (tm) must not be used to
   endorse or promote products derived from this software
   without prior written permission from Zope Corporation.

4. The right to distribute this software or to use it for
   any purpose does not give you the right to use Servicemarks
   (sm) or Trademarks (tm) of Zope Corporation. Use of them is
   covered in a separate agreement (see
   http://www.zope.com/Marks).

5. If any files are modified, you must cause the modified
   files to carry prominent notices stating that you changed
   the files and the date of any change.

Disclaimer

  THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS''
  AND ANY EXPRESSED 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 ZOPE CORPORATION OR ITS 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.


This software consists of contributions made by Zope
Corporation and many individuals on behalf of Zope
Corporation.  Specific attributions are listed in the
accompanying credits file.




=== Added File Packages/WebService/PKG-INFO ===
Metadata-Version: 1.0
Name: WebService
Version: 1.0a
Summary: Web Services for Python
Home-page: UNKNOWN
Author: Brian Lloyd
Author-email: brian@zope.com
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN


=== Added File Packages/WebService/SOAPCallInfo.py ===
# 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.

from Utility import DOM
import WSDLTools


class SOAPCallInfo:
    """SOAPCallInfo captures the important binding information about a 
       SOAP operation, in a structure that is easier to work with than
       raw WSDL structures."""

    def __init__(self, methodName):
        self.methodName = methodName
        self.inheaders = []
        self.outheaders = []
        self.inparams = []
        self.outparams = []
        self.retval = None

    encodingStyle = DOM.NS_SOAP_ENC
    documentation = ''
    soapAction = None
    transport = None
    namespace = None
    location = None
    use = 'encoded'
    style = 'rpc'

    def addInParameter(self, name, type, namespace=None, element_type=0):
        """Add an input parameter description to the call info."""
        parameter = ParameterInfo(name, type, namespace, element_type)
        self.inparams.append(parameter)
        return parameter

    def addOutParameter(self, name, type, namespace=None, element_type=0):
        """Add an output parameter description to the call info."""
        parameter = ParameterInfo(name, type, namespace, element_type)
        self.outparams.append(parameter)
        return parameter

    def setReturnParameter(self, name, type, namespace=None, element_type=0):
        """Set the return parameter description for the call info."""
        parameter = ParameterInfo(name, type, namespace, element_type)
        self.retval = parameter
        return parameter

    def addInHeaderInfo(self, name, type, namespace, element_type=0,
                        mustUnderstand=0):
        """Add an input SOAP header description to the call info."""
        headerinfo = HeaderInfo(name, type, namespace, element_type)
        if mustUnderstand:
            headerinfo.mustUnderstand = 1
        self.inheaders.append(headerinfo)
        return headerinfo

    def addOutHeaderInfo(self, name, type, namespace, element_type=0,
                         mustUnderstand=0):
        """Add an output SOAP header description to the call info."""
        headerinfo = HeaderInfo(name, type, namespace, element_type)
        if mustUnderstand:
            headerinfo.mustUnderstand = 1
        self.outheaders.append(headerinfo)
        return headerinfo

    def getInParameters(self):
        """Return a sequence of the in parameters of the method."""
        return self.inparams

    def getOutParameters(self):
        """Return a sequence of the out parameters of the method."""
        return self.outparams

    def getReturnParameter(self):
        """Return param info about the return value of the method."""
        return self.retval

    def getInHeaders(self):
        """Return a sequence of the in headers of the method."""
        return self.inheaders

    def getOutHeaders(self):
        """Return a sequence of the out headers of the method."""
        return self.outheaders


class ParameterInfo:
    """A ParameterInfo object captures parameter binding information."""
    def __init__(self, name, type, namespace=None, element_type=0):
        if element_type:
            self.element_type = 1
        if namespace is not None:
            self.namespace = namespace
        self.name = name
        self.type = type

    element_type = 0
    namespace = None
    default = None


class HeaderInfo(ParameterInfo):
    """A HeaderInfo object captures SOAP header binding information."""
    def __init__(self, name, type, namespace, element_type=None):
        ParameterInfo.__init__(self, name, type, namespace, element_type)

    mustUnderstand = 0
    actor = None


def callInfoFromWSDL(port, name):
    """Return a SOAPCallInfo given a WSDL port and operation name."""
    wsdl = port.getService().getWSDL()
    binding = port.getBinding()
    portType = binding.getPortType()
    operation = portType.operations[name]
    opbinding = binding.operations[name]
    messages = wsdl.messages
    callinfo = SOAPCallInfo(name)

    addrbinding = port.getAddressBinding()
    if not isinstance(addrbinding, WSDLTools.SoapAddressBinding):
        raise ValueError, 'Unsupported binding type.'        
    callinfo.location = addrbinding.location

    soapbinding = binding.findBinding(WSDLTools.SoapBinding)
    if soapbinding is None:
        raise ValueError, 'Missing soap:binding element.'
    callinfo.transport = soapbinding.transport
    callinfo.style = soapbinding.style or 'document'

    soap_op_binding = opbinding.findBinding(WSDLTools.SoapOperationBinding)
    if soap_op_binding is not None:
        callinfo.soapAction = soap_op_binding.soapAction
        callinfo.style = soap_op_binding.style or callinfo.style

    parameterOrder = operation.parameterOrder

    if operation.input is not None:
        message = messages[operation.input.message]
        msgrole = opbinding.input

        mime = msgrole.findBinding(WSDLTools.MimeMultipartRelatedBinding)
        if mime is not None:
            raise ValueError, 'Mime bindings are not supported.'
        else:
            for item in msgrole.findBindings(WSDLTools.SoapHeaderBinding):
                part = messages[item.message].parts[item.part]
                header = callinfo.addInHeaderInfo(
                    part.name,
                    part.element or part.type,
                    item.namespace,
                    element_type = part.element and 1 or 0
                    )
                header.encodingStyle = item.encodingStyle

            body = msgrole.findBinding(WSDLTools.SoapBodyBinding)
            if body is None:
                raise ValueError, 'Missing soap:body binding.'
            callinfo.encodingStyle = body.encodingStyle
            callinfo.namespace = body.namespace
            callinfo.use = body.use

            if body.parts is not None:
                parts = []
                for name in body.parts:
                    parts.append(message.parts[name])
            else:
                parts = message.parts.values()

            for part in parts:
                callinfo.addInParameter(
                    part.name,
                    part.element or part.type,
                    element_type = part.element and 1 or 0
                    )

    if operation.output is not None:
        message = messages[operation.output.message]
        msgrole = opbinding.output

        mime = msgrole.findBinding(WSDLTools.MimeMultipartRelatedBinding)
        if mime is not None:
            raise ValueError, 'Mime bindings are not supported.'
        else:
            for item in msgrole.findBindings(WSDLTools.SoapHeaderBinding):
                part = messages[item.message].parts[item.part]
                header = callinfo.addOutHeaderInfo(
                    part.name,
                    part.element or part.type,
                    item.namespace,
                    element_type = part.element and 1 or 0
                    )
                header.encodingStyle = item.encodingStyle

            body = msgrole.findBinding(WSDLTools.SoapBodyBinding)
            if body is None:
                raise ValueError, 'Missing soap:body binding.'
            callinfo.encodingStyle = body.encodingStyle
            callinfo.namespace = body.namespace
            callinfo.use = body.use

            if body.parts is not None:
                parts = []
                for name in body.parts:
                    parts.append(message.parts[name])
            else:
                parts = message.parts.values()

            if parts:
                callinfo.setReturnParameter(
                    part.name,
                    part.element or part.type,
                    element_type = part.element and 1 or 0
                    )
                for part in parts[1:]:
                    callinfo.addOutParameter(
                        part.name,
                        part.element or part.type,
                        element_type = part.element and 1 or 0
                        )

    return callinfo


=== Added File Packages/WebService/SOAPMessage.py ===
# 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.

from Serializer import Serializer, SerializationContext
from Transports import HTTPTransport
from MimeWriter import MimeWriter
from SOAPReader import SOAPReader
from SOAPWriter import SOAPWriter
from StringIO import StringIO
from Utility import DOM


class SOAPMessage:
    """A SOAPMessage provides a higher level interface for working with 
       SOAP messages that handles most of the details of serialization."""

    def __init__(self, message_body=None):
        self.body = message_body
        self.parameters = []
        self.mimeparts = []
        self.headers = []

    serializer = Serializer()
    soapAction = None
    methodName = None
    namespace = None
    version = '1.1'
    style = 'rpc'

    def getContentType(self):
        """Return the content type of the serialized message body."""
        return getattr(self, 'content_type', 'text/xml')

    def getMessageBody(self):
        """Return the serialized message body of the SOAP message."""
        return self.body

    def getMimePart(self, name):
        """Return the named MIME message part associated with the message,
           or None if the named MIME part is not present in the message."""
        for item in self.mimeparts:
            if item.name == name:
                return item
        return None

    def getMimeParts(self):
        """Return the MIME message parts associated with the SOAP message."""
        return self.mimeparts

    def addSoapHeader(self, name, namespace, value, type, actor=None,
                      mustUnderstand=0,):
        """Add a SOAP header with the given values to the message."""
        header = SOAPHeader(name, namespace, value, type)
        header.mustUnderstand = mustUnderstand
        header.actor = actor
        self.headers.append(header)

    def getSoapHeader(self, name):
        """Return the named SOAP header from the message, or None if
           the named header is not present in the message."""
        for item in self.headers:
            if item.name == name:
                return item
        return None

    def getSoapHeaders(self):
        """Return a sequence of the SOAP headers found in the message."""
        return self.headers

    def getMustUnderstandHeaders(self):
        """Return a sequence of those headers in the SOAP message that
           have true mustUnderstand attribute values."""
        result = []
        for item in self.headers:
            if item.mustUnderstand == 1:
                result.append(item)
        return result

    def getHeadersForActor(self, actorURI):
        """Return a sequence of those headers in the SOAP message that
           have actor attributes matching the given value."""
        nexturi = DOM.GetSOAPActorNext(self.getSOAPVersion())
        result = []
        for item in self.headers:
            if ((actorURI == nexturi and item.actor is None) or
                (item.actor == actor)):
                result.append(item)
        return result

    def isFault(self):
        """Return true if the SOAP response message contains a fault."""
        return self.getFault() is not None

    def getFault(self):
        """Return the fault associated with the SOAP response message,
           as a SOAPFault or None if no fault is present in the message."""
        return getattr(self, 'fault', None)

    def addMimeParam(self, name, content_type, data):
        """Add a MIME part to the message. Note that adding MIME parts
           causes the message to be sent as a mime/multipart message."""
        part = MIMEPart(name, content_type, data)
        self.mimeparts.append(part)
        param = Parameter(name, part, None)
        self.parameters.append(param)

    def addParameter(self, name, value, type, namespace=None):
        """Add a parameter to the SOAP request message. Parameters are
           serialized and sent in the order they are added."""
        param = Parameter(name, value, type, namespace)
        self.parameters.append(param)

    def getParameter(self, name):
        """Return the named message parameter of the SOAP response."""
        for item in self.params:
            if item.name == name:
                return item
        return None

    def getParameters(self):
        """Return a sequence of the parameters in the SOAP response."""
        return self.parameters

    def getReturnValue(self):
        """A convenience method that returns the value of the first
           parameter of the message (which represents the return
           value in a reply from a server). This returns None if no
           parameters appear in the SOAP message."""
        if not len(self.parameters):
            return None
        return self.parameters[0].value

    def beforeSerialize(self):
        """This method is called before serialization of a SOAP message.
           Subclasses can implement this to customize message processing."""
        pass

    def afterSerialize(self):
        """This method is called after serialization of a SOAP message.
           Subclasses can implement this to customize message processing."""
        pass

    def beforeDeserialize(self):
        """This method is called before deserialization of a SOAP message.
           Subclasses can implement this to customize message processing."""
        pass

    def afterDeserialize(self):
        """This method is called after deserialization of a SOAP message.
           Subclasses can implement this to customize message processing."""
        pass

    def serialize(self):
        """Encode the message data into a valid SOAP XML message, using the
           standard SOAP encoding for rpc style messages."""
        self.beforeSerialize()

        serializer = self.serializer
        context = SerializationContext(serializer)
        context.writer = SOAPWriter(self.version)
        writer = context.writer

        writer.startEnvelope()
        if self.style == 'rpc':
            writer.writeEncodingStyle(writer.NS_SOAP_ENC)
            values = []
            for item in self.headers:
                values.append(getattr(item, 'value', None))
            for item in self.parameters:
                values.append(getattr(item, 'value', None))                
            context.mapValueRefs(filter(None, values))
 
        if self.headers:
            writer.startHeader()
            for item in self.headers:
                if self.mimeparts and isinstance(item.value, MIMEPart):
                    writer.startElement(item.name, item.namespace)
                    writer.writeAttr('href', 'cid:%s@message' % item.name)
                    writer.endElement()
                else:
                    serializer.serialize(
                        item.name,
                        item.value,
                        item.type,
                        context,
                        item.namespace,
                        )
                element = writer.currentElement().childNodes[-1]
                if item.mustUnderstand is not None:
                    element.setAttribute('mustUnderstand', '1')
                if item.actor is not None:
                    element.setAttribute('actor', actor)

        writer.startBody()

        if self.style == 'rpc':
            # Standard SOAP rpc style message. We use the serializer to
            # convert the param values using the standard SOAP encoding.
            writer.startElement(self.methodName, self.namespace)
            for item in self.parameters:
                if self.mimeparts and isinstance(item.value, MIMEPart):
                    writer.startElement(item.name, item.namespace)
                    writer.writeAttr('href', 'cid:%s@message' % item.name)
                    writer.endElement()
                else:
                    serializer.serialize(
                        item.name,
                        item.value,
                        item.type,
                        context
                        )
            writer.endElement()

        else:
            # Document style message. Be warned that exactly what we should
            # be doing here is subject to change. For now, we allow either
            # a string, a DOM document object, or a DOM element as the
            # parameter values.
            for item in self.parameters:
                value = item.value
                if self.mimeparts and isinstance(value, MIMEPart):
                    writer.startElement(item.name, item.namespace)
                    writer.writeAttr('href', 'cid:%s@message' % item.name)
                    writer.endElement()
                elif hasattr(value, 'nodeType'):
                    if value.nodeType == value.DOCUMENT_NODE:
                        element = value.documentElement
                        strval = DOM.elementToString(element)
                        writer.writeXML(strval)
                        continue
                    if value.nodeType == value.ELEMENT_NODE:
                        strval = DOM.elementToString(value)
                        writer.writeXML(strval)
                        continue
                    raise ValueError(
                        'Parameters of document-style SOAP messages must ' \
                        'be a string, DOM document or DOM element object.'
                        )
                elif type(value) in (type(''), type(u'')):
                        writer.writeXML(value)
                        continue
                raise ValueError(
                    'Unknown parameter type.'
                    )

        writer.endBody()
        writer.endEnvelope()

        output = writer.toString()

        # If the message contains MIME parts, create a multipart message.
        if self.mimeparts:
            stream = StringIO()
            writer = MimeWriter(stream)
            writer.startmultipartbody('related',
                plist=[('type', 'text/xml'),
                       ('start', '<soap-envelope@message>')
                       ]
                )
            soap = writer.nextpart()
            soap.addheader('Content-Transfer-Encoding', '8bit')
            soap.addheader('Content-ID', '<soap-envelope@message>')
            body = soap.startbody('text/xml')
            body.write(output)

            for mimepart in self.mimeparts:
                part = writer.nextpart()
                part.addheader('Content-ID', '<%s@message>' % mimepart.name)
                if mimepart.content_type[:4] == 'text':
                    part.addheader('Content-Transfer-Encoding', '8bit')
                    body = part.startbody(mimepart.content_type)
                    body.write(mimepart.data)
                else:
                    part.addheader('Content-Transfer-Encoding', 'base64')
                    body = part.startbody(mimepart.content_type)
                    body.write(base64.encodestring(mimepart.data))
            writer.lastpart()
            output = stream.getvalue()
            output = output.split('--', 1)[-1]

        self.body = output
        self.afterSerialize()


    def deserialize(self):
        """Decode the response SOAP message."""
        serializer = self.serializer
        context = SerializationContext(serializer)

        if self.body is None:
            raise InvalidMessage(
                'Cannot deserialize without a message body.'
                )

        context.reader = SOAPReader(self.body)
        reader = self.reader = context.reader
        self.version = reader.version

        # xxx - handle mime response here.


        envelope = reader.getEnvelope()

        self.checkEncodingStyle(envelope)

        # Check for a fault in the response message first.
        fault = reader.getFault()
        if fault is not None:
            faultcode = reader.getFaultCode()
            faultcodeNS = reader.getFaultCodeNS()
            faultstring = reader.getFaultString()
            faultactor = reader.getFaultActor()

            # For now, save fault detail as an xml string.
            detail = reader.getFaultDetail()
            if detail is not None:
                detail = reader.derefElement(detail)
                detail = DOM.elementToString(detail)
            self.fault = SOAPFault(
                faultcode, faultstring, faultactor, detail, faultcodeNS
                )
            return

        # Hmm - think about this!
        headers = reader.getHeader()
        if headers is not None:
            self.checkEncodingStyle(headers)

            for element in reader.getHeaderElements():
                self.checkEncodingStyle(element)
                name = element.localName
                namespace = element.namespaceURI or None
                type = DOM.getTypeRef(element)
                try: value = serializer.deserialize(element, context)
                except: value = element
                header = SOAPHeader(name, value, type, namespace)
                header.actor = DOM.getAttr(element, 'actor', default=None)
                header.mustUnderstand = (
                    DOM.getAttr(element, 'mustUnderstand') == '1'
                    )
                self.headers.append(header)

        body = reader.getBody()

        self.checkEncodingStyle(body)

        if self.style == 'rpc':
            struct = reader.getRPCStruct()
            self.namespace = struct.namespaceURI
            self.methodName = struct.localName

            # Standard SOAP rpc style message. We use the serializer to
            # convert the param values using the standard SOAP encoding.
            for element in reader.getRPCParams():
                self.checkEncodingStyle(element)
                name = element.localName
                namespace = element.namespaceURI or None
                type = DOM.getTypeRef(element)
                value = serializer.deserialize(element, context)

                param = Parameter(name, value, type, namespace)
                self.parameters.append(param)
        else:
            # Document style message. In this case the value attributes of
            # the out params are set to reference the actual DOM elements
            # that represent "document" elements in the SOAP message.
            #
            # XXX - actually, this is broken because we don't keep a ref to
            # the reader :(
            self.reader = reader
            for element in reader.getBodyElements():
                name = element.localName
                namespace = element.namespaceURI or None
                param = Parameter(name, element, None, namespace)
                self.parameters.append(param)

        return

    def checkEncodingStyle(self, element):
        encoding = DOM.getAttr(element, 'encodingStyle', None, default=None)
        if encoding is not None and encoding.find(
            DOM.GetSOAPEncUri(self.version)) < 0:
            raise ValueError, 'Unknown encoding style: %s' % encoding


class Parameter:
    """A Parameter object models a single SOAP message parameter."""
    def __init__(self, name, value, type, namespace=None):
        self.namespace = namespace
        self.name = name
        self.type = type
        self.value = value


class SOAPHeader(Parameter):
    """A SOAPHeader object models a single SOAP message header."""
    def __init__(self, name, value, type, namespace):
        Parameter.__init__(self, name, value, type, namespace)

    mustUnderstand = 0
    actor = None


class SOAPFault:
    """A SOAPFault object captures SOAP fault information."""
    def __init__(self, faultcode, faultstring, faultactor=None,
                 detail=None, faultcodeNS=DOM.NS_SOAP_ENV,
                 typeref=None):
        self.faultcodeNS = faultcodeNS
        self.faultcode = faultcode
        self.faultstring = faultstring
        self.faultactor = faultactor
        self.detail = detail
        self.typeref = typeref


class MIMEPart:
    """A MIMEPart object represents a MIME part of a SOAP message."""
    def __init__(self, name, content_type, data, headers={}):
        self.name = name
        self.content_type = content_type
        self.headers = headers
        if hasattr(data, 'read'):
            data = data.read()
        self.data = data


class InvalidMessage(Exception):
    pass





if __name__ == '__main__':

    message = SOAPMessage()
    message.soapAction = 'urn:xmethodsBabelFish#BabelFish'
    message.methodName = 'BabelFish'
    message.namespace = 'urn:xmethodsBabelFish'

    message.addParameter('translationmode', 'en_de', (DOM.NS_XSD, 'string'))
    message.addParameter('sourcedata', 'This is a test!', (DOM.NS_XSD, 'string'))
    message.serialize()
    print message.getMessageBody()


    message = SOAPMessage()
    message.soapAction = 'urn:xmethodsBabelFish#BabelFish'
    message.methodName = 'BabelFish'
    message.namespace = 'urn:xmethodsBabelFish'

    message.addParameter('translationmode', 'en_de', (DOM.NS_XSD, 'string'))
    message.addParameter('sourcedata', 'This is a test!', (DOM.NS_XSD, 'string'))
    message.addMimeParam('signature', 'text/html',
                         '<html>This is my sig!</html>'
                         )

    message.serialize()
    print message.getMessageBody()


=== Added File Packages/WebService/SOAPReader.py ===
# 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.

from StringIO import StringIO
from string import split
from Utility import DOM


class SOAPReader:
    """A SOAPReader provides a simplified (but still low level) interface
       for reading SOAP xml messages. It provides quick access to the major
       components of the message, which are returned as DOM elements."""

    def __init__(self, xmldata):
        if not hasattr(xmldata, 'read'):
            xmldata = StringIO(xmldata)
        self.document = DOM.loadDocument(xmldata)
        self.getEnvelope()

    def __del__(self):
        self.document.unlink()

    def getEnvelope(self):
        """Return the SOAP envelope element of the message."""
        element = getattr(self, '_env_element', None)
        if element is not None:
            return element
        element = self.document.documentElement
        if element.localName != 'Envelope':
            raise InvalidMessage(
                'Malformed or missing SOAP envelope element.'
                )
        # Initialize version information.
        version = DOM.SOAPUriToVersion(element.namespaceURI)
        if version is None:
            raise InvalidMessage(
                'Unknown SOAP envelope namespace uri.'
                )
        self.version = version
        self.NS_SOAP_ENV = DOM.GetSOAPEnvUri(self.version)
        self.NS_SOAP_ENC = DOM.GetSOAPEncUri(self.version)
        self._env_element = element
        return element

    def getHeader(self):
        """Return the SOAP header element of the message, or None if
           no header element exists in the message."""
        element = getattr(self, '_header_element', None)
        if element is not None:
            return element
        envelope = self.getEnvelope()
        element = DOM.getElement(envelope, 'Header', self.NS_SOAP_ENV, None)
        self._header_element = element
        return element

    def getHeaderElements(self):
        """Return the sequence of elements that appear in the SOAP header."""
        elements = getattr(self, '_header_elements', None)
        if elements is not None:
            return elements        
        header = self.getHeader()
        if header is not None:
            self._header_elements = DOM.getElements(header, None, None)
        else:
            self._header_elements = []
        return self._header_elements

    def getHeaderElement(self, name, namespaceURI=None):
        """Return the element that appears in the SOAP header matching the
           given name and (optional) namespace uri. A KeyError will be
           raised if the named element is not present in the SOAP header."""
        header = self.getHeader()
        if header is None:
            raise KeyError, name
        result = DOM.getElement(header, name, namespaceURI, None)
        if result is None:
            raise KeyError, name
        return result

    def getMustUnderstandHeaders(self):
        """Return a sequence of the elements that appear in the SOAP header
           that have a true value for the 'mustUnderstand' attribute."""
        elements = getattr(self, '_must_understand', None)
        if elements is not None:
            return elements
        self._must_understand = []
        for element in self.getHeaderElements():
            if DOM.getAttr(element, 'mustUnderstand', None) == '1':
                self._must_understand.append(element)
        return self._must_understand

    def getBody(self):
        """Return the SOAP body element of the message."""
        element = getattr(self, '_body_element', None)
        if element is not None:
            return element
        envelope = self.getEnvelope()
        element = DOM.getElement(envelope, 'Body', self.NS_SOAP_ENV, None)
        if element is None:
            raise InvalidMessage(
                'Malformed or missing SOAP body element.'
                )
        self._body_element = element
        return element

    def getBodyElements(self):
        """Return the sequence elements that appear in the SOAP body."""
        elements = getattr(self, '_body_elements', None)
        if elements is not None:
            return elements
        self._body_elements = DOM.getElements(self.getBody(), None, None)
        return self._body_elements

    def getBodyElement(self, name, namespaceURI=None):
        """Return the element that appears in the SOAP body matching the
           given name and (optional) namespace uri. A KeyError will be
           raised if the named element is not present in the SOAP body."""
        result = DOM.getElement(self.getBody(), name, namespaceURI, None)
        if result is None:
            raise KeyError, name
        return result

    def getRPCStruct(self):
        """Return the rpc struct (first element) of the SOAP body, or
           None if the SOAP body element contains no child elements."""
        element = getattr(self, '_rpc_element', self)
        if element is not self:
            return element
        body_elements = self.getBodyElements()
        self._rpc_element = None
        if len(body_elements):
            self._rpc_element = body_elements[0]
        else:
            self._rpc_element = None
        return self._rpc_element

    def getRPCParams(self):
        """Return the child elements of the rpc struct of the SOAP message."""
        params = getattr(self, '_rpc_params', None)
        if params is not None:
            return params
        rpc_struct = self.getRPCStruct()
        if rpc_struct is not None:
            self._rpc_params = DOM.getElements(self.getRPCStruct(), None, None)
        else:
            self._rpc_params = []
        return  self._rpc_params

    def getRPCParam(self, name, namespaceURI=None):
        """Return the child element of the rpc struct of the message that
           matches the given name and (optional) namespace uri. A KeyError
           will be raised if the named parameter is not present."""
        rpc_struct = self.getRPCStruct()
        if rpc_struct is None:
            raise KeyError, name
        result = DOM.getElement(rpc_struct, name, namespaceURI, None)
        if result is None:
            raise KeyError, name
        return result

    def getRPCResult(self):
        """Return the first element of the rpc struct of the message, or
           None if the rpc struct of the message has no child elements."""
        elements = DOM.getElements(self.getRPCStruct(), None, None)
        if not len(elements):
            return None
        return elements[0]

    def getElementByRef(self, reference):
        """Return an (independent) element given an element id reference,
           or raise a KeyError if the referenced element is not found."""
        if reference[0] != '#':
            raise ValueError, 'Invalid reference: %s' % reference
        return self.getElementById(reference[1:])

    def getElementById(self, element_id):
        """Return an (independent) element given an element id, or raise 
           a KeyError if no matching element is found in the document."""
        element_map = getattr(self, '_element_map', None)
        if element_map is not None:
            return element_map[element_id]
        self._element_map = DOM.getMappingById(self.document)
        return self._element_map[element_id]

    def derefElement(self, element):
        """Dereference a DOM element if it has an href attribute. If the
           element has no href attribute, the passed in element is returned.
           If the referenced element is not found, a KeyError is raised."""
        reference = DOM.getAttr(element, 'href', None, None)
        if reference is not None:
            return self.getElementByRef(reference)
        return element

    def getEncodingStyle(self, element):
        """Given a DOM element of the SOAP message, return the encoding
           style that applies in the context of that element, or None
           if no encoding claims are made in the context of element."""
        result = None
        while 1:
            if element.nodeType is not 1:
                element = element.parentNode
                continue
            result = DOM.getAttr(
                element, 'encodingStyle', self.NS_SOAP_ENV, None
                )
            if result is not None:
                break
            element = element.parentNode
            if element.nodeType is 9:
                break
        return result == '' and None or result

    def isFaultMessage(self):
        """Return true if the SOAP message contains a fault."""
        return self.getFault() is not None

    def getFault(self):
        """Return the SOAP fault element of the message, or None if the
           document does not contain a fault element."""
        element = getattr(self, '_fault_element', self)
        if element is not self:
            return element
        body = self.getBody()
        element = DOM.getElement(body, 'Fault', None, None)
        self._fault_element = element
        return element

    def getFaultString(self):
        """Return the SOAP faultstring *value* as a string, or None if
           the document contains no fault or no faultstring element."""
        return self._faultElementStr('faultstring')

    def getFaultCode(self):
        """Return the SOAP faultcode *value* as a string, or None if
           the document contains no fault or no faultcode element."""
        result = getattr(self, '_fault_code', self)
        if result is not self:
            return result
        fault = self.getFault()
        self._fault_code_ns = None
        self._fault_code = None
        if fault is None:
            return None
        element = DOM.getElement(fault, 'faultcode', None, None)
        if element is None:
            return None
        fault_code = DOM.getElementText(element)
        parts = split(fault_code, ':', 1)
        self._fault_code = parts[-1]
        if len(parts) == 2:
            self._fault_code_ns = DOM.findNamespaceURI(parts[0], element)
        return self._fault_code
                             
    def getFaultCodeNS(self):
        """Return the namespace uri of the faultcode value, or None if
           the document contains no faultcode element or the value is
           not qualified with a namespace prefix."""
        self.getFaultCode()
        return self._fault_code_ns

    def getFaultActor(self):
        """Return the SOAP faultactor *value* as a string, or None."""
        return self._faultElementStr('faultactor')

    def getFaultDetail(self):
        """Return the SOAP faultdetail element of the message, or None."""
        fault = self.getFault()
        if fault is None:
            return None
        return DOM.getElement(fault, 'detail', None, None)

    def _faultElementStr(self, attrname):
        fault = self.getFault()
        if fault is None:
            return None
        element = DOM.getElement(fault, attrname, None, None)
        if element is None:
            return None
        return DOM.getElementText(element)
            

class InvalidMessage(Exception):
    pass


=== Added File Packages/WebService/SOAPWriter.py ===
# 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.

from XMLWriter import XMLWriter
from Utility import DOM


class SOAPWriter(XMLWriter):
    """A SOAPWriter provides a simplified interface for writing SOAP xml
       messages. It extends the basic XMLWriter utility with convenience
       methods for writing the major structures of a SOAP message."""

    def __init__(self, version='1.1', encoding='UTF-8'):
        XMLWriter.__init__(self, encoding)
        self.NS_SOAP_ENV = DOM.GetSOAPEnvUri(version)
        self.NS_SOAP_ENC = DOM.GetSOAPEncUri(version)
        self.version = version
        self.declareNSPrefix('SOAP-ENV', self.NS_SOAP_ENV)
        self.declareNSPrefix('SOAP-ENC', self.NS_SOAP_ENC)

    def startEnvelope(self, encodingStyle=None):
        """Begin the SOAP envelope element of the message."""
        self._dup_check('_envelope')
        element = self.startElement('Envelope', self.NS_SOAP_ENV)
        if encodingStyle is not None:
            self.writeEncodingStyle(encodingStyle)
        self._envelope = element
        return element

    def endEnvelope(self):
        """End the SOAP envelope element of the message."""
        self._stack.pop()

    def startHeader(self, encodingStyle=None):
        """Begin the SOAP header element of the message."""
        self._assert('_envelope')
        self._dup_check('_header')
        element = self.startElement('Header', self.NS_SOAP_ENV)
        if encodingStyle is not None:
            self.writeEncodingStyle(encodingStyle)
        self._header = element
        return element

    def endHeader(self):
        """End the SOAP header element of the message."""
        self._stack.pop()

    def startHeaderElement(self, name, namespaceURI, mustUnderstand=None,
                           actor=None):
        """Begin a SOAP header entry element in the message."""
        self._assert('_header')
        self._stack.append(self._header)
        element = self.startElement(name, namespaceURI)
        if mustUnderstand is not None:
            self.writeAttr('mustUnderstand', '1')
        if actor is not None:
            self.writeAttr('actor', actor)
        return element

    def endHeaderElement(self):
        """End a SOAP header entry element of the message."""
        self._stack.pop()
        self._stack.pop()

    def startBody(self, encodingStyle=None):
        """Begin the SOAP body element of the message."""
        self._assert('_envelope')
        self._dup_check('_body')
        element = self.startElement('Body', self.NS_SOAP_ENV)
        if encodingStyle is not None:
            self.writeEncodingStyle(encodingStyle)
        self._body = element
        return element

    def endBody(self):
        """End the SOAP body element of the message."""
        self._stack.pop()

    def startBodyElement(self, name, namespaceURI=None):
        """Begin a new child element of the SOAP body element."""
        self._assert('_body')
        self._stack.append(self._body)
        return self.startElement(name, namespaceURI)

    def endBodyElement(self):
        """End a child element of the SOAP body element."""
        self._stack.pop()
        self._stack.pop()

    def startTrailerElement(self, name, namespaceURI=None):
        """Begin a new child element of the SOAP envelope element that 
           follows the SOAP header and body elements of the message."""
        self._assert('_envelope')
        self._stack.append(self._envelope)
        return self.startElement(name, namespaceURI)

    def endTrailerElement(self):
        """End a trailing child element of the SOAP envelope element."""
        self._stack.pop()
        self._stack.pop()

    def writeEncodingStyle(self, encodingStyle):
        """Write a SOAP encoding style attribute the current element."""
        self.writeAttr('encodingStyle', encodingStyle, self.NS_SOAP_ENV)

    def startFault(self, faultcode, faultstring, faultactor=None,
                   faultcodeNS=None):
        """Begin the SOAP fault element of the message."""
        self._assert('_body')
        self._dup_check('_fault')
        self._stack.append(self._body)
        element = self.startElement('Fault', self.NS_SOAP_ENV)
        self._fault = element

        codestr = self.makeQName(faultcodeNS or self.NS_SOAP_ENV, faultcode)
        self.startElement('faultcode')
        self.writeString(codestr)
        self.endElement()

        self.startElement('faultstring')
        self.writeString(faultstring)
        self.endElement()

        if faultactor is not None:
            self.startElement('faultactor')
            self.writeString(faultactor)
            self.endElement()

    def endFault(self):
        """End the SOAP fault element of the message."""
        self._stack.pop()
        self._stack.pop()

    def startFaultDetail(self):
        """Begin the fault detail element of the message."""
        self._assert('_fault')
        self._stack.append(self._fault)
        element = self.startElement('detail', None)
        return element

    def endFaultDetail(self):
        """End the fault detail element of the message."""
        self._stack.pop()
        self._stack.pop()

    def _dup_check(self, name):
        if getattr(self, name, None) is not None:
            raise WriterError(
                '%s element already started.' % name[1:]
                )

    def _assert(self, name):
        if not hasattr(self, name):
            raise WriterError(
                '%s element must be started.' % name[1:]
                )
        

class WriterError(Exception):
    pass


=== Added File Packages/WebService/Serializer.py === (851/951 lines abridged)
# 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.

import string, types, base64, re
from Utility import DOM


class SerializationContext:
    """A SerializationContext maintains per-message serialization state
       and provides a common container used to pass around various data
       structures used in data serialization (including a reference to
       the serializer, which is required by complex type handlers)."""
    def __init__(self, serializer):
        self.serializer = serializer
        self.write_ns = 0
        self._refmap = {}

    NS_XSI = DOM.NS_XSI
    reader = None
    writer = None
    strict = 1

    def isMultiRef(self, value):
        """Return true if a value should be encoded as multi-reference."""
        return self.ref_map.get(id(value), 1) != 1

    def mapValueRefs(self, values):
        """Map reference relationships amongst a set of values to
           enable correct SOAP serialization of multiref values."""
        self._refmap = mapping = {}
        for value in values:
            self._map_object(value, mapping)

    def _map_object(self, object, mapping, isclass=0):
        ob_type = type(object)
        ob_id = id(object)

        if ob_type in (types.StringType, types.UnicodeType, types.BufferType):
            mapping[ob_id] = mapping.get(ob_id, 0) + 1
            return
        elif ob_type in (types.TupleType, types.ListType):
            mapping[ob_id] = mapping.get(ob_id, 0) + 1
            for value in object:
                self._map_object(value, mapping)

[-=- -=- -=- 851 lines omitted -=- -=- -=-]

   xsd:long                                   long

   xsd:int                                    int
   xsd:short                                  int
   xsd:unsignedShort                          int
   xsd:byte                                   int
   xsd:unsignedByte                           int
   
   xsd:decimal                                float
   xsd:double                                 float
   xsd:float                                  float

   xsd:string                                 string
   xsd:normalizedString                       string
   xsd:anyURI                                 string
   xsd:QName                                  string
   xsd:Name                                   string
   xsd:NCName                                 string
   xsd:token                                  string
   xsd:language                               string

   xsd:NOTATION                               string
   xsd:NMTOKENS                               sequence
   xsd:NMTOKEN                                string
   xsd:IDREFS                                 sequence
   xsd:IDREF                                  string
   xsd:ENTITIES                               sequence
   xsd:ENTITY                                 string
   xsd:ID                                     string

   xsd:dateTime                               ?
   xsd:timePeriod                             ? (99)
   xsd:duration                               ? (01)
   xsd:time                                   ?
   xsd:date                                   ?
   xsd:gYearMonth                             ? (01)
   xsd:gYear                                  ? (01)
   xsd:gMonthDay                              ? (01)
   xsd:gDay                                   ? (01)
   xsd:gMonth                                 ? (01)
   
   xsd:base64Binary                           string
   xsd:base64                                 string
   xsd:hexBinary                              string
   
   enc:base64                                 string
   enc:arrayType                              sequence


"""


=== Added File Packages/WebService/ServiceProxy.py ===
# 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.

from Serializer import Serializer, SerializationContext
from SOAPCallInfo import callInfoFromWSDL
from Transports import HTTPTransport
from SOAPMessage import SOAPMessage
from WSDLTools import WSDLReader
import weakref


class ServiceProxy:
    """A ServiceProxy provides a convenient way to call a remote web
       service that is described with WSDL. The proxy exposes methods
       that reflect the methods of the remote web service."""

    def __init__(self, wsdl, service=None, port=None):
        if not hasattr(wsdl, 'targetNamespace'):
            wsdl = WSDLReader().loadFromURL(wsdl)
        self._serializer = Serializer()
        self._transport = HTTPTransport()
        for item in wsdl.types.items():
            self._serializer.loadSchema(item)
        self._service = wsdl.services[service or 0]
        self.__doc__ = self._service.documentation
        self._port = self._service.ports[port or 0]
        self._name = self._service.name
        self._wsdl = wsdl
        binding = self._port.getBinding()
        portType = binding.getPortType()
        for item in portType.operations:
            callinfo = callInfoFromWSDL(self._port, item.name)
            method = MethodProxy(self, callinfo)
            setattr(self, item.name, method)

    def _call(self, name, *args, **kwargs):
        """Call the named remote web service method."""
        if len(args) and len(kwargs):
            raise TypeError(
                'Use positional or keyword argument only.'
                )

        callinfo = getattr(self, name).callinfo
        params = callinfo.getInParameters()

        arglist = args or []
        if kwargs:
            for item in params:
                if not kwargs.has_key(item.name):
                    raise TypeError(
                        'Missing keyword argument: %s.' % item.name
                        )
                argval = kwargs[item.name]
                arglist.append(argval)

        if len(arglist) != len(params):
            raise TypeError(
                '%s takes exactly %d argument%s (%d given)' % (
                self.name,
                len(params),
                len(params) != 1 and 's' or '',
                len(arglist)
                ))

        message = SOAPMessage()
        message.serializer = self._serializer
        message.methodName = callinfo.methodName
        message.namespace = callinfo.namespace
        message.style = callinfo.style

        for i in range(len(params)):
            param = params[i]
            value = arglist[i]
            message.addParameter(param.name, value, param.type)

        message.serialize()
        xmldata = message.getMessageBody()

        print xmldata
        
        resp = self._transport.send(
            callinfo.location,
            callinfo.soapAction,
            xmldata
            )

        if resp is None:
            return None

        message = SOAPMessage(resp.body)
        message.serializer = self._serializer
        message.style = callinfo.style

        print resp.body

        message.deserialize()

        params = message.getParameters()
        pcount = len(params)
        
        if pcount == 0:
            return None

        if pcount == 1:
            return params[0].value

        values = {}
        for param in params:
            value[param.name] = param.value
        return values


class MethodProxy:
    """ """
    def __init__(self, parent, callinfo):
        self.__name__ = callinfo.methodName
        self.__doc__ = callinfo.documentation
        self.callinfo = callinfo
        self.parent = weakref.ref(parent)

    def __call__(self, *args, **kwargs):
        return self.parent()._call(self.__name__, *args, **kwargs)


=== Added File Packages/WebService/TimeoutSocket.py ===
# 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.

"""Based on code from timeout_socket.py, with some tweaks for compatibility
   and efficiency. 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>
"""
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 Timeout('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


=== Added File Packages/WebService/Transports.py ===
# 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.

import string, httplib, smtplib, socket
from TimeoutSocket import TimeoutSocket
from TimeoutSocket import TimeoutError
from urlparse import urlparse


class HTTPTransport:
    """Manages the transport of SOAP messages over the HTTP protocol."""

    def __init__(self, timeout=20):
        self.timeout = timeout
        self.redirects = {}

    userAgent = 'Python WebService Toolkit'
    followRedirects = 1

    # This implementation maintains a cache shared by transport instances
    # that remembers redirects and demands for M-POST (if anyone uses it).
    _req_cache = {}
    
    def send(self, address, soapAction, message, contentType='text/xml',
             headers={}):
        """Send a SOAP message using HTTP, returning an HTTPResponse."""
        address, verb = self._req_cache.get(address, (address, 'POST'))

        scheme, host, path, params, query, frag = urlparse(address)
        if params: path = '%s;%s' % (path, params)
        if query:  path = '%s?%s' % (path, query)
        if frag:   path = '%s#%s' % (path, frag)

        if hasattr(message, 'getvalue'):
            body = message.getvalue()
        elif hasattr(message, 'read'):
            body = message.read()
        else: body = message

        if scheme == 'https':
            if not hasattr(socket, 'ssl'):
                raise ValueError(
                    'This Python installation does not have SSL support.'
                    )
            conn = TimeoutHTTPS(host, None, self.timeout)
        else:
            conn = TimeoutHTTP(host, None, self.timeout)

        conn.putrequest(verb, path)

        if verb == 'M-POST':
            conn.putheader(
                'Man', '"http://schemas.xmlsoap.org/soap/envelope/"; ns=01'
                )

        for name, value in headers.items():
            conn.putheader(name, value)

        sentheader = headers.has_key

        if not sentheader('SOAPAction') or sentheader('01-SOAPAction'):
            header = verb == 'POST' and 'SOAPAction' or '01-SOAPAction'
            conn.putheader(header, soapAction)

        if not sentheader('Connection'):
            conn.putheader('Connection', 'close')

        if not sentheader('User-Agent'):
            conn.putheader('User-Agent', self.userAgent)

        if not sentheader('Content-Type'):
            conn.putheader('Content-Type', contentType)

        if not sentheader('Content-Length'):
            conn.putheader('Content-Length', str(len(body)))

        conn.endheaders()
        conn.send(body)

        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 the server only supports M-POST, we will try again using
        # the HTTP extension framework (may never happen in practice).
        if status == 510 and verb == 'POST':
            response.close()
            self._req_cache[address] = address, 'M-POST'
            return self.send(address, soapAction, message, headers)

        # If we get an HTTP redirect, we will follow it automatically.
        if status >= 300 and status < 400 and self.followRedirects:
            location = response.msg.getheader('location')
            if location is not None:
                response.close()
                if self.redirects.has_key(location):
                    raise RecursionError(
                        'Circular HTTP redirection detected.'
                        )
                self.redirects[location] = 1
                self._req_cache[address] = location, verb
                return self.send(location, soapAction, message, headers)
            raise HTTPResponse(response)

        # Otherwise, any non-2xx response may or may not not contain a
        # meaningful SOAP message. A 500 error *may* contain a message,
        # so we will raise an HTTP error unless the response is xml.
        if not (status >= 200 and status < 300):
            content_type =  response.msg.getheader('content-type', '')
            if content_type[:8] != 'text/xml':
                raise HTTPResponse(response)

        return HTTPResponse(response)


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 SMTPTransport:
    """Manages the transport of SOAP messages over the SMTP protocol."""

    def __init__(self, smtphost, fromaddr, subject, timeout=20):
        self.smtphost = smtphost
        self.fromaddr = fromaddr
        self.subject = subject
        self.timeout = timeout

    def send(self, address, soapAction, message, contentType='text/xml',
             headers=None):
        """Send a SOAP message object via SMTP. Messages sent via
           SMTP are by definition one-way, so this always returns
           None on success or raises an exception from smtplib if
           an error occurs while attempting to send the message."""

        if address[:7] == 'mailto:':
            scheme, host, address, params, query, frag = urlparse(address)

        if hasattr(message, 'read'):
            message = message.read()

        smtpheaders = []
        if headers is not None:
            for name, value in headers.items():
                smtpheaders.append('%s: %s' % (name, value))
        smtpheaders.append('SOAPAction: %s' % soapAction)
        smtpheaders.append('Subject: %s' % self.subject)
        smtpheaders.append('To: <%s>' % address)

        if not headers.has_key('Content-Type'):
            smtpheaders.append('Content-Type: %s' % contentType)

        msgdata = '%s\r\n%s' % (
            string.join(smtpheaders, '\r\n'),
            message
            )
        server = TimeoutSMTP(self.smtphost, 0, self.timeout)
        server.sendmail(self.fromaddr, address, msgdata)
        server.quit()

        return None


from httplib import HTTPConnection, HTTPSConnection
from smtplib import SMTP, SMTP_PORT

class TimeoutHTTP(HTTPConnection):
    """A custom http 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 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((self.host, self.port))


class TimeoutHTTPS(HTTPSConnection):
    """A custom http object that supports socket timeout."""
    def __init__(self, host, port=None, timeout=20):
        HTTPConnection.__init__(self, str(host), port)
        self.timeout = timeout

    def connect(self):
#        sock = TimeoutSocket(self.timeout)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((self.host, self.port))
        realsock = getattr(sock, '_sock', sock)
        ssl = socket.ssl(realsock, self.key_file, self.cert_file)
        self.sock = httplib.FakeSocket(sock, ssl)


class TimeoutSMTP(SMTP):
    """A custom smtp object that supports socket timeout."""

    def __init__(self, host='', port=0, timeout=20):
        self.timeout = timeout
        SMTP.__init__(self, str(host), port)

    def connect(self, host='localhost', port = 0):
        if not port:
            i = host.find(':')
            if i >= 0:
                host, port = host[:i], host[i+1:]
                try: port = int(port)
                except ValueError:
                    raise socket.error, "nonnumeric port"
        if not port: port = SMTP_PORT
        self.sock = TimeoutSocket(self.timeout)
        if self.debuglevel > 0: print 'connect:', (host, port)
        try:
            self.sock.connect((host, port))
        except socket.error:
            self.close()
            raise
        (code,msg)=self.getreply()
        if self.debuglevel >0 : print "connect:", msg
        return (code,msg)


=== Added File Packages/WebService/Utility.py === (463/563 lines abridged)
# 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.

from string import join, strip, split
from UserDict import UserDict
from StringIO import StringIO
from urllib import urlopen
import xml.dom.minidom
import weakref


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:

[-=- -=- -=- 463 lines omitted -=- -=- -=-]

        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


=== Added File Packages/WebService/WSDLTools.py === (1281/1381 lines abridged)
# 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.

from urllib import urlopen, basejoin
from Utility import DOM, Collection
from XMLSchema import XMLSchema
from XMLWriter import XMLWriter
from StringIO import StringIO
import md5


class WSDLReader:
    """A WSDLReader creates WSDL instances from urls and xml data."""

    # Custom subclasses of WSDLReader may wish to implement a caching
    # strategy or other optimizations. Because application needs vary 
    # so widely, we don't try to provide any caching by default.

    def loadFromStream(self, file, checksum=None):
        """Return a WSDL instance loaded from a file object."""
        document = DOM.loadDocument(file)
        wsdl = WSDL()
        wsdl.load(document)
        self.checkMd5Hash(wsdl, checksum)
        return wsdl

    def loadFromURL(self, url, checksum=None):
        """Return a WSDL instance loaded from the given url."""
        file = urlopen(url)
        try: document = DOM.loadDocument(file)
        finally: file.close()
        wsdl = WSDL()
        wsdl.location = url
        wsdl.load(document)
        self.checkMd5Hash(wsdl, checksum)
        return wsdl

    def loadFromString(self, data, checksum=None):
        """Return a WSDL instance loaded from an xml string."""
        return self.loadFromStream(StringIO(data), checksum)

    def loadFromFile(self, filename, checksum=None):
        """Return a WSDL instance loaded from the given file."""
        file = open(filename, 'rb')

[-=- -=- -=- 1281 lines omitted -=- -=- -=-]

    docnode = DOM.getElement(element, 'documentation', None, None)
    if docnode is not None:
        return DOM.getElementText(docnode)
    return ''

def GetExtensions(element):
    result = []
    for item in DOM.getElements(element, None, None):
        if item.namespaceURI != DOM.NS_WSDL:
            result.append(item)
    return result

def ExtensionToXML(writer, object):
    if hasattr(object, 'toXML'):
        object.toXML(writer)
    else:
        strval = DOM.elementToString(object)
        writer.writeXML(strval)

def FindExtensions(object, kind, t_type=type(())):
    result = []
    if isinstance(kind, t_type):
        namespaceURI, name = kind
        for item in object.extensions:
            if not hasattr(item, 'nodeType'):
                continue
            if DOM.nsUriMatch(namespaceURI, item.namespaceURI) and \
               item.name == name:
                result.append(item)
    else:
        for item in object.extensions:
            if isinstance(item, kind):
                result.append(item)
    return result

def FindExtension(object, kind, t_type=type(())):
    if isinstance(kind, t_type):
        namespaceURI, name = kind
        for item in object.extensions:
            if not hasattr(item, 'nodeType'):
                continue
            if DOM.nsUriMatch(namespaceURI, item.namespaceURI) and \
               item.name == name:
                return item
    else:
        for item in object.extensions:
            if isinstance(item, kind):
                return item
    return None



=== Added File Packages/WebService/XMLSchema.py ===
# 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.

from Utility import DOM, Collection
from urllib import urlopen, basejoin
from StringIO import StringIO
import string, types, base64, re


class SchemaReader:
    """A SchemaReader creates XMLSchema objects from urls and xml data."""

    def loadFromStream(self, file):
        """Return an XMLSchema instance loaded from a file object."""
        document = DOM.loadDocument(file)
        return self.loadFromDOM(document)

    def loadFromString(self, data):
        """Return an XMLSchema instance loaded from an xml string."""
        return self.loadFromStream(StringIO(data))

    def loadFromURL(self, url):
        """Return an XMLSchema instance loaded from the given url."""
        file = urlopen(url)
        try:     schema = self.loadFromStream(file)
        finally: file.close()
        return schema

    def loadFromFile(self, filename):
        """Return an XMLSchema instance loaded from the given file."""
        file = open(filename, 'rb')
        try:     schema = self.loadFromStream(file)
        finally: file.close()
        return schema


class XMLSchema:
    # This is temporary, for the benefit of WSDL until the real thing works.
    def __init__(self, element):
        self.targetNamespace = DOM.getAttr(element, 'targetNamespace')
        self.element = element

    def toXML(self, writer):
        strval = DOM.elementToString(self.element)
        writer.writeXML(strval)


class realXMLSchema:
    """A schema is a collection of schema components derived from one
       or more schema documents, that is, one or more <schema> element
       information items. It represents the abstract notion of a schema
       rather than a single schema document (or other representation)."""
    def __init__(self):
        self.simpleTypes = Collection(self)
        self.complexTypes = Collection(self)
        self.attributes = Collection(self)
        self.elements = Collection(self)
        self.attrGroups = Collection(self)
        self.idConstraints=None
        self.modelGroups = None
        self.notations = None

    def load(self, document):
        if document.nodeType == document.DOCUMENT_NODE:
            schema = DOM.getElement(document, 'schema', None, None)
        else:
            schema = document
        if schema is None:
            raise SchemaError('Missing <schema> element.')

        # Check nsuri here

        self.namespace = schema.namespaceURI
        self.attributeFormDefault = DOM.getAttr(
            schema, 'attributeFormDefault', None, 'unqualified'
            )
        self.elementFormDefault = DOM.getAttr(
            schema, 'elementFormDefault', None, 'unqualified'
            )

        self.targetNamespace = DOM.getAttr(schema, 'targetNamespace',
                                           None, None)
        self.name = DOM.getAttr(definitions, 'name', None, None)
        self.documentation = GetDocumentation(definitions)

        # Resolve (recursively) any import elements in the document.
        imported = {}
        while 1:
            imports = []
            for element in DOM.getElements(definitions, 'import', NS_WSDL):
                location = DOM.getAttr(element, 'location')
                if not imported.has_key(location):
                    imports.append(element)
            if not imports:
                break
            for element in imports:
                self._import(document, element)
                imported[location] = 1

        for element in DOM.getElements(definitions, None, None):
            localName = element.localName

            if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL):
                if localName == 'schema':
                    self.types.addSchema(XMLSchema(element))
                else:
                    self.extensions.append(element)
                continue

            elif localName == 'message':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                message = self.addMessage(name, docs)
                parts = DOM.getElements(element, 'part', NS_WSDL)
                message.load(parts)
                continue

            elif localName == 'portType':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                ptype = self.addPortType(name, docs)
                operations = DOM.getElements(element, 'operation', NS_WSDL)
                ptype.load(operations)
                continue

            elif localName == 'binding':
                name = DOM.getAttr(element, 'name')
                type = DOM.getAttr(element, 'type', default=None)
                if type is None:
                    raise WSDLError(
                        'Missing type attribute for binding %s.' % name
                        )
                type = type.split(':', 1)[-1]
                docs = GetDocumentation(element)
                binding = self.addBinding(name, type, docs)
                operations = DOM.getElements(element, 'operation', NS_WSDL)
                binding.load(operations)
                binding.load_ex(GetExtensions(element))
                continue

            elif localName == 'service':
                name = DOM.getAttr(element, 'name')
                docs = GetDocumentation(element)
                service = self.addService(name, docs)
                ports = DOM.getElements(element, 'port', NS_WSDL)
                service.load(ports)
                service.load_ex(GetExtensions(element))
                continue

            elif localName == 'types':
                self.types.documentation = GetDocumentation(element)
                for item in DOM.getElements(element, None, None):
                    if item.localName == 'schema':
                        self.types.addSchema(XMLSchema(item))
                    else:
                        self.types.addExtension(item)
                continue

    def _import(self, document, element):
        namespace = DOM.getAttr(element, 'namespace', default=None)
        location = DOM.getAttr(element, 'location', default=None)
        if namespace is None or location is None:
            raise WSDLError(
                'Invalid import element (missing namespace or location).'
                )

        # Sort-of support relative locations to simplify unit testing. The
        # WSDL specification actually doesn't allow relative URLs, so its
        # ok that this only works with urls relative to the initial document.
        location = basejoin(self.location, location)

        obimport = self.addImport(namespace, location)
        obimport._loaded = 1

        importdoc = DOM.loadFromURL(location)
        try:
            if location.find('#') > -1:
                idref = location.split('#')[-1]
                imported = DOM.getElementById(importdoc, idref)
            else:
                imported = importdoc.documentElement
            if imported is None:
                raise WSDLError(
                    'Import target element not found for: %s' % location
                    )

            imported_tns = DOM.getAttr(imported, 'targetNamespace')
            importer_tns = namespace

            if imported_tns != importer_tns:
                return

            if imported.localName == 'definitions':
                imported_nodes = imported.childNodes
            else:
                imported_nodes = [imported]
            parent = element.parentNode
            for node in imported_nodes:
                if node.nodeType != node.ELEMENT_NODE:
                    continue
                child = DOM.importNode(document, node, 1)
                parent.appendChild(child)
                child.setAttribute('targetNamespace', importer_tns)
                attrsNS = imported._attrsNS
                for attrkey in attrsNS.keys():
                    if attrkey[0] == DOM.NS_XMLNS:
                        attr = attrsNS[attrkey].cloneNode(1)
                        child.setAttributeNode(attr)
        finally:
            importdoc.unlink()




class SimpleTypeDefinition:
    """Represents an xml schema simple type definition."""

class ComplexTypeDefinition:
    """Represents an xml schema complex type definition."""

class AttributeDeclaration:
    """Represents an xml schema attribute declaration."""

class ElementDeclaration:
    """Represents an xml schema element declaration."""

class AttributeGroupDefinition:
    """Represents an xml schema attribute group definition."""

class IdentityConstraintDefinition:
    """Represents an xml schema identity constraint definition."""

class ModelGroupDefinition:
    """Represents an xml schema model group definition."""

class NotationDeclaration:
    """Represents an xml schema notation declaration."""

class Annotation:
    """Represents an xml schema annotation."""

class ModelGroup:
    """Represents an xml schema model group."""

class Particle:
    """Represents an xml schema particle."""

class WildCard:
    """Represents an xml schema wildcard."""

class AttributeUse:
    """Represents an xml schema attribute use."""


class ElementComponent:
    namespace = ''
    name = ''
    type = None
    form = 'qualified | unqualified'
    scope = 'global or complex def'
    constraint = ('value', 'default | fixed')
    nillable = 0
    id_constraint_defs = None
    sub_group_affil = None
    sub_group_exclusions = None
    disallowed_subs = 'substitution, extension, restriction'
    abstract = 0
    minOccurs = 1
    maxOccurs = 1
    ref = ''

class AttributeThing:
    name = ''
    namespace = ''
    typeName = ''
    typeUri = ''
    scope = 'global | local to complex def'
    constraint = ('value:default', 'value:fixed')
    use = 'optional | prohibited | required'

class ElementDataType:
    namespace = ''
    name = ''
    element_form = 'qualified | unqualified'
    attr_form = None
    type_name = ''
    type_uri = ''
    def __init__(self, name, namespace, type_name, type_uri):
        self.namespace = namespace
        self.name = name
        # type may be anonymous...
        self.type_name = type_name
        self.type_uri = type_uri

    def checkValue(self, value, context):
        # Delegate value checking to the type of the element.
        typeref = (self.type_uri, self.type_name)
        handler = context.serializer.getType(typeref)
        return handler.checkValue(value, context)

    def serialize(self, name, namespace, value, context, **kwargs):
        if context.check_values:
            self.checkValue(value, context)
        # Delegate serialization to the type of the element.
        typeref = (self.type_uri, self.type_name)
        handler = context.serializer.getType(typeref)
        return handler.serialize(self.name, self.namespace, value, context)

    def deserialize(self, element, context):
        if element_is_null(element, context):
            return None
        # Delegate deserialization to the type of the element.
        typeref = (self.type_uri, self.type_name)
        handler = context.serializer.getType(typeref)
        return handler.deserialize(element, context)



def parse_schema(data):
    targetNS = ''
    attributeFormDefault = 0
    elementFormDefault = 0
    blockDefault = ''
    finalDefault = ''
    language = None
    version = None
    id = ''


=== Added File Packages/WebService/XMLWriter.py ===
# 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.

from StringIO import StringIO
from Utility import DOM


class XMLWriter:
    """An XMLWriter provides a simplified interface for writing xml
       documents. The underlying DOM document may be accessed through
       the 'document' attribute of the writer. Note that the lifetime
       of the DOM document is bound to the lifetime of the writer."""

    def __init__(self, encoding='UTF-8'):
        self.encoding = encoding
        self.document = None
        self._stack = []
        self._nsmap = {}

    def __del__(self):
        if self.document is not None:
            self.document.unlink()
            self.document = None

    def startElement(self, name, namespaceURI=None, **attrs):
        """Begin a new element at the current point in the document."""
        tagname = self.makeQName(namespaceURI, name)
        if self.document is None:
            self.document = DOM.createDocument(namespaceURI, tagname)
            element = self.document.childNodes[0]
            self._stack.append(element)
            for name, value in attrs.items():
                self.writeAttr(name, value)
            return element
        if namespaceURI is not None:
            element = self.document.createElementNS(namespaceURI, tagname)
        else:
            element = self.document.createElement(tagname)
        stack = self._stack
        stack[-1].appendChild(element)
        stack.append(element)
        for name, value in attrs.items():
            self.writeAttr(name, value)
        return element

    def endElement(self):
        """End the last started element."""
        self._stack.pop()

    def currentElement(self):
        """Return the currently active DOM element of the writer."""
        return self._stack[-1]
        
    def writeAttr(self, name, value, namespaceURI=None):
        """Write an attribute to the current open element."""
        element = self._stack[-1]
        if namespaceURI is not None:
            attrname = self.makeQName(namespaceURI, name)
            element.setAttributeNS(namespaceURI, attrname, value)
        else:
            element.setAttribute(name, value)

    def writeText(self, value):
        """Write a string to the current element in the xml stream.
           Special characters in the given value will be escaped."""
        textnode = self.document.createTextNode(value)
        self._stack[-1].appendChild(textnode)

    def writeCDATA(self, value):
        """Write a CDATA section at the current point in the stream."""
        textnode = self.document.createCDATASection(value)
        self._stack[-1].appendChild(textnode)

    def writeXML(self, value):
        """Write a literal xml string to the stream. The data passed
           will not be escaped or modified on output."""
        textnode = LiteralText(value)
        textnode.ownerDocument = self.document
        self._stack[-1].appendChild(textnode)

    def declareNSDefault(self, namespaceURI):
        """Declare the default namespace uri to be used in the document."""
        if hasattr(self, '_nsdefault'):
            raise WriterError(
                'A default namespace is already set.'
                )
        self._nsdefault = namespaceURI
        self._nsmap[namespaceURI] = None

    def declareNSPrefix(self, prefix, namespaceURI):
        """Add an xml namespace prefix declaration to the document. All
           namespace declarations are written to the top level element."""
        if self._nsmap.has_key(namespaceURI):
            raise WriterError(
                'A prefix has already been declared for: %s' % namespaceURI
                )
        self._nsmap[namespaceURI] = prefix

    def hasNSPrefix(self, namespaceURI):
        """Return true if a prefix is declared for the given namespace uri."""
        return self._nsmap.has_key(namespaceURI)

    def getNSPrefix(self, namespaceURI):
        """Return the prefix to be used for the given namespace uri. A
           namespace prefix will be generated (and declared in the xml
           document) if a prefix for that uri has not been declared."""
        prefix = self._nsmap.get(namespaceURI, 0)
        if prefix is not 0:
            return prefix
        nsnum = getattr(self, '_nsnum', 0)
        self._nsnum = nsnum + 1
        prefix = 'ns%d' % nsnum
        self.declareNSPrefix(prefix, namespaceURI)
        return prefix

    def makeQName(self, namespaceURI, name):
        """Return an appropriate qname, given a name and namespace uri."""
        if namespaceURI is None:
            return name
        prefix = self.getNSPrefix(namespaceURI)
        if prefix is None: # default ns
            return name
        return '%s:%s' % (prefix, name)

    def makeRefId(self):
        """Return a generated unique id for use as an element reference."""
        idnum = getattr(self, '_idnum', 0)
        self._idnum = idnum + 1
        return 'ref-%d' % idnum

    def toString(self, format=0):
        """Return the xml stream as a string. If the format argument is
           a true value, the output will be formatted for readability."""
        if len(self._stack):
            tagname = self._stack[-1].tagName
            raise WriterError(
                'Missing endElement call for: %s' % tagname
                )

        element = self.document.childNodes[0]
        default = getattr(self, '_nsdefault', None)
        if default is not None:
            element.setAttribute('xmlns', default)
        for namespaceURI, prefix in self._nsmap.items():
            if prefix is not None:
                element.setAttribute('xmlns:%s' % prefix, namespaceURI)

        stream = StringIO()
        stream.write('<?xml version="1.0" encoding="%s"?>\n' % (
            self.encoding
            ))
        for child in self.document.childNodes:
            DOM.elementToStream(child, stream, format)
        return stream.getvalue()


from xml.dom.minidom import Text

class LiteralText(Text):
    def writexml(self, writer, indent="", addindent="", newl=""):
        writer.write("%s%s" % (self.data, newl))


class WriterError(Exception):
    pass


=== Added File Packages/WebService/__init__.py ===
# 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.

"""Web services package for Python."""

__version__='$Revision: 1.1 $'[11:-2]


# We make use of weak references in various places to prevent leaking of
# circular structures, so we need to setup pickling support for weak refs
# to allow certain objects to be pickled.

import weakref, copy_reg

def save_weakref(object):
    return (weakref.ref, (object(),))

copy_reg.pickle(weakref.ReferenceType, save_weakref, weakref.ref)


=== Added File Packages/WebService/setup.py ===
#!/usr/bin/env python

from distutils.core import setup

setup(name="WebService",
      version="1.0a",
      description="Web Services for Python",
      author="Brian Lloyd",
      author_email="brian@zope.com",
      url="",
      py_modules=(
        '__init__',
        'ServiceProxy',
        'SOAPCallInfo',
        'SOAPMessage',
        'SOAPReader',
        'SOAPWriter',
        'Serializer',
        'WSDLTools',
        'XMLSchema',
        'XMLWriter',
        'Transports',
        'TimeoutSocket',
        'Utility',
        ),
      )
      


=== Added File Packages/WebService/todo.txt ===
Punch-out list:

  - finish SOAPMessage docs

  - connection timeouts for WSDL & schema readers

  - rethink Message params apis

  - write getting started docs

  - finish Schema and serializer docs

  - implement DWIM SOAP method proxy

  - Support HTTP basic auth for default proxies

  - implement schema model and update serializer

  - null handling in serializer

  - decide how to handle document-style parameters

  - implement client interop test suite + reports

  - add copyright / legal mumbo jumbo to files

  - finish MIME part handling in SOAPMessage

  - speed tweaks for WSDL parsing

  - see if HTTPS works with timeouts



  - decide if WSDL really needs to keep DOM document / 
    loss of ns in wsdl on read / change?