[Zope-Checkins] CVS: Zope3/lib/python/SOAPpy - CHANGELOG:1.1.2.1 README:1.1.2.1 SOAP.py:1.1.2.1 SOAPtest.py:1.1.2.1 TCtest.py:1.1.2.1 __init__.py:1.1.2.1 echoClient.py:1.1.2.1 echoServer.py:1.1.2.1 excelTest.py:1.1.2.1 speedTest.py:1.1.2.1

Stephan Richter srichter@cbu.edu
Wed, 13 Mar 2002 11:39:34 -0500


Update of /cvs-repository/Zope3/lib/python/SOAPpy
In directory cvs.zope.org:/tmp/cvs-serv1678/SOAPpy

Added Files:
      Tag: srichter-OFS_Formulator-branch
	CHANGELOG README SOAP.py SOAPtest.py TCtest.py __init__.py 
	echoClient.py echoServer.py excelTest.py speedTest.py 
Log Message:
- Switched to SOAPpy library.

- Made the first action in XUL work.

This checkin is primary for people that want to look at the code. I will 
probably replace SOAPpy with Brian Lloyd's SOAP implementation later today,
since I have no approval to use SOAPpy in Zope 3 and Brian's stuff is 
already ZPL 2.0.


=== Added File Zope3/lib/python/SOAPpy/CHANGELOG ===

SOAP.py

CHANGES: 

VERSION 0.9.7 (6/27/01)
- Fixed the unamed ordered parameters bug
- Added the ability to specify a http_proxy
- Added a patch provided by Tim MiddelKoop to allow printing of proxy objects
- Added the contrib directory and included a medusa implementation of a 
  SOAP.py server by Ng Pheng Siong


VERSION 0.9.6 (6/08/01)

- The date and time types now check their initial values when the type
  is created, not when the data is marshalled.
- The date and time types are now parsed and returned as tuples (for
  multi-element types) or scalars (for single element types) in UTC and thus
  can represent the entire range of SOAP dates.
- If an element doesn't have a type but has a name with a namespace, the
  name is tried as the type.
- Untyped compound types with more than one element and all the elements
  the same name are turned into an array when parsing.
- When parsing a structType, elements with the same name are placed in a
  list instead of saving just the last one. _getItemsAsList can be used to
  get an element of a structure as a list, whether there was one or many
  occurances of the item.
- Added schemaNamespace, schemaNamespaceURI, and namespaceStyle
  configuration options. namespaceStyle takes one of 1999, 2000, or 2001,
  and sets typesNamespace, typesNamespaceURI, schemaNamespace, and
  schemaNamespaceURI.
- Normalized the type class names, replacing Compound with compoundType,
  Struct with structType, Header with headerType, Body with bodyType, Array
  with arrayType, TypedArray with typedArrayType, Fault with faultType, and
  urType with anyType.
- Attributes now appear on an element itself instead of the element's
  parent. For elements parsed to builtin python types, the attributes are
  stored in a dictionary keyed by the element's python id. The dictionary
  is in the Context object, can be returned from parseSOAP*, and can be
  returned from method calls if the returnAllAttrs configuration option
  is set.
- isinstance is used to check for a class, so classes can be subtyped.
- An encoding of None can be specified to not include encoding information.
- Problems with the SOAPProxy URL are now reported when the SOAPProxy
  instance is created instead of when the first method call is made.
- The Binary, Boolean and DateTime types have been removed in favor of
  binaryType, booleanType, and dateTimeType.


VERSION 0.9.5 (5/16/01)

- Should parse and build all 1999, 2000, 2001, and SOAP-ENC datatypes.
- Initial handling of multi-dimensional, partial, and sparse arrays.
- Supports SSL clients (if Python built with OpenSSL).
- Supports SSL servers (if M2Crypto installed).
- Applies defaults to SOAPproxy URLs (nice for command-line tools).
- Added the _SOAPContext object, gives registered server functions more info
  about the current call.
- Now assumes that any type that isn't in a schema could be a struct.
- Added the Config object, now config options can be set globally or on an
  individual call level.
- Deprecated the DateTime, Binary and Boolean types, should now 
  use dateTimeType, binaryType and booleanType.
- Includes N+I interop suite.
- Various bug fixes and improvements.


VERSION 0.9 (5/01/01)

- The Envelope now just contains definitions for namespaces actually used
  (Builder)
- Namespace definitions are inherited by children but not siblings (Builder)
- Further improved multi-reference parsing -- it handles circular references
  (Parser)
- Added support for building recursive and circular types using references
  (Builder)
- More types
- Proper handling of overflow and underflow integral and floating point
  types (Parser)
- More interop
- Various bug fixes and improvements

VERSION 0.8.5 (4/25/01)
- buildSOAP, SOAPProxy, SOAPServer now taking encoding argument
- Much improved multi-referencing (Parser)
- Added base64 and dateTime to interop suite
- Various bug fixes

VERSION 0.8 (4/23/01)
- Added more types
- Early multi-referencing support (Parser)
- Reorganized the parser, much cleaner now
- Preserve whitepsace in strings (per the standard)
- Full XML attribute support (Parser/Builder)
- Object (de)serialization now maintains element order
- Fixed the zero-length array problem
- Made indentation uniform (spaces not tabs)
- Made Header and Body work more like real structs
- Changed the parseSOAP api, now returns the body structure, 
  instead of a list of body elements
- Changed the soapaction and namespaces for the interop server
- New silabclient options
- Initial encoding support

VERSION 0.7 (4/19/01)
- Fixed a bug that caused nothing to work with Python 2.1
- Float work arounds for WIN32 (others?)
- DateTime parsing for WIN32
- Beginnings of XML attribute support
- Better interop

VERSION 0.6 (4/18/01)
- Fixed numerous bugs (dateTime, float precision, Response Element, null
  strings)
- Added more types
- Homogeneous typed arrays
- Added support for more schemas
- Early Header support and mustUnderstand and actor
- Added interop suite
- Passes validator
- Interop greatly improved, passes all client tests for Frontier,
  SOAP::LITE.

VERSION 0.5 (4/17/01)
- Initial public release


=== Added File Zope3/lib/python/SOAPpy/README ===
Copyright (c) 2001

SOAP.py 0.9.7 - Cayce Ullman   (c_ullman@yahoo.com)
                Brian Matthews (blm@blmatthews.com)

MANIFEST:
README
SOAP.py       the library
SOAPtest.py   tests the builder and parser
echoClient.py an example client
echoServer.py an example server
speedTest.py  benchmarks the various parsers, compares speed to DOM
TCtest.py     experimental type coercion system tests
tests/*       examples
validate/*    interop client and servers
bid/*	      N+I interop client and server

IMPORTANT NOTE:

It appears that there are some memory leaks in the Python 2.0 pyexpat, so
if you run a server under Python 2.0, eventually it will run out of memory.
We *strongly* recommend upgrading to Python 2.1, which doesn't exhibit the
memory leak (and has a number of other bug fixes and additional features).

SSL NOTE:

If you want to use either an SSL client or server, you'll need to have
OpenSSL (http://www.openssl.org/) available, and build your Python with
OpenSSL support (see the README in the top of the Python source directory
for how to customize Modules/Setup, and make sure the socket module with
SSL support lines are uncommented). If you want to use an SSL server, in
addition to building your Python for OpenSSL, you'll need to build and
install M2Crypto (http://www.pobox.org.sg/home/ngps/m2/).

HOWTO:

The easiest way to get up to speed is to run and read the scripts in the
tests directory. Better documentation is coming.

Here are some examples of how to use SOAP.py:

CLIENT EXAMPLES:

## CODE
import SOAP
server = SOAP.SOAPProxy("http://localhost:8080/")
print server.echo("Hello world")
## /CODE

This opens a connection to the server listening on localhost:8080, calls the
method echo with the ordered parameter of "Hello World", and prints the
results.

## CODE
import SOAP
server = SOAP.SOAPProxy("https://localhost:8443/")
print server.echo("Hello world")
## /CODE

This opens a secure connection to the SSL server listening on
localhost:8443, calls the method echo with the ordered parameter of
"Hello World" and prints the results. Python must be built with OpenSSL.

## CODE
import SOAP
server = SOAP.SOAPProxy("http://services.xmethods.com/soap",
        	        namespace = "urn:xmethods-delayed-quotes")
print server.getQuote(symbol = "IBM")
## /CODE

This calls method getQuote that is in the namespace URI of
urn:xmethods-delayed-quotes on server services.xmethods.com. getQuote is
passed a named parameter, symbol.

## CODE
import SOAP
server = SOAP.SOAPProxy("http://services.xmethods.com/soap")

print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM")
## /CODE

This does the same thing as the previous example, however namespace is
specified inline on a per call basis rather than at the server level.

## CODE
import SOAP
server = SOAP.SOAPProxy("http://services.xmethods.com/soap",
			soapaction = "http://somesite.com/myaction")

print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM")
## /CODE

This is the same quote call with a soapaction specified.

## CODE
import SOAP
server = SOAP.SOAPProxy("http://services.xmethods.com:80/soap")

ns = "urn:xmethods-delayed-quotes")
sa = "http://somesite.com/myaction"
my_call = server._ns(ns)._sa(sa)
my_call.getQuote(symbol = "IBM")
my_call.getQuote(symbol = "IBM")
my_call.getQuote(symbol = "IBM")
## /CODE

The same example, this time with both the soapaction and the namespace
specified inline and saved in a local variable for getQuote to be called
against.

** What SOAP.py does with the results of a call could seem surprising. If
there is only one element in the structType that has the return value and
unwrap_results is turned on (the default) it will bubble up the single
attribute, otherwise it will return you a structType object with all of the
attributes.

SERVER EXAMPLES:

## CODE
import SOAP
def echo(s):
    return s + s # repeats a string twice

server = SOAP.SOAPServer(("localhost", 8080))
server.registerFunction(echo)
server.serve_forever()
## /CODE

This exposes the function echo (that takes an unnamed arguement) on a server
running on localhost:8080.

## CODE
import SOAP
def echo(s):
    return s + s # repeats a string twice

server = SOAP.SOAPServer()
server.registerFunction(echo, "echo-space")
server.serve_forever()
## /CODE

The same as above, but this time the method is available in the namespace
"echo-space".

## CODE
import SOAP

class echoBuilder:
    def echo(self, val):
        return val + val

server = SOAP.SOAPServer()
e = echoBuilder()
server.registerObject(e)
server.serve_forever()
## /CODE

This registers the whole instance of the object echoBuilder, e.  Every
method of the instance is exposed on the server.

## CODE
import SOAP

def echo(**kw):
    return kw['first'] + kw['second'] + kw['third']

server = SOAP.SOAPServer()
server.registerKWFunction(echo)
server.serve_forever()
## /CODE

This time the method echo is exposed and it expects named arguments. The
main thing to notice here is the use of the method registerKWFunction over
registerFunction.

## CODE
import SOAP

from M2Crypto import SSL

def echo(s):
    return s+s # repeats a string twice

ssl_context = SSL.Context()
ssl_context.load_cert('server.pem')

server = SOAP.SOAPServer(("localhost",8443), ssl_context = ssl_context)
server.registerFunction(echo)
server.serve_forever()
## /CODE

This exposes the function echo (taking an unnamed arguement) on a server
accepting SSL connections at localhost:8443. Ng Pheng Siong's M2Crypto
package (available at <http://www.pobox.org.sg/home/ngps/m2/>) must be
installed. Also see tests/silabserver.py.


Copyright (c) 2001, Cayce Ullman.
Copyright (c) 2001, Brian Matthews.

All rights reserved.

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

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

Neither the name of actzero, inc. nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.


=== Added File Zope3/lib/python/SOAPpy/SOAP.py === (3880/3980 lines abridged)
#!/usr/bin/python
################################################################################
#
# SOAP.py 0.9.7 - Cayce Ullman    (cayce@actzero.com)
#                 Brian Matthews  (blm@actzero.com)
#
# INCLUDED:
# - General SOAP Parser based on sax.xml (requires Python 2.0)
# - General SOAP Builder
# - SOAP Proxy for RPC client code
# - SOAP Server framework for RPC server code
#
# FEATURES:
# - Handles all of the types in the BDG
# - Handles faults
# - Allows namespace specification
# - Allows SOAPAction specification
# - Homogeneous typed arrays
# - Supports multiple schemas
# - Header support (mustUnderstand and actor)
# - XML attribute support
# - Multi-referencing support (Parser/Builder)
# - Understands SOAP-ENC:root attribute
# - Good interop, passes all client tests for Frontier, SOAP::LITE, SOAPRMI
# - Encodings
# - SSL clients (with OpenSSL configured in to Python)
# - SSL servers (with OpenSSL configured in to Python and M2Crypto installed)
#
# TODO:
# - Timeout on method calls - MCU
# - Arrays (sparse, multidimensional and partial) - BLM
# - Clean up data types - BLM
# - Type coercion system (Builder) - MCU
# - Early WSDL Support - MCU
# - Attachments - BLM
# - setup.py - MCU
# - mod_python example - MCU
# - medusa example - MCU
# - Documentation - JAG
# - Look at performance
#
################################################################################
#
# Copyright (c) 2001, Cayce Ullman.
# Copyright (c) 2001, Brian Matthews.
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:

[-=- -=- -=- 3880 lines omitted -=- -=- -=-]


        if ssl_context != None and not config.SSLserver:
            raise AttributeError, \
                "SSL server not supported by this Python installation"

        self.namespace          = namespace
        self.objmap             = {}
        self.funcmap            = {}
        self.ssl_context        = ssl_context
        self.encoding           = encoding
        self.config             = config
        self.log                = log

        self.allow_reuse_address= 1

        SocketServer.TCPServer.__init__(self, addr, RequestHandler)

    def get_request(self):
        sock, addr = SocketServer.TCPServer.get_request(self)

        if self.ssl_context:
            sock = SSL.Connection(self.ssl_context, sock)
            sock._setup_ssl(addr)
            if sock.accept_ssl() != 1:
                raise socket.error, "Couldn't accept SSL connection"

        return sock, addr

    def registerObject(self, object, namespace = ''):
        if namespace == '': namespace = self.namespace
        self.objmap[namespace] = object

    def registerFunction(self, function, namespace = '', funcName = None):
        if not funcName : funcName = function.__name__
        if namespace == '': namespace = self.namespace
        if self.funcmap.has_key(namespace):
            self.funcmap[namespace][funcName] = function
        else:
            self.funcmap[namespace] = {funcName : function}

    def registerKWObject(self, object, namespace = ''):
        if namespace == '': namespace = self.namespace
        for i in dir(object.__class__):
            if i[0] != "_" and callable(getattr(object, i)):
                self.registerKWFunction(getattr(object,i), namespace)

    # convenience  - wraps your func for you.
    def registerKWFunction(self, function, namespace = '', funcName = None):
        self.registerFunction(MethodSig(function,keywords=1), namespace,
        funcName)


=== Added File Zope3/lib/python/SOAPpy/SOAPtest.py === (3568/3668 lines abridged)
#!/usr/bin/env python

################################################################################
#
# A bunch of regression type tests for the builder and parser.
#
################################################################################

import urllib
import sys
import unittest

from SOAP import *

ident = '$Id: SOAPtest.py,v 1.1.2.1 2002/03/13 16:39:33 srichter Exp $'

# as borrowed from jake.soapware.org for float compares.
def nearlyeq(a, b, prec = 1e-7):
    return abs(a - b) <= abs(a) * prec

# helper
def negfloat(x):
    return float(x) * -1.0

class Book(structType):
    def __init__(self):
        self.title = "Title of a book"

class Person(structType):
    def __init__(self):
        self.age = "49"
        self.height = "5.5"

class Result(structType):
    def __init__(self):
        structType.__init__(self, name = 'Result')
        self.Book = Book()
        self.Person = Person()

class one:
    def __init__(self):
        self.str = "one"
        
class two:
    def __init__(self):
        self.str = "two"
        
class three:
    def __init__(self):
        self.str = "three"

[-=- -=- -=- 3568 lines omitted -=- -=- -=-]

        self.assertEquals( x ,  [None, None, 'The third element', 'The fourth element', None])

        xml = env % '''<SOAP-ENV:Body>
<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[,][4]">
   <SOAP-ENC:Array href="#array-1" SOAP-ENC:position="[2]"/>
</SOAP-ENC:Array>
<SOAP-ENC:Array id="array-1" SOAP-ENC:arrayType="xsd:string[10,10]">
   <item SOAP-ENC:position="[2,2]">Third row, third col</item>
   <item SOAP-ENC:position="[7,2]">Eighth row, third col</item>
</SOAP-ENC:Array>
</SOAP-ENV:Body>'''

        x = parseSOAPRPC(xml)

    # Example using key data
    def testKeyData(self):
        xml = '''<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<soap:Body>
    <xkms:RegisterResult xmlns:xkms="http://www.xkms.org/schema/xkms-2001-01-20">
        <xkms:Result>Success</xkms:Result>
        <xkms:Answer soapenc:arrayType="KeyBinding[1]">
            <xkms:KeyBinding>
                <xkms:Status>Valid</xkms:Status>
                <xkms:KeyID>mailto:actzerotestkeyname</xkms:KeyID>
                <dsig:KeyInfo>
                    <dsig:X509Data>
                        <dsig:X509Certificate>MIIDPjCCAqegAwIBAgIEOroMvDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVI3nlMkH84ZdPKIyz60sNcVEwJ8kF+B6ZVNimCF+r7BWgLi/Dolce5CpbfMMyexZ+UQEMADrc7331eYS891KXSDQx</dsig:X509Certificate>
                    </dsig:X509Data>
                    <dsig:KeyName>mailto:actzerotestkeyname</dsig:KeyName>
                    <dsig:KeyValue>
                        <dsig:RSAKeyValue>
                            <dsig:Modulus>wgmV2FY6MBKvtaMmCvCoNi/0hycZkiPKC2PXjRLJKFJ5wjNfF+vWsQQUXxOKUQnu
HjJqRkx90jJvnEzW3j9FlZFQcZTfJbE0v6BXhhSre2kZvkgcOERmDMeMs//oEA4u
epnedUwrkPzedWU9AL7c/oN7rk65UuPWf7V8c/4E9bc=</dsig:Modulus>
                            <dsig:Exponent>AQAB</dsig:Exponent>
                        </dsig:RSAKeyValue>
                    </dsig:KeyValue>
                </dsig:KeyInfo>
            </xkms:KeyBinding>
        </xkms:Answer>
        <xkms:Private>9GKuRC3ISwE9aEatzDKW0WIp+P/ufOvCxy9d5jVglLaRiTTIelHoGKCE6cDG62HYOu/3ebce6M7Z6LX6l1J9pB5PUx+f2DaMYYEGuOtNA7/ei5Ga/mibRBCehQIcN6FF6ESFOwAJBRLajj+orgYSy0u1sTCla0V4nSBrYA2H6lx8mD3qfDJ4hie7nU0YqZxy50F9f9UxXKIVSeutyIIBjWDDKv0kVpKy7OUerOaZXOW6HBohXuV74kXMUZu+MpLIkMHOrhJeo+edfhmeFuw4kCo5it6GkrOKrGs6zo1hSxWp7uuvKAPbvUrumC6sTsTxAUg4KTGq85IUnBTYI40Q9TZtzMcONtrWfIIF23/7NJyOmygBaFa4wFqHxe7j2gSWCQRv2fPwXo/AAJTeKwsUIY8OgmANHHbFVqJEeg27jbCuSaQFxWD7ms240YurTb55HBLk6JSufDl0CUbxoUgjrDB++gUb8oalroWDIb5NcZ94QER+HiTQfB11HcPDHvONnzk/n+iF+Mcri53ZbAButnfp2x87sh6RedeiUUWruYA4eonRq5+aj2I9cIrGLQaLemna1AQ+PyD2SMelBLukfR7GUc7zaSPjPJh2W/aYAJSyjM98g6ABNntdfhuf+6jRYnYFqSXZL1W1JPf92OMOfwfuXTE2K68sNwCRhcbHDLM=</xkms:Private>
        </xkms:RegisterResult>
    </soap:Body>
</soap:Envelope>'''

        x = parseSOAPRPC(xml)

if __name__ == '__main__':
    unittest.main()

=== Added File Zope3/lib/python/SOAPpy/TCtest.py ===
#!/usr/bin/env python

from SOAP import *
import sys

x = '''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SomeMethod>
<Result>
<Book>
   <title>My Life and Work</title>
</Book>
<Person>
   <name>Henry Ford</name>
   <age> 49 </age>
   <height> 5.5 </height>
</Person>
</Result>
</SomeMethod>
</soap:Body>
</soap:Envelope>
'''

def negfloat(x):
    return float(x) * -1.0
# parse rules
pr = {'Result':
      {'Book':   {'title':"string"},
       'Person': {'age':"int",
                  'height':negfloat}
       }
      }
y = parseSOAPRPC(x, parse_rules=pr)
assert y.Result.Person.age == 49
assert y.Result.Person.height == -5.5


x = '''
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
   <SOAP-ENV:Body>
   <Bounds>
   <param>
   <item>12</item>
   <item>23</item>
   <item>0</item>
   <item>-31</item>
   </param>
   <param1 xsi:null="1"></param1>
   </Bounds>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
'''
# parse rules
pr = {'Bounds':
      {'param': 'arrayType=string[]'
       }
      }

pr2 = {'Bounds':
      {'param': 'arrayType=int[4]'
       }
      }

y = parseSOAPRPC(x, parse_rules=pr)
assert y.param[1]=='23'

y = parseSOAPRPC(x, parse_rules=pr2)
assert y.param[1]==23

x = '''
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
   <SOAP-ENV:Body>
   <Bounds>
   <param>
   <item xsi:type="xsd:int">12</item>
   <item xsi:type="xsd:string">23</item>
   <item xsi:type="xsd:float">0</item>
   <item xsi:type="xsd:int">-31</item>
   </param>
   <param1 xsi:null="1"></param1>
   </Bounds>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
'''

pr = {'Bounds':
      {'param': 'arrayType=ur-type[]'
       }
      }
y = parseSOAPRPC(x, parse_rules=pr)
assert y.param[0]==12
assert y.param[1]=='23'
assert y.param[2]==float(0)
assert y.param[3]==-31



# Try the reverse, not implemented yet.

class Book(structType):
    def __init__(self):
        self.title = "Title of a book"
class Person(structType):
    def __init__(self):
        self.age = "49"
        self.height = "5.5"
class Result(structType):
    def __init__(self):
        self._name = "Result"
        self.Book = Book()
        self.Person = Person()

x = buildSOAP(Result())
#sys.exit(0)


=== Added File Zope3/lib/python/SOAPpy/__init__.py ===


=== Added File Zope3/lib/python/SOAPpy/echoClient.py ===
#!/usr/bin/env python

# Copyright (c) 2001 actzero, inc. All rights reserved.

import sys

import SOAP

# Uncomment to see outgoing HTTP headers and SOAP and incoming SOAP.
#SOAP.Config.debug = 1

SOAP.Config.BuildWithNoType = 1
SOAP.Config.BuildWithNoNamespacePrefix = 1

if len(sys.argv) > 1 and sys.argv[1] == '-s':
    server = SOAP.SOAPProxy("https://localhost:9900")
else:
    server = SOAP.SOAPProxy("http://localhost:9900")

# Echo...

# ...in an object
print server.echo_ino("moo")

# ...in an object in an object
print server.prop.echo2("moo")

# ...with keyword arguments 
print server.echo_wkw(third = "three", first = "one", second = "two")

# ...with a context object
print server.echo_wc("moo")

# ...with a header
hd = SOAP.headerType(data = {"mystring": "Hello World"})
print server._hd(hd).echo_wc("moo")


=== Added File Zope3/lib/python/SOAPpy/echoServer.py ===
#!/usr/bin/env python

# Copyright (c) 2001 actzero, inc. All rights reserved.

import sys

import SOAP

if SOAP.Config.SSLserver:
    from M2Crypto import SSL

# Simple echo
def echo(s):
    return s + s

# An echo class
class echoBuilder2:
    def echo2(self, val):
        return val * 3

# A class that has an instance variable which is an echo class
class echoBuilder:
    def __init__(self):
        self.prop = echoBuilder2()

    def echo_ino(self, val):
        return val + val

# Echo with context
def echo_wc(s, _SOAPContext):
    c = _SOAPContext

    sep = '-' * 72

    # The Context object has extra info about the call

    print "-- XML", sep[7:]
    print c.xmldata     # The original XML request

    print "-- Header", sep[10:]
    print c.header      # The SOAP Header or None if not present

    if c.header:
        print "-- Header.mystring", sep[19:]
        print c.header.mystring         # An element of the SOAP Header

    print "-- Body", sep[8:]
    print c.body        # The whole Body object

    print "-- Peer", sep[8:]
    print c.connection.getpeername()    # The socket object, useful for

    print "-- SOAPAction", sep[14:]
    print c.soapaction                  # The SOAPaction HTTP header

    print "-- HTTP headers", sep[16:]
    print c.httpheaders                 # All the HTTP headers

    return s + s

# Echo with keyword arguments
def echo_wkw(**kw):
    return kw['first'] + kw['second'] + kw['third']

if len(sys.argv) > 1 and sys.argv[1] == '-s':
    if not SOAP.Config.SSLserver:
        raise RuntimeError, \
            "this Python installation doesn't have OpenSSL and M2Crypto"
    ssl_context = SSL.Context()
    ssl_context.load_cert('validate/server.pem')
else:
    ssl_context = None

server = SOAP.SOAPServer(('localhost',9900), ssl_context = ssl_context)

server.registerFunction(echo)

# Register a whole object
o = echoBuilder()
server.registerObject(o)

# Register a function which gets called with the Context object
server.registerFunction(SOAP.MethodSig(echo_wc, keywords = 0, context = 1))

# Register a function that takes keywords
server.registerKWFunction(echo_wkw)

# Start the server
try:
    server.serve_forever()
except KeyboardInterrupt:
    pass


=== Added File Zope3/lib/python/SOAPpy/excelTest.py ===
#!/usr/bin/python

import SOAP
server = SOAP.SOAPProxy("http://206.135.217.234:8000/")
server.COM_SetProperty("Visible", 1)
server.Workbooks.Open("c:\\test.xls")
server.COM_NestedCall('ActiveSheet.Range("A2").EntireRow.Delete()')
server.quit()









=== Added File Zope3/lib/python/SOAPpy/speedTest.py ===
#!/usr/bin/env python

ident = '$Id: speedTest.py,v 1.1.2.1 2002/03/13 16:39:33 srichter Exp $'

import time

x='''<SOAP-ENV:Envelope
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
      xmlns:xsd="http://www.w3.org/1999/XMLSchema">
      <SOAP-ENV:Body>
         <ns1:getRate xmlns:ns1="urn:demo1:exchange"  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
            <country1 xsi:type="xsd:string">USA</country1>
            <country2 xsi:type="xsd:string">japan</country2>
         </ns1:getRate>
      </SOAP-ENV:Body>
   </SOAP-ENV:Envelope>'''

x2='''<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.microsoft.com/soap/encoding/clr/1.0 http://schemas.xmlsoap.org/soap/encoding/" xmlns:i3="http://soapinterop.org/xsd" xmlns:i2="http://soapinterop.org/">
<SOAP-ENV:Body>
<i2:echoStructArray id="ref-1">
<return href="#ref-4"/>
</i2:echoStructArray>
<SOAP-ENC:Array id="ref-4" SOAP-ENC:arrayType="i3:SOAPStruct[3]">
<item href="#ref-5"/>
<item href="#ref-6"/>
<item href="#ref-7"/>
</SOAP-ENC:Array>
<i3:SOAPStruct id="ref-5">
<varString xsi:type="xsd:string">West Virginia</varString>
<varInt xsi:type="xsd:int">-546</varInt>
<varFloat xsi:type="xsd:float">-5.398</varFloat>
</i3:SOAPStruct>
<i3:SOAPStruct id="ref-6">
<varString xsi:type="xsd:string">New Mexico</varString>
<varInt xsi:type="xsd:int">-641</varInt>
<varFloat xsi:type="xsd:float">-9.351</varFloat>
</i3:SOAPStruct>
<i3:SOAPStruct id="ref-7">
<varString xsi:type="xsd:string">Missouri</varString>
<varInt xsi:type="xsd:int">-819</varInt>
<varFloat xsi:type="xsd:float">1.495</varFloat>
</i3:SOAPStruct>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
'''

# Import in function, because for some reason they slow each other
# down in same namespace ???
def SOAPParse(inxml):
    import SOAP
    t=  time.time()
    SOAP.parseSOAPRPC(inxml)
    return time.time()-t

def SAXParse(inxml):
    import xml.sax
    y = xml.sax.handler.ContentHandler()
    t=  time.time()
    xml.sax.parseString(inxml,y)
    return time.time()-t

def DOMParse(inxml):
    import xml.dom.minidom
    t=  time.time()
    xml.dom.minidom.parseString(inxml)
    return time.time()-t

# Wierd but the SAX parser runs really slow the first time.
# Probably got to load a c module or something
SAXParse(x)
print
print "Simple XML"
print "SAX Parse, no marshalling   ", SAXParse(x)
print "SOAP Parse, and marshalling ", SOAPParse(x)
print "DOM Parse, no marshalling   ", DOMParse(x)
print
print "Complex XML (references)"
print "SAX Parse, no marshalling   ", SAXParse(x2)
print "SOAP Parse, and marshalling ", SOAPParse(x2)
print "DOM Parse, no marshalling   ", DOMParse(x2)