├── SOAPpy ├── .cvsignore ├── wstools │ ├── .cvsignore │ ├── test │ │ ├── .cvsignore │ │ ├── schema.tar.gz │ │ ├── xmethods.tar.gz │ │ ├── __init__.py │ │ ├── test_wstools_net.py │ │ ├── test_t1.py │ │ ├── test_wstools.py │ │ ├── README │ │ └── test_wsdl.py │ ├── __init__.py │ ├── ZPL │ ├── license.txt │ ├── XMLname.py │ ├── MIMEAttachment.py │ ├── UserTuple.py │ └── TimeoutSocket.py ├── version.py ├── __init__.py ├── URLopener.py ├── SOAP.py ├── Errors.py ├── NS.py ├── WSDL.py ├── GSIServer.py ├── Utilities.py ├── fpconst.py └── Config.py ├── bid ├── .cvsignore ├── monitorClient.py ├── inventory.servers └── inventoryServer.py ├── contrib ├── .cvsignore └── soap_cli.py ├── tests ├── .cvsignore ├── ZeroLengthArray.py ├── simpleWSDL.py ├── excelTest.py ├── testleak.py ├── GoogleTest.py ├── echoHeader.py ├── whoisTest.py ├── ComplexTypes.py ├── weatherTest.py ├── cardClient.py ├── BabelfishWSDLTest.py ├── Bug1161780.py ├── xmethods.py ├── Bug916265.py ├── alanbushTest.py ├── Bug1356261.py ├── esj_test_server.py ├── largeDataTest.py ├── quoteTest.py ├── Bug1366752.py ├── Bug918216.py ├── newsTest.py ├── TemperatureService.wsdl ├── Bug1936883.py ├── Bug1001646.py ├── Makefile ├── README ├── esj_test_client.py ├── echoClient.py ├── speedTest.py ├── cardServer.py ├── testClient1.py ├── storageTest.py ├── TCtest.py ├── testWSDL.py └── echoServer.py ├── tools ├── .cvsignore └── interop2html.py ├── validate ├── .cvsignore ├── server.pem ├── soapware.py └── silabserver.py ├── TODO ├── docs ├── attrs.txt ├── complexTypes.txt ├── WSDL.txt ├── UsingHeaders.txt ├── MethodParameterNaming.txt ├── GlobusSupport.txt └── GettingStarted.txt ├── MANIFEST.in ├── zope ├── zope-soap-client.py ├── README ├── zope-2.5.0-soappy.diff └── zope-2.6.2-soappy.diff ├── setup.py ├── LICENSE ├── SOAPpy.spec └── README /SOAPpy/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /bid/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /contrib/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /tests/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /tools/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /validate/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /SOAPpy/wstools/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /SOAPpy/wstools/test/.cvsignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /SOAPpy/version.py: -------------------------------------------------------------------------------- 1 | __version__="0.12.0" 2 | 3 | -------------------------------------------------------------------------------- /SOAPpy/wstools/test/schema.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/python-soappy/master/SOAPpy/wstools/test/schema.tar.gz -------------------------------------------------------------------------------- /SOAPpy/wstools/test/xmethods.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grangier/python-soappy/master/SOAPpy/wstools/test/xmethods.tar.gz -------------------------------------------------------------------------------- /SOAPpy/wstools/test/__init__.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """wstools.WSDLTools.WSDLReader tests directory.""" 3 | 4 | import utils 5 | 6 | -------------------------------------------------------------------------------- /SOAPpy/wstools/__init__.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """WSDL parsing services package for Web Services for Python.""" 3 | 4 | ident = "$Id$" 5 | 6 | import WSDLTools 7 | import XMLname 8 | import logging 9 | 10 | -------------------------------------------------------------------------------- /tests/ZeroLengthArray.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, "..") 3 | from SOAPpy import * 4 | 5 | one = typedArrayType(data=[1],typed=type(1)) 6 | tmp = typedArrayType(data=[], typed=type(1)) 7 | print buildSOAP( one ) 8 | print buildSOAP( tmp ) 9 | -------------------------------------------------------------------------------- /tests/simpleWSDL.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.insert(1, "..") 4 | import SOAPpy 5 | 6 | url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' 7 | zip = '06340' 8 | proxy = SOAPpy.WSDL.Proxy(url) 9 | temp = proxy.getTemp(zip) 10 | print 'Temperature at', zip, 'is', temp 11 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | # $Id$ 2 | 3 | - figure out why parsing rules are broken 4 | 5 | - generate a test harness that will run all of the test code. 6 | 7 | - create unit-tests for all features, as well as for reported bugs. 8 | 9 | - write better documentation (!!!) 10 | - topics: WSDL, Globus, Authentication, ... 11 | - general introduction article 12 | - ... 13 | 14 | 15 | -------------------------------------------------------------------------------- /SOAPpy/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | ident = '$Id$' 3 | from version import __version__ 4 | 5 | from Client import * 6 | from Config import * 7 | from Errors import * 8 | from NS import * 9 | from Parser import * 10 | from SOAPBuilder import * 11 | from Server import * 12 | from Types import * 13 | from Utilities import * 14 | import wstools 15 | import WSDL 16 | -------------------------------------------------------------------------------- /tests/excelTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | sys.path.insert(1, "..") 5 | 6 | from SOAPpy import * 7 | server = SOAPProxy("http://206.135.217.234:8000/") 8 | server.COM_SetProperty("Visible", 1) 9 | server.Workbooks.Open("c:\\test.xls") 10 | server.COM_NestedCall('ActiveSheet.Range("A2").EntireRow.Delete()') 11 | server.quit() 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/attrs.txt: -------------------------------------------------------------------------------- 1 | 2 | Using SOAPpy Attributes 3 | ======================= 4 | 5 | All SOAPpy data classes implement methods to access and mutate 6 | individual attributes. 7 | 8 | The _setAttr method has as parameters a 'tag', the attribute name, and the 9 | value to which the attribute should be set. 10 | 11 | The _getAttrs method simply has the 'tag' parameter. 12 | 13 | 14 | 15 | $Id$ 16 | -------------------------------------------------------------------------------- /contrib/soap_cli.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import time 4 | from SOAPpy import SOAP 5 | 6 | srv = SOAP.SOAPProxy('http://localhost:10080/') 7 | 8 | for p in ('good param', 'ok param'): 9 | ret = srv.badparam(p) 10 | if isinstance(ret, SOAP.faultType): 11 | print ret 12 | else: 13 | print 'ok' 14 | 15 | dt = SOAP.dateTimeType(time.localtime(time.time())) 16 | print srv.dt(dt) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/testleak.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | sys.path.insert(1, "..") 5 | import SOAPpy 6 | import time 7 | import gc 8 | import types 9 | 10 | gc.set_debug(gc.DEBUG_SAVEALL) 11 | 12 | for i in range(400): 13 | try: 14 | t = SOAPpy.SOAP.parseSOAPRPC('bad soap payload') 15 | except: pass 16 | 17 | gc.collect() 18 | if len(gc.garbage): 19 | print 'still leaking' 20 | else: 21 | print 'no leak' 22 | -------------------------------------------------------------------------------- /tests/GoogleTest.py: -------------------------------------------------------------------------------- 1 | from SOAPpy import WSDL 2 | server = WSDL.Proxy('/home/warneg/src/google/googleapi/GoogleSearch.wsdl') 3 | key = "6k0oDPZQFHL0zpjy6ZO6ufUVFKBgvqTo" 4 | 5 | results = server.doGoogleSearch(key, 'warnes', 0, 10, False, "", 6 | False, "", "utf-8", "utf-8") 7 | 8 | 9 | for i in range(len(results.resultElements)): 10 | res = results.resultElements[i] 11 | print '%d: %s --> %s' % ( i, res.title, res.URL ) 12 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README* 2 | include LICENSE 3 | include RELEASE_INFO 4 | include TODO 5 | include ChangeLog 6 | recursive-include SOAPpy *.py 7 | recursive-include bid *.py 8 | recursive-include contrib *.py 9 | recursive-include docs *.txt 10 | recursive-include tests *.py 11 | recursive-include tests *.wsdl 12 | recursive-include tools *.py 13 | recursive-include validate *.py 14 | include validate/server.pem 15 | include validate/silab.servers 16 | -------------------------------------------------------------------------------- /zope/zope-soap-client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys 4 | from SOAPpy import SOAP 5 | 6 | # Uncomment to see outgoing HTTP headers and SOAP and incoming SOAP. 7 | SOAP.Config.debug = 1 8 | 9 | SOAP.Config.BuildWithNoType = 0 10 | SOAP.Config.BuildWithNoNamespacePrefix = 0 11 | 12 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 13 | server = SOAP.SOAPProxy("https://localhost:8080") 14 | else: 15 | server = SOAP.SOAPProxy("http://admin:pw3340@localhost:8080/",encoding=None) 16 | 17 | x = server.sopa() 18 | print x 19 | -------------------------------------------------------------------------------- /tests/echoHeader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | 10 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 11 | #Config.debug = 1 12 | 13 | Config.BuildWithNoType = 1 14 | Config.BuildWithNoNamespacePrefix = 1 15 | 16 | 17 | 18 | hd = headerType(data = {"mystring": "Hello World"}) 19 | server = SOAPProxy("http://localhost:9900/", header=hd) 20 | 21 | print server.echo("Hello world") 22 | 23 | server.quit() 24 | -------------------------------------------------------------------------------- /SOAPpy/URLopener.py: -------------------------------------------------------------------------------- 1 | """Provide a class for loading data from URL's that handles basic 2 | authentication""" 3 | 4 | ident = '$Id$' 5 | from version import __version__ 6 | 7 | from Config import Config 8 | from urllib import FancyURLopener 9 | 10 | class URLopener(FancyURLopener): 11 | 12 | username = None 13 | passwd = None 14 | 15 | 16 | def __init__(self, username=None, passwd=None, *args, **kw): 17 | FancyURLopener.__init__( self, *args, **kw) 18 | self.username = username 19 | self.passwd = passwd 20 | 21 | 22 | def prompt_user_passwd(self, host, realm): 23 | return self.username, self.passwd 24 | -------------------------------------------------------------------------------- /SOAPpy/wstools/test/test_wstools_net.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ############################################################################ 4 | # Joshua R. Boverhof, David W. Robertson, LBNL 5 | # See LBNLCopyright for copyright notice! 6 | ########################################################################### 7 | import unittest 8 | import test_wsdl 9 | 10 | def makeTestSuite(): 11 | suite = unittest.TestSuite() 12 | suite.addTest(test_wsdl.makeTestSuite("services_by_http")) 13 | return suite 14 | 15 | def main(): 16 | unittest.main(defaultTest="makeTestSuite") 17 | 18 | if __name__ == "__main__" : main() 19 | 20 | 21 | -------------------------------------------------------------------------------- /SOAPpy/wstools/test/test_t1.py: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Joshua R. Boverhof, David W. Robertson, LBNL 3 | # See LBNLCopyright for copyright notice! 4 | ########################################################################### 5 | import unittest 6 | import test_wsdl 7 | import utils 8 | 9 | def makeTestSuite(): 10 | suite = unittest.TestSuite() 11 | suite.addTest(test_wsdl.makeTestSuite("services_by_file")) 12 | return suite 13 | 14 | def main(): 15 | loader = utils.MatchTestLoader(True, None, "makeTestSuite") 16 | unittest.main(defaultTest="makeTestSuite", testLoader=loader) 17 | 18 | if __name__ == "__main__" : main() 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/complexTypes.txt: -------------------------------------------------------------------------------- 1 | COMPLEX TYPES HOWTO 2 | =================== 3 | 4 | The easiest way (at the moment) to create complex SOAP typs is to 5 | use the SOAPpy.structType class, which allows you to create an 6 | object with named arguments of arbitraty types. For example: 7 | 8 | >>> in0 = SOAPpy.structType() 9 | >>> in0._addItem('outwardDate', dep) 10 | >>> in0._addItem('returnDate', ret) 11 | >>> in0._addItem('originAirport', 'den') 12 | >>> in0._addItem('destinationAirport', 'iad') 13 | 14 | SOAPpy has code for declaring structured object templates including 15 | the type for each component, but this broke sometime in the past and 16 | has not yet been corrected. (See tests/TCtypes.py to see how it 17 | should work.) 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/whoisTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id$' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import SOAPProxy 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | server = SOAPProxy("http://www.SoapClient.com/xml/SQLDataSoap.WSDL", 20 | http_proxy=proxy) 21 | 22 | print "whois>>", server.ProcessSRL(SRLFile="WHOIS.SRI", 23 | RequestName="whois", 24 | key = "microsoft.com") 25 | 26 | -------------------------------------------------------------------------------- /tests/ComplexTypes.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, "..") 3 | 4 | import SOAPpy 5 | 6 | import time 7 | dep = SOAPpy.dateTimeType((2004, 3, 24, 12, 30, 59, 4, 86, 0)) 8 | ret = SOAPpy.dateTimeType((2004, 3, 26, 12, 30, 59, 4, 86, 0)) 9 | 10 | in0 = SOAPpy.structType() 11 | in0._addItem('outwardDate', dep) 12 | in0._addItem('returnDate', ret) 13 | in0._addItem('originAirport', 'den') 14 | in0._addItem('destinationAirport', 'iad') 15 | 16 | 17 | x = SOAPpy.buildSOAP( 18 | in0, 19 | method="getAirFareQuote", 20 | namespace="urn:SBGAirFareQuotes.sbg.travel.ws.dsdata.co.uk" 21 | ) 22 | 23 | 24 | wsdl = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl' 25 | proxy = SOAPpy.WSDL.Proxy(wsdl) 26 | 27 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # $Id$ 4 | 5 | CVS=0 6 | 7 | from distutils.core import setup, Command, Extension 8 | from SOAPpy.version import __version__ 9 | 10 | url="http://pywebsvcs.sf.net/" 11 | 12 | long_description="SOAPpy provides tools for building SOAP clients and servers. For more information see " + url 13 | 14 | 15 | if CVS: 16 | import time 17 | __version__ += "_CVS_" + time.strftime('%Y_%m_%d') 18 | 19 | 20 | setup(name="SOAPpy", 21 | version=__version__, 22 | description="SOAP Services for Python", 23 | maintainer="Gregory Warnes", 24 | maintainer_email="Gregory.R.Warnes@Pfizer.com", 25 | url = url, 26 | long_description=long_description, 27 | packages=['SOAPpy','SOAPpy/wstools'] 28 | ) 29 | 30 | -------------------------------------------------------------------------------- /tests/weatherTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id$' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import SOAPProxy 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | SoapEndpointURL = 'http://services.xmethods.net:80/soap/servlet/rpcrouter' 20 | MethodNamespaceURI = 'urn:xmethods-Temperature' 21 | 22 | # Do it inline ala SOAP::LITE, also specify the actually ns 23 | 24 | server = SOAPProxy(SoapEndpointURL, http_proxy=proxy) 25 | print "inline", server._ns('ns1', MethodNamespaceURI).getTemp(zipcode='94063') 26 | -------------------------------------------------------------------------------- /docs/WSDL.txt: -------------------------------------------------------------------------------- 1 | 2 | WSDL NOTES: 3 | 4 | Release 0.9.9 and later include logic for dealing with web service 5 | description language (WSDL) files. 6 | 7 | - SOAPpy.WSDL provides a SOAP Proxy object that parses a WSDL file 8 | and provides access to the listed services: 9 | 10 | url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' 11 | zip = '01072' 12 | proxy = SOAPpy.WSDL.Proxy(url) 13 | temp = proxy.getTemp(zip) 14 | print 'Temperature at', zip, 'is', temp 15 | 16 | - On the server, you can allow the client to download the WSDL for 17 | a service by sending a request of the form by adding a do_GET 18 | method to the SOAPRequestHandler. [Not yet working when 19 | debug=FALSE. Add example here when working] 20 | 21 | 22 | $Id$ 23 | -------------------------------------------------------------------------------- /tests/cardClient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | 7 | sys.path.insert (1, '..') 8 | 9 | from SOAPpy import * 10 | 11 | ident = '$Id$' 12 | 13 | endpoint = "http://localhost:12027/xmethodsInterop" 14 | sa = "urn:soapinterop" 15 | ns = "http://soapinterop.org/" 16 | 17 | serv = SOAPProxy(endpoint, namespace=ns, soapaction=sa) 18 | try: hand = serv.dealHand(NumberOfCards = 13, StringSeparator = '\n') 19 | except: print "no dealHand"; hand = 0 20 | try: sortedhand = serv.dealArrangedHand(NumberOfCards=13,StringSeparator='\n') 21 | except: print "no sorted"; sortedhand = 0 22 | try: card = serv.dealCard() 23 | except: print "no card"; card = 0 24 | 25 | print "*****hand****\n",hand,"\n*********" 26 | print "******sortedhand*****\n",sortedhand,"\n*********" 27 | print "card:",card 28 | 29 | serv.quit() 30 | 31 | -------------------------------------------------------------------------------- /SOAPpy/SOAP.py: -------------------------------------------------------------------------------- 1 | """This file is here for backward compatibility with versions <= 0.9.9 2 | 3 | Delete when 1.0.0 is released! 4 | """ 5 | 6 | ident = '$Id$' 7 | from version import __version__ 8 | 9 | from Client import * 10 | from Config import * 11 | from Errors import * 12 | from NS import * 13 | from Parser import * 14 | from SOAPBuilder import * 15 | from Server import * 16 | from Types import * 17 | from Utilities import * 18 | import wstools 19 | import WSDL 20 | 21 | from warnings import warn 22 | 23 | warn(""" 24 | 25 | The sub-module SOAPpy.SOAP is deprecated and is only 26 | provided for short-term backward compatibility. Objects are now 27 | available directly within the SOAPpy module. Thus, instead of 28 | 29 | from SOAPpy import SOAP 30 | ... 31 | SOAP.SOAPProxy(...) 32 | 33 | use 34 | 35 | from SOAPpy import SOAPProxy 36 | ... 37 | SOAPProxy(...) 38 | 39 | instead. 40 | """, DeprecationWarning) 41 | -------------------------------------------------------------------------------- /tests/BabelfishWSDLTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id$' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import WSDL 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | server = WSDL.Proxy('http://www.xmethods.net/sd/2001/BabelFishService.wsdl', 20 | http_proxy=proxy) 21 | 22 | english = "Hi Friend!" 23 | 24 | print "Babelfish Translations" 25 | print "------------------------" 26 | print "English: '%s'" % english 27 | print "French: '%s'" % server.BabelFish('en_fr',english) 28 | print "Spanish: '%s'" % server.BabelFish('en_es',english) 29 | print "Italian: '%s'" % server.BabelFish('en_it',english) 30 | print "German: '%s'" % server.BabelFish('en_de',english) 31 | 32 | print "Done." 33 | -------------------------------------------------------------------------------- /tests/Bug1161780.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | sys.path.insert(1, "..") 4 | from SOAPpy.Errors import Error 5 | from SOAPpy.Parser import parseSOAPRPC 6 | 7 | original = """ 8 | 12 | 13 | 14 | 15 | 16 | The CustomerID tag could not be found or the number contained in the tag was invalid 17 | 18 | """ 19 | 20 | try: 21 | parseSOAPRPC(original, attrs = 1) 22 | except Error, e: 23 | if e.msg != "expected nothing, got `ErrorString'": 24 | raise AssertionError, "Incorrect error message generated: " + e.msg 25 | else: 26 | raise AssertionError, "Incorrect error message generated" 27 | 28 | print "Success" 29 | -------------------------------------------------------------------------------- /tests/xmethods.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | ident = '$Id$' 5 | 6 | import os, re 7 | import sys 8 | sys.path.insert(1, "..") 9 | 10 | from SOAPpy import SOAPProxy 11 | 12 | # Check for a web proxy definition in environment 13 | try: 14 | proxy_url=os.environ['http_proxy'] 15 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 16 | proxy = "%s:%s" % (phost, pport) 17 | except: 18 | proxy = None 19 | 20 | 21 | print "##########################################" 22 | print " SOAP services registered at xmethods.net" 23 | print "##########################################" 24 | 25 | server = SOAPProxy("http://www.xmethods.net/interfaces/query", 26 | namespace = 'urn:xmethods-delayed-quotes', 27 | http_proxy=proxy) 28 | 29 | names = server.getAllServiceNames() 30 | 31 | for item in names: 32 | print 'name:', item['name'] 33 | print 'id :', item['id'] 34 | print 35 | -------------------------------------------------------------------------------- /tests/Bug916265.py: -------------------------------------------------------------------------------- 1 | """ 2 | Check handing of unicode. 3 | """ 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | from SOAPpy import * 8 | 9 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 10 | #Config.debug = 1 11 | #Config.dumpHeadersIn = 1 12 | #Config.dumpSOAPIn = 1 13 | #Config.dumpSOAPOut = 1 14 | 15 | # ask for returned SOAP responses to be converted to basic python types 16 | Config.simplify_objects = 0 17 | 18 | #Config.BuildWithNoType = 1 19 | #Config.BuildWithNoNamespacePrefix = 1 20 | 21 | server = SOAPProxy("http://localhost:9900/") 22 | 23 | x = u'uMOO' # Single unicode string 24 | y = server.echo_simple((x,)) 25 | assert( x==y[0] ) 26 | 27 | x = [u'uMoo1',u'uMoo2'] # array of unicode strings 28 | y = server.echo_simple(x) 29 | assert( x[0] == y[0] ) 30 | assert( x[1] == y[1] ) 31 | 32 | x = { 33 | u'A':1, 34 | u'B':u'B', 35 | 'C':u'C', 36 | 'D':'D' 37 | } 38 | y = server.echo_simple(x) 39 | 40 | for key in x.keys(): 41 | assert( x[key] == y[0][key] ) 42 | 43 | print "Success" 44 | -------------------------------------------------------------------------------- /tests/alanbushTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | ident = '$Id$' 6 | 7 | import os, re,sys 8 | 9 | # add local SOAPpy code to search path 10 | sys.path.insert(1, "..") 11 | 12 | from SOAPpy import * 13 | Config.debug=0 14 | 15 | # Check for a web proxy definition in environment 16 | try: 17 | proxy_url=os.environ['http_proxy'] 18 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 19 | proxy = "%s:%s" % (phost, pport) 20 | except: 21 | proxy = None 22 | 23 | SoapEndpointURL = 'http://www.alanbushtrust.org.uk/soap/compositions.asp' 24 | MethodNamespaceURI = 'urn:alanbushtrust-org-uk:soap.methods' 25 | SoapAction = MethodNamespaceURI + ".GetCategories" 26 | 27 | server = SOAPProxy(SoapEndpointURL, 28 | namespace=MethodNamespaceURI, 29 | soapaction=SoapAction, 30 | http_proxy=proxy 31 | ) 32 | 33 | for category in server.GetCategories(): 34 | print category 35 | -------------------------------------------------------------------------------- /zope/README: -------------------------------------------------------------------------------- 1 | Using SOAP with ZOPE 2 | -------------------- 3 | 4 | We can use Zope to provide web services. The first is to support SOAP like 5 | XML-RPC. There are two patches for Zope 2.5.0 version and for Zope 2.6.2 6 | version. To apply the path, you only need to do: 7 | 8 | $ cd 9 | $ patch -p1 < //zope-2.6.2-soappy.diff 10 | 11 | You need to install SOAPpy and fpconst. You can download this two packages 12 | from here: 13 | 14 | http://sourceforge.net/projects/pywebsvcs 15 | http://software.biostat.washington.edu/statsoft/snake/fpconst/ 16 | 17 | If you are using the precompiled version of Zope, you need to add the path 18 | to the PYTHONPATH environment variable to specify where this packages 19 | lives. 20 | To do this, add a line like this to your start script: 21 | 22 | export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.3/site-packages/ 23 | 24 | Note: This can be dangerous because in your machine you are using several 25 | versions of python. 26 | 27 | [NB: The contents of this directory contributed by Antonio Beamud 28 | Montero ] 29 | -------------------------------------------------------------------------------- /SOAPpy/wstools/test/test_wstools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ############################################################################ 4 | # Joshua R. Boverhof, David W. Robertson, LBNL 5 | # See LBNLCopyright for copyright notice! 6 | ########################################################################### 7 | 8 | import unittest, tarfile, os, ConfigParser 9 | import test_wsdl 10 | 11 | 12 | SECTION='files' 13 | CONFIG_FILE = 'config.txt' 14 | 15 | def extractFiles(section, option): 16 | config = ConfigParser.ConfigParser() 17 | config.read(CONFIG_FILE) 18 | archives = config.get(section, option) 19 | archives = eval(archives) 20 | for file in archives: 21 | tar = tarfile.open(file) 22 | if not os.access(tar.membernames[0], os.R_OK): 23 | for i in tar.getnames(): 24 | tar.extract(i) 25 | 26 | def makeTestSuite(): 27 | suite = unittest.TestSuite() 28 | suite.addTest(test_wsdl.makeTestSuite("services_by_file")) 29 | return suite 30 | 31 | def main(): 32 | extractFiles(SECTION, 'archives') 33 | unittest.main(defaultTest="makeTestSuite") 34 | 35 | if __name__ == "__main__" : main() 36 | 37 | 38 | -------------------------------------------------------------------------------- /tests/Bug1356261.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: SOAPtest.py,v 1.19 2004/04/01 13:25:46 warnes Exp $' 4 | 5 | import urllib 6 | import sys 7 | import unittest 8 | import re 9 | 10 | sys.path.insert(1, "..") 11 | from SOAPpy import * 12 | config=Config 13 | config.strict_range=1 14 | 15 | 16 | class SOAPTestCase(unittest.TestCase): 17 | def testAttributes(self): 18 | x = ''' 19 | 20 | 21 | 22 | 23 | 24 | My Life and Work 25 | 26 | 27 | Henry Ford 28 | 49 29 | 5.5 30 | 31 | 32 | 33 | 34 | 35 | ''' 36 | # parse rules 37 | y = parseSOAPRPC(x) 38 | self.assertEquals(y.Result.Book.title._attrs[(None, 'some_attr')], 'some_value'); 39 | 40 | if __name__ == '__main__': 41 | unittest.main() 42 | -------------------------------------------------------------------------------- /tests/esj_test_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | #standard imports 4 | import syslog, sys 5 | 6 | #domain specific imports 7 | sys.path.insert (1, '..') 8 | import SOAPpy 9 | 10 | class test_service: 11 | 12 | run = 1 13 | 14 | def test_integer(self,pass_integer): 15 | print type(pass_integer) 16 | return pass_integer 17 | 18 | def test_string(self,pass_string): 19 | print type(pass_string) 20 | return pass_string 21 | 22 | def test_float(self,pass_float): 23 | print type(pass_float) 24 | return pass_float 25 | 26 | def test_tuple(self,pass_tuple): 27 | print type(pass_tuple), pass_tuple 28 | return pass_tuple 29 | 30 | def test_list(self,pass_list): 31 | print type(pass_list), pass_list 32 | return pass_list 33 | 34 | def test_dictionary(self,pass_dictionary): 35 | print type(pass_dictionary), pass_dictionary 36 | return pass_dictionary 37 | 38 | def quit(self): 39 | self.run = 0 40 | 41 | server = SOAPpy.SOAPServer(("localhost",9999)) 42 | SOAPpy.Config.simplify_objects=1 43 | 44 | access_object = test_service() 45 | server.registerObject(access_object) 46 | 47 | while access_object.run: 48 | server.handle_request() 49 | -------------------------------------------------------------------------------- /tests/largeDataTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | from SOAPpy import Parser 10 | 11 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 12 | #Config.debug = 1 13 | 14 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 15 | server = SOAPProxy("https://localhost:9900") 16 | else: 17 | server = SOAPProxy("http://localhost:9900") 18 | 19 | 20 | # BIG data: 21 | 22 | big = repr('.' * (1<<18) ) 23 | 24 | # ...in an object 25 | print "server.echo_ino(big):..", 26 | tmp = server.echo_ino(big) 27 | print "done" 28 | 29 | # ...in an object in an object 30 | print "server.prop.echo2(big)..", 31 | tmp = server.prop.echo2(big) 32 | print "done" 33 | 34 | # ...with keyword arguments 35 | print 'server.echo_wkw(third = big, first = "one", second = "two")..', 36 | tmp = server.echo_wkw(third = big, first = "one", second = "two") 37 | print "done" 38 | 39 | # ...with a context object 40 | print "server.echo_wc(big)..", 41 | tmp = server.echo_wc(big) 42 | print "done" 43 | 44 | # ...with a header 45 | hd = headerType(data = {"mystring": "Hello World"}) 46 | print "server._hd(hd).echo_wc(big)..", 47 | tmp = server._hd(hd).echo_wc(big) 48 | print "done" 49 | 50 | server.quit() 51 | -------------------------------------------------------------------------------- /tests/quoteTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | ident = '$Id$' 5 | 6 | import os, re 7 | import sys 8 | sys.path.insert(1, "..") 9 | 10 | from SOAPpy import SOAPProxy 11 | 12 | # Check for a web proxy definition in environment 13 | try: 14 | proxy_url=os.environ['http_proxy'] 15 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 16 | proxy = "%s:%s" % (phost, pport) 17 | except: 18 | proxy = None 19 | 20 | # Three ways to do namespaces, force it at the server level 21 | 22 | server = SOAPProxy("http://services.xmethods.com:9090/soap", 23 | namespace = 'urn:xmethods-delayed-quotes', 24 | http_proxy=proxy) 25 | 26 | print "IBM>>", server.getQuote(symbol = 'IBM') 27 | 28 | # Do it inline ala SOAP::LITE, also specify the actually ns 29 | 30 | server = SOAPProxy("http://services.xmethods.com:9090/soap", 31 | http_proxy=proxy) 32 | print "IBM>>", server._ns('ns1', 33 | 'urn:xmethods-delayed-quotes').getQuote(symbol = 'IBM') 34 | 35 | # Create a namespaced version of your server 36 | 37 | dq = server._ns('urn:xmethods-delayed-quotes') 38 | print "IBM>>", dq.getQuote(symbol='IBM') 39 | print "ORCL>>", dq.getQuote(symbol='ORCL') 40 | print "INTC>>", dq.getQuote(symbol='INTC') 41 | -------------------------------------------------------------------------------- /bid/monitorClient.py: -------------------------------------------------------------------------------- 1 | from SOAPpy import SOAP 2 | import sys 3 | import getopt 4 | 5 | 6 | def usage(): 7 | print """usage: %s [options] 8 | -m, --method=METHOD#[,METHOD#...] specify METHOD# of ? for the list 9 | -p, --port=PORT# allows to specify PORT# of server 10 | """ 11 | sys.exit(1) 12 | 13 | def methodUsage(): 14 | print "The available methods are:" 15 | print "1. Monitor \t\t2. Clear" 16 | sys.exit(0) 17 | 18 | 19 | port = 12080 20 | methodnum = 1 21 | 22 | try: 23 | opts, args = getopt.getopt (sys.argv[1:], 'p:m:', ['method','port']) 24 | for opt, arg in opts: 25 | if opt in ('-m','--method'): 26 | if arg == '?': 27 | methodUsage() 28 | methodnum = int(arg) 29 | elif opt in ('-p', '--port'): 30 | port = int(arg) 31 | else: 32 | raise AttributeError, "Recognized but unimpl option '%s'" % opt 33 | except SystemExit: 34 | raise 35 | except: 36 | usage () 37 | 38 | ep = "http://208.177.157.221:%d/xmethodsInterop" % (port) 39 | sa = "urn:soapinterop" 40 | ns = "http://www.soapinterop.org/Bid" 41 | 42 | serv = SOAP.SOAPProxy(ep, namespace =ns, soapaction = sa) 43 | if methodnum == 1: 44 | print serv.Monitor(str="actzero") 45 | elif methodnum == 2: 46 | print serv.Clear(str="actzero") 47 | else: 48 | print "invalid methodnum" 49 | methodUsage() 50 | 51 | -------------------------------------------------------------------------------- /tests/Bug1366752.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: speedTest.py 243 2003-05-21 14:52:37Z warnes $' 4 | 5 | import time 6 | import sys 7 | from SOAPpy import fpconst 8 | sys.path.insert(1, "..") 9 | 10 | from SOAPpy import parseSOAP, parseSOAPRPC 11 | 12 | env = ''' 13 | 14 | %s 15 | ''' 16 | 17 | xml = env % ''' 18 | 19 | <_1 SOAP-ENC:arrayType="xsd:double[2]" xsi:type="SOAP-ENC:Array"> 20 | 3.3 21 | 4.4 22 | NaN 23 | Inf 24 | +Inf 25 | Infinity 26 | +Infinity 27 | -Inf 28 | -Infinity 29 | 30 | 31 | ''' 32 | 33 | 34 | x = parseSOAPRPC(xml)['_1'] 35 | 36 | assert( x[0:2] == [ 3.3, 4.4 ] ) 37 | assert( fpconst.isNaN( x[2] ) ) 38 | assert( fpconst.isPosInf( x[3] ) ) 39 | assert( fpconst.isPosInf( x[4] ) ) 40 | assert( fpconst.isPosInf( x[5] ) ) 41 | assert( fpconst.isPosInf( x[6] ) ) 42 | assert( fpconst.isNegInf( x[7] ) ) 43 | assert( fpconst.isNegInf( x[8] ) ) 44 | 45 | print "Success" 46 | 47 | -------------------------------------------------------------------------------- /tests/Bug918216.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.insert(1, "..") 3 | from SOAPpy import * 4 | 5 | detailed_fault = \ 6 | """ 7 | 8 | 9 | 10 | 11 | 12 | soapenv:Server.generalException 13 | Exception thrown on Server 14 | 15 | 16 | 17 | ... 18 | 19 | 20 | 21 | 22 | 23 | Login failure (504):Unknown User 24 | ... 25 | ... 26 | ... 27 | ... 28 | 29 | 30 | 31 | 32 | """ 33 | 34 | z = parseSOAPRPC(detailed_fault.strip() ) 35 | assert(z.__class__==faultType) 36 | assert(z.faultstring=="Exception thrown on Server") 37 | assert(z.detail.loginFailureFault.description=='Login failure (504):Unknown User') 38 | print "Success" 39 | -------------------------------------------------------------------------------- /tests/newsTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id$' 4 | 5 | import os, re 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import SOAPProxy 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | proxy = "%s:%s" % (phost, pport) 16 | except: 17 | proxy = None 18 | 19 | SoapEndpointURL = 'http://www22.brinkster.com/prasads/BreakingNewsService.asmx?WSDL' 20 | 21 | MethodNamespaceURI = 'http://tempuri.org/' 22 | 23 | # Three ways to do namespaces, force it at the server level 24 | 25 | server = SOAPProxy(SoapEndpointURL, namespace = MethodNamespaceURI, 26 | soapaction='http://tempuri.org/GetCNNNews', encoding = None, 27 | http_proxy=proxy) 28 | print "[server level CNN News call]" 29 | print server.GetCNNNews() 30 | 31 | # Do it inline ala SOAP::LITE, also specify the actually ns (namespace) and 32 | # sa (soapaction) 33 | 34 | server = SOAPProxy(SoapEndpointURL, encoding = None) 35 | print "[inline CNNNews call]" 36 | print server._ns('ns1', 37 | MethodNamespaceURI)._sa('http://tempuri.org/GetCNNNews').GetCNNNews() 38 | 39 | # Create an instance of your server with specific namespace and then use 40 | # inline soapactions for each call 41 | 42 | dq = server._ns(MethodNamespaceURI) 43 | print "[namespaced CNNNews call]" 44 | print dq._sa('http://tempuri.org/GetCNNNews').GetCNNNews() 45 | print "[namespaced CBSNews call]" 46 | print dq._sa('http://tempuri.org/GetCBSNews').GetCBSNews() 47 | -------------------------------------------------------------------------------- /tests/TemperatureService.wsdl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Returns current temperature in a given U.S. zipcode 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/Bug1936883.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id: speedTest.py 243 2003-05-21 14:52:37Z warnes $' 4 | 5 | import time 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | from SOAPpy import parseSOAP, parseSOAPRPC 10 | 11 | env = ''' 12 | 13 | %s 14 | ''' 15 | 16 | xml = env % ''' 17 | <_1 SOAP-ENC:arrayType="xsd:int[4]" SOAP-ENC:offset="[2]" xsi:type="SOAP-ENC:Array"> 18 | <_2 SOAP-ENC:arrayType="xsd:int[2]" xsi:type="SOAP-ENC:Array"> 19 | 1 20 | 2 21 | 22 | <_3 SOAP-ENC:arrayType="xsd:double[2]" xsi:type="SOAP-ENC:Array"> 23 | 3.3 24 | 4.4 25 | 26 | <_4 SOAP-ENC:arrayType="xsd:bool[2]" xsi:type="SOAP-ENC:Array"> 27 | 0 28 | 1 29 | 30 | <_5 SOAP-ENC:arrayType="xsd:bool[2]" xsi:type="SOAP-ENC:Array"> 31 | False 32 | True 33 | 34 | 35 | ''' 36 | 37 | 38 | x = parseSOAPRPC(xml) 39 | 40 | 41 | assert( x[2] == [ 1, 2 ] ) 42 | assert( x[3] == [ 3.3, 4.4 ] ) 43 | 44 | # These previously failed, instead having strings 45 | assert( x[4] == [ False, True ] ) 46 | assert( x[5] == [ False, True ] ) 47 | 48 | print "Success" 49 | 50 | -------------------------------------------------------------------------------- /tests/Bug1001646.py: -------------------------------------------------------------------------------- 1 | """ 2 | Check handing of unicode. 3 | """ 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | from SOAPpy import * 8 | 9 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 10 | #Config.debug = 1 11 | #Config.dumpHeadersIn = 1 12 | #Config.dumpSOAPIn = 1 13 | #Config.dumpSOAPOut = 1 14 | 15 | # ask for returned SOAP responses to be converted to basic python types 16 | Config.simplify_objects = 1 17 | 18 | #Config.BuildWithNoType = 1 19 | #Config.BuildWithNoNamespacePrefix = 1 20 | 21 | 22 | def headers(): 23 | '''Return a soap header containing all the needed information.''' 24 | hd = Types.headerType() 25 | hd.useragent = Types.stringType("foo") 26 | return hd 27 | 28 | server = SOAPProxy("http://localhost:9900/",header=headers()) 29 | 30 | adgroupid = 197497504 31 | keyword1 = { 'status': 'Moderate', 32 | 'adGroupId': 197497504, 33 | 'destinationURL': None, 34 | 'language': '', 35 | 'text': 'does not work', 36 | 'negative': bool(0), 37 | 'maxCpc': 50000, 38 | 'type': 'Keyword', 39 | 'id': 1 } 40 | keyword2 = { 'status': 'Moderate', 41 | 'adGroupId': 197497504, 42 | 'destinationURL': None, 43 | 'language': '', 44 | 'text': 'yes it does not', 45 | 'negative': bool(0), 46 | 'maxCpc': 50000, 47 | 'type': 'Keyword', 48 | 'id': 2 } 49 | keylist = [keyword1, keyword2] 50 | 51 | # Check that the data goes through properly 52 | 53 | retval = server.echo_simple(adgroupid, keylist) 54 | 55 | kw1 = retval[1][0] 56 | kw2 = retval[1][1] 57 | 58 | assert(retval[0] == adgroupid) 59 | 60 | for key in kw1.keys(): 61 | assert(kw1[key]==keyword1[key]) 62 | 63 | for key in kw2.keys(): 64 | assert(kw2[key]==keyword2[key]) 65 | 66 | # Check that the header is preserved 67 | retval = server.echo_header((adgroupid, keylist)) 68 | 69 | assert(retval[1].has_key('useragent')) 70 | assert(retval[1]['useragent'] == 'foo') 71 | 72 | server.quit() 73 | 74 | print "Success!" 75 | 76 | -------------------------------------------------------------------------------- /SOAPpy/wstools/test/README: -------------------------------------------------------------------------------- 1 | Two top level modules have been provided to run the tests. "test_wstools.py" 2 | is used to run all of the local tests. "test_wstools_net.py" is used to run 3 | all of the tests that require network access. 4 | 5 | Add the -v option for more informative feedback. 6 | 7 | ADDING TESTS: 8 | 1. For Stand-Alone tests add WSDL FILE to appropriate archive file 9 | Need to add a NEW Archive?: 10 | config.txt [files] "archive" -- tuple of all archive files, 11 | if you need to create a new archive append the archive 12 | name to the 'archive' tuple. 13 | 14 | 2. Edit config.txt section(s): 15 | option -- name by which service will be referenced in test case. 16 | Need an entry under appropriate section(s), this name 17 | must be unique within each section it appears but it may 18 | appear in multiple sections. 19 | 20 | config.txt "test" sections: 21 | Stand-Alone -- add "option" under [services_by_file] 22 | eg. amazon = exports/AmazonWebServices.wsdl 23 | 24 | Network -- add "option" under [services_by_http] 25 | eg. amazon = http://soap.amazon.com/schemas/AmazonWebServices.wsdl 26 | 27 | Broken -- add "option" under [broken] 28 | 29 | 3. Done 30 | 31 | 32 | CONTENTS OF SAMPLE WSDL/XSD: 33 | schema -- Taken from globus-3.0.1(http://www.globus.org) 34 | xmethods -- Taken from XMethods(http://www.xmethods.com) 35 | airport.wsdl 36 | AmazonWebServices.wsdl 37 | books.wsdl 38 | Distance.wsdl 39 | freedb.wsdl 40 | globalweather.wsdl 41 | IHaddock.wsdl 42 | ip2geo.wsdl 43 | magic.wsdl 44 | query.wsdl 45 | RateInfo.wsdl 46 | SHA1Encrypt.wsdl 47 | siteInspect.wsdl 48 | TemperatureService.wsdl 49 | usweather.wsdl 50 | rtf2html.xml 51 | SolveSystem.wsdl.xml 52 | zip2geo.wsdl 53 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | PYTHON=python 2 | 3 | default: echoClient echoHeader largeDataTest bugs \ 4 | card independent \ 5 | testClient1 outside_services 6 | 7 | bugs: Bug1001646 Bug916265 Bug1161780 Bug1936883 8 | 9 | echoClient: 10 | $(PYTHON) echoServer.py >& echoServer_echoClient.log & 11 | sleep 5s # wait for server to start up 12 | $(PYTHON) echoClient.py 13 | 14 | echoHeader: 15 | $(PYTHON) echoServer.py >& echoServer_echoHeader.log & 16 | sleep 5s # wait for server to start up 17 | $(PYTHON) echoHeader.py 18 | 19 | largeDataTest: 20 | $(PYTHON) echoServer.py >& echoServer_largeDataTest.log & 21 | sleep 5s # wait for server to start up 22 | $(PYTHON) largeDataTest.py 23 | 24 | card: 25 | $(PYTHON) cardServer.py >& cardServer.log & 26 | sleep 5s # wait for server to start up 27 | $(PYTHON) cardClient.py 28 | 29 | esj: 30 | $(PYTHON) esj_test_server.py >& esj_test.log & 31 | $(PYTHON) esj_test_client.py 32 | 33 | 34 | Bug1936883: 35 | $(PYTHON) Bug1936883.py 36 | 37 | Bug1161780: 38 | $(PYTHON) Bug1161780.py 39 | 40 | Bug1001646: 41 | $(PYTHON) echoServer.py >& echoServer_largeDataTest.log & 42 | sleep 5s # wait for server to start up 43 | $(PYTHON) Bug1001646.py 44 | 45 | Bug916265: 46 | $(PYTHON) echoServer.py >& echoServer_Bug916265.log & 47 | sleep 5s # wait for server to start up 48 | $(PYTHON) Bug916265.py 49 | 50 | outside_services: 51 | $(PYTHON) alanbushTest.py 52 | $(PYTHON) BabelfishWSDLTest.py 53 | $(PYTHON) GoogleTest.py 54 | $(PYTHON) quoteTest.py 55 | $(PYTHON) simpleWSDL.py 56 | $(PYTHON) testWSDL.py 57 | 58 | independent: 59 | $(PYTHON) speedTest.py 60 | $(PYTHON) Bug918216.py 61 | -$(PYTHON) ComplexTypes.py 62 | -$(PYTHON) SOAPtest.py # one subtest will fail 63 | $(PYTHON) TCtest.py 64 | $(PYTHON) testleak.py 65 | -$(PYTHON) translateTest.py 66 | -$(PYTHON) weatherTest.py 67 | -$(PYTHON) whoisTest.py 68 | -$(PYTHON) xmethods.py 69 | $(PYTHON) ZeroLengthArray.py 70 | 71 | testClient1: 72 | $(PYTHON) testClient1.py 73 | 74 | broken: 75 | $(PYTHON) newsTest.py 76 | $(PYTHON) excelTest.py 77 | $(PYTHON) storageTest.py 78 | -------------------------------------------------------------------------------- /tests/README: -------------------------------------------------------------------------------- 1 | $Id$ 2 | 3 | This file contains various python scripts for testing SOAPpy. 4 | 5 | Type "make" to run the tests. You can specify which Python interpreter 6 | to run the tests with, e.g. "make PYTHON=python2.5". 7 | 8 | All of the tests here work without generating errors EXCEPT: 9 | 10 | - SOAPtest.py 11 | 12 | Fails the 'testArray' test because 'referenced' elements are 13 | included in the return object. This is a known shortcoming of 14 | SOAPpy and is on the future features list. All other tests pass. 15 | 16 | - storageTest.py 17 | 18 | Fails because the hard-coded user/password combination is no 19 | longer valid. 20 | 21 | - translateTest.py 22 | 23 | Fails (gracefully) with a message that the service is no longer 24 | available. 25 | 26 | - excelTest.py 27 | 28 | Fails because the EXCEL service is not available. 29 | 30 | - testClient1.py 31 | 32 | This is experimental code for making unit tests that depend on 33 | running both a client and a server process. It failse because the 34 | code doesn't quite manage to get the server started up for the second 35 | test. This is a problem with the test, not with SOAPpy, but we 36 | intend to get it fixed so that we can create better unit tests. 37 | 38 | The test files which rely on no-longer available servers should be 39 | removed unless we can find a replacement. This will wait for a cleanup 40 | associated with release of version 1.0. 41 | 42 | Also note that serveral of the client tests need to have the 43 | corresponding server running: 44 | 45 | Client Server 46 | ---------------------- ------------------------ 47 | cardClient.py cardServer.py 48 | echoClient.py echoServer.py 49 | echoHeader.py echoServer.py 50 | esj_test_client.py esj_test_server.py 51 | largeDataTest.py echoServer.py 52 | speedTest.py echoServer.py 53 | 54 | Of course, tests which rely on access to an external URL require that 55 | the web is accessible. If you are behind a firewall, try setting the 56 | http_proxy environment variable to the URL of your web proxy. 57 | 58 | -------------------------------------------------------------------------------- /tests/esj_test_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | 3 | #standard imports 4 | import syslog, sys 5 | 6 | #domain specific imports 7 | sys.path.insert (1, '..') 8 | import SOAPpy 9 | 10 | SOAPpy.Config.simplify_objects=1 11 | 12 | ## def test_integer(self,pass_integer): 13 | ## def test_string(self,pass_string): 14 | ## def test_float(self,pass_float): 15 | ## def test_tuple(self,pass_tuple): 16 | ## def test_list(self,pass_list): 17 | ## def test_dictionary(self,pass_dictionary): 18 | 19 | if __name__ == "__main__": 20 | 21 | server = SOAPpy.SOAPProxy("http://localhost:9999") 22 | 23 | original_integer = 5 24 | result_integer = server.test_integer(original_integer) 25 | print "original_integer %s" % original_integer 26 | print "result_integer %s" % result_integer 27 | assert(result_integer==original_integer) 28 | print 29 | 30 | original_string = "five" 31 | result_string = server.test_string(original_string) 32 | print "original_string %s" % original_string 33 | print "result_string %s" % result_string 34 | assert(result_string==original_string) 35 | print 36 | 37 | original_float = 5.0 38 | result_float = server.test_float(original_float) 39 | print "original_float %s" % original_float 40 | print "result_float %s" % result_float 41 | assert(result_float==original_float) 42 | print 43 | 44 | original_tuple = (1,2,"three","four",5) 45 | result_tuple = server.test_tuple(original_tuple) 46 | print "original_tuple %s" % str(original_tuple) 47 | print "result_tuple %s" % str(result_tuple) 48 | assert(tuple(result_tuple)==original_tuple) 49 | print 50 | 51 | original_list = [5,4,"three",2,1] 52 | result_list = server.test_list(original_list) 53 | print "original_list %s" % original_list 54 | print "result_list %s" % result_list 55 | assert(result_list==original_list) 56 | print 57 | 58 | original_dictionary = { 59 | 'one': 1, 60 | "two": 2, 61 | "three": 3, 62 | "four": 4, 63 | "five": 5, 64 | } 65 | result_dictionary = server.test_dictionary(original_dictionary) 66 | print "original_dictionary %s" % original_dictionary 67 | print "result_dictionary %s" % result_dictionary 68 | assert(result_dictionary==original_dictionary) 69 | print 70 | 71 | server.quit() 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ============================================== 2 | SOAPpy - Simple to use SOAP library for Python 3 | ============================================== 4 | 5 | Current Maintainers: 6 | 7 | Gregory R. Warnes 8 | Christopher Blunck 9 | 10 | Original Authors: 11 | 12 | Cayce Ullman 13 | Brian Matthews 14 | 15 | Contributions by: 16 | 17 | Brad Knotwell 18 | Mark Bucciarelli (ported WSDL 19 | client from ZSI) 20 | Ivan R. Judson (Globus support) 21 | Kirk Strauser 22 | Antonio Beamud Montero (patches 23 | for integrating SOAPpy into Zope) 24 | 25 | Copyright (c) 2002-2003, Pfizer, Inc. 26 | Copyright (c) 2001, Cayce Ullman. 27 | Copyright (c) 2001, Brian Matthews. 28 | All rights reserved. 29 | 30 | LICENSE: 31 | ---------------------------------------------------------------------------- 32 | Redistribution and use in source and binary forms, with or without 33 | modification, are permitted provided that the following conditions are met: 34 | 35 | Redistributions of source code must retain the above copyright notice, this 36 | list of conditions and the following disclaimer. 37 | Redistributions in binary form must reproduce the above copyright notice, 38 | this list of conditions and the following disclaimer in the documentation 39 | and/or other materials provided with the distribution. 40 | 41 | Neither the name of actzero, inc. nor the names of its contributors may 42 | be used to endorse or promote products derived from this software without 43 | specific prior written permission. 44 | 45 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 46 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 49 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 51 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 52 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 55 | DAMAGE. 56 | 57 | -------------------------------------------------------------------------------- /SOAPpy/wstools/ZPL: -------------------------------------------------------------------------------- 1 | Zope Public License (ZPL) Version 2.0 2 | ----------------------------------------------- 3 | 4 | This software is Copyright (c) Zope Corporation (tm) and 5 | Contributors. All rights reserved. 6 | 7 | This license has been certified as open source. It has also 8 | been designated as GPL compatible by the Free Software 9 | Foundation (FSF). 10 | 11 | Redistribution and use in source and binary forms, with or 12 | without modification, are permitted provided that the 13 | following conditions are met: 14 | 15 | 1. Redistributions in source code must retain the above 16 | copyright notice, this list of conditions, and the following 17 | disclaimer. 18 | 19 | 2. Redistributions in binary form must reproduce the above 20 | copyright notice, this list of conditions, and the following 21 | disclaimer in the documentation and/or other materials 22 | provided with the distribution. 23 | 24 | 3. The name Zope Corporation (tm) must not be used to 25 | endorse or promote products derived from this software 26 | without prior written permission from Zope Corporation. 27 | 28 | 4. The right to distribute this software or to use it for 29 | any purpose does not give you the right to use Servicemarks 30 | (sm) or Trademarks (tm) of Zope Corporation. Use of them is 31 | covered in a separate agreement (see 32 | http://www.zope.com/Marks). 33 | 34 | 5. If any files are modified, you must cause the modified 35 | files to carry prominent notices stating that you changed 36 | the files and the date of any change. 37 | 38 | Disclaimer 39 | 40 | THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS'' 41 | AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 42 | NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 43 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 44 | NO EVENT SHALL ZOPE CORPORATION OR ITS CONTRIBUTORS BE 45 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 46 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 47 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 48 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 50 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 51 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 52 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 53 | DAMAGE. 54 | 55 | 56 | This software consists of contributions made by Zope 57 | Corporation and many individuals on behalf of Zope 58 | Corporation. Specific attributions are listed in the 59 | accompanying credits file. 60 | 61 | 62 | -------------------------------------------------------------------------------- /SOAPpy/wstools/license.txt: -------------------------------------------------------------------------------- 1 | ********* 2 | 3 | Copyright (c) 2003, The Regents of the University of California, 4 | through Lawrence Berkeley National Laboratory (subject to receipt of 5 | any required approvals from the U.S. Dept. of Energy). All rights 6 | reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are 10 | met: 11 | (1) Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | (2) Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | (3) Neither the name of the University of California, Lawrence 17 | Berkeley National Laboratory, U.S. Dept. of Energy nor the names of 18 | its contributors may be used to endorse or promote products derived 19 | from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | You are under no obligation whatsoever to provide any bug fixes, 34 | patches, or upgrades to the features, functionality or performance of 35 | the source code ("Enhancements") to anyone; however, if you choose to 36 | make your Enhancements available either publicly, or directly to 37 | Lawrence Berkeley National Laboratory, without imposing a separate 38 | written license agreement for such Enhancements, then you hereby grant 39 | the following license: a non-exclusive, royalty-free perpetual 40 | license to install, use, modify, prepare derivative works, incorporate 41 | into other computer software, distribute, and sublicense such 42 | enhancements or derivative works thereof, in binary and source code form. 43 | 44 | ********* 45 | -------------------------------------------------------------------------------- /SOAPpy/wstools/XMLname.py: -------------------------------------------------------------------------------- 1 | """Translate strings to and from SOAP 1.2 XML name encoding 2 | 3 | Implements rules for mapping application defined name to XML names 4 | specified by the w3 SOAP working group for SOAP version 1.2 in 5 | Appendix A of "SOAP Version 1.2 Part 2: Adjuncts", W3C Working Draft 6 | 17, December 2001, 7 | 8 | Also see . 9 | 10 | Author: Gregory R. Warnes 11 | Date:: 2002-04-25 12 | Version 0.9.0 13 | 14 | """ 15 | 16 | ident = "$Id$" 17 | 18 | from re import * 19 | 20 | 21 | def _NCNameChar(x): 22 | return x.isalpha() or x.isdigit() or x=="." or x=='-' or x=="_" 23 | 24 | 25 | def _NCNameStartChar(x): 26 | return x.isalpha() or x=="_" 27 | 28 | 29 | def _toUnicodeHex(x): 30 | hexval = hex(ord(x[0]))[2:] 31 | hexlen = len(hexval) 32 | # Make hexval have either 4 or 8 digits by prepending 0's 33 | if (hexlen==1): hexval = "000" + hexval 34 | elif (hexlen==2): hexval = "00" + hexval 35 | elif (hexlen==3): hexval = "0" + hexval 36 | elif (hexlen==4): hexval = "" + hexval 37 | elif (hexlen==5): hexval = "000" + hexval 38 | elif (hexlen==6): hexval = "00" + hexval 39 | elif (hexlen==7): hexval = "0" + hexval 40 | elif (hexlen==8): hexval = "" + hexval 41 | else: raise Exception, "Illegal Value returned from hex(ord(x))" 42 | 43 | return "_x"+ hexval + "_" 44 | 45 | 46 | def _fromUnicodeHex(x): 47 | return eval( r'u"\u'+x[2:-1]+'"' ) 48 | 49 | 50 | def toXMLname(string): 51 | """Convert string to a XML name.""" 52 | if string.find(':') != -1 : 53 | (prefix, localname) = string.split(':',1) 54 | else: 55 | prefix = None 56 | localname = string 57 | 58 | T = unicode(localname) 59 | 60 | N = len(localname) 61 | X = []; 62 | for i in range(N) : 63 | if i< N-1 and T[i]==u'_' and T[i+1]==u'x': 64 | X.append(u'_x005F_') 65 | elif i==0 and N >= 3 and \ 66 | ( T[0]==u'x' or T[0]==u'X' ) and \ 67 | ( T[1]==u'm' or T[1]==u'M' ) and \ 68 | ( T[2]==u'l' or T[2]==u'L' ): 69 | X.append(u'_xFFFF_' + T[0]) 70 | elif (not _NCNameChar(T[i])) or (i==0 and not _NCNameStartChar(T[i])): 71 | X.append(_toUnicodeHex(T[i])) 72 | else: 73 | X.append(T[i]) 74 | 75 | if prefix: 76 | return "%s:%s" % (prefix, u''.join(X)) 77 | return u''.join(X) 78 | 79 | 80 | def fromXMLname(string): 81 | """Convert XML name to unicode string.""" 82 | 83 | retval = sub(r'_xFFFF_','', string ) 84 | 85 | def fun( matchobj ): 86 | return _fromUnicodeHex( matchobj.group(0) ) 87 | 88 | retval = sub(r'_x[0-9A-Za-z]+_', fun, retval ) 89 | 90 | return retval 91 | -------------------------------------------------------------------------------- /tests/echoClient.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | 10 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 11 | #Config.debug = 1 12 | #Config.dumpHeadersIn = 1 13 | #Config.dumpSOAPIn = 1 14 | #Config.dumpSOAPOut = 1 15 | 16 | # ask for returned SOAP responses to be converted to basic python types 17 | Config.simplify_objects = 1 18 | 19 | #Config.BuildWithNoType = 1 20 | #Config.BuildWithNoNamespacePrefix = 1 21 | 22 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 23 | # Use secure http 24 | pathserver = SOAPProxy("https://localhost:9900/pathtest") 25 | server = SOAPProxy("https://localhost:9900") 26 | 27 | elif len(sys.argv) > 1 and sys.argv[1] == '-g': 28 | # use Globus for communication 29 | import pyGlobus 30 | pathserver = SOAPProxy("httpg://localhost:9900/pathtest") 31 | server = SOAPProxy("httpg://localhost:9900") 32 | 33 | else: 34 | # Default: use standard http 35 | pathserver = SOAPProxy("http://localhost:9900/pathtest") 36 | server = SOAPProxy("http://localhost:9900") 37 | 38 | # Echo... 39 | 40 | try: 41 | print server.echo("MOO") 42 | except Exception, e: 43 | print "Caught exception: ", e 44 | try: 45 | print pathserver.echo("MOO") 46 | except Exception, e: 47 | print "Caught exception: ", e 48 | 49 | # ...in an object 50 | try: 51 | print server.echo_ino("moo") 52 | except Exception, e: 53 | print "Caught exception: ", e 54 | try: 55 | print pathserver.echo_ino("cow") 56 | except Exception, e: 57 | print "Caught exception: ", e 58 | 59 | # ...in an object in an object 60 | try: 61 | print server.prop.echo2("moo") 62 | except Exception, e: 63 | print "Caught exception: ", e 64 | 65 | try: 66 | print pathserver.prop.echo2("cow") 67 | except Exception, e: 68 | print "Caught exception: ", e 69 | 70 | # ...with keyword arguments 71 | try: 72 | print server.echo_wkw(third = "three", first = "one", second = "two") 73 | except Exception, e: 74 | print "Caught exception: ", e 75 | try: 76 | print pathserver.echo_wkw(third = "three", first = "one", second = "two") 77 | except Exception, e: 78 | print "Caught exception: ", e 79 | 80 | # ...with a context object 81 | try: 82 | print server.echo_wc("moo") 83 | except Exception, e: 84 | print "Caught exception: ", e 85 | try: 86 | print pathserver.echo_wc("cow") 87 | except Exception, e: 88 | print "Caught exception: ", e 89 | 90 | # ...with a header 91 | hd = headerType(data = {"mystring": "Hello World"}) 92 | try: 93 | print server._hd(hd).echo_wc("moo") 94 | except Exception, e: 95 | print "Caught exception: ", e 96 | try: 97 | print pathserver._hd(hd).echo_wc("cow") 98 | except Exception, e: 99 | print "Caught exception: ", e 100 | 101 | # close down server 102 | server.quit() 103 | -------------------------------------------------------------------------------- /SOAPpy.spec: -------------------------------------------------------------------------------- 1 | Summary: SOAPpy 2 | Name: SOAPpy 3 | Version: 0.9.7 4 | Release: 2 5 | License: Copyright (c) 2001, Cayce Ullman. 6 | Group: Productivity/Networking/Web/Applications 7 | Source: SOAPpy-%{version}.tgz 8 | Requires: python >= 2.2 9 | BuildArch: noarch 10 | AutoReq: no 11 | Packager: Antonio Beamud Montero 12 | 13 | %description 14 | SOAP implementation by Cayce Ullman and Brian Matthews. 15 | %prep 16 | %setup SOAPpy-%{version} 17 | 18 | %build 19 | 20 | %install 21 | mkdir -p /usr/share/doc/SOAPpy/bid 22 | cp -a bid/* /usr/share/doc/SOAPpy/bid 23 | mkdir -p /usr/share/doc/SOAPpy/tests 24 | cp -a tests/* /usr/share/doc/SOAPpy/tests 25 | cp -a TCtest.py /usr/share/doc/SOAPpy/tests 26 | mkdir -p /usr/share/doc/SOAPpy/contrib 27 | cp contrib/* /usr/share/doc/SOAPpy/contrib/ 28 | cp docs/* /usr/share/doc/SOAPpy/ 29 | mkdir -p /usr/share/doc/SOAPpy/tools 30 | cp -a tools/* /usr/share/doc/SOAPpy/tools 31 | cp README /usr/share/doc/SOAPpy/ 32 | cp echoServer.py /usr/share/doc/SOAPpy/ 33 | cp speedTest.py /usr/share/doc/SOAPpy/ 34 | cp CHANGELOG /usr/share/doc/SOAPpy/ 35 | cp SOAPtest.py /usr/share/doc/SOAPpy/tests 36 | cp excelTest.py /usr/share/doc/SOAPpy/ 37 | cp echoClient.py /usr/share/doc/SOAPpy/ 38 | mkdir -p /usr/share/doc/SOAPpy/validate 39 | cp -a validate/* /usr/share/doc/SOAPpy/validate 40 | cp SOAP.py /usr/lib/python/site-packages/ 41 | 42 | %clean 43 | 44 | %pre 45 | 46 | %post 47 | 48 | %preun 49 | 50 | %postun 51 | 52 | %files 53 | %defattr(-,root,root) 54 | /usr/share/doc/SOAPpy/bid/monitorClient.py 55 | /usr/share/doc/SOAPpy/bid/inventoryServer.py 56 | /usr/share/doc/SOAPpy/bid/inventory.servers 57 | /usr/share/doc/SOAPpy/bid/inventoryClient.py 58 | /usr/share/doc/SOAPpy/tests/TCtest.py 59 | /usr/share/doc/SOAPpy/simpleTypes.txt 60 | /usr/share/doc/SOAPpy/attrs.txt 61 | /usr/share/doc/SOAPpy/quickstart.txt 62 | /usr/share/doc/SOAPpy/complexTypes.txt 63 | /usr/share/doc/SOAPpy/contrib/soap_cli.py 64 | /usr/share/doc/SOAPpy/contrib/soap_handler.py 65 | /usr/share/doc/SOAPpy/tests/cardServer.py 66 | /usr/share/doc/SOAPpy/tests/guidTest.py 67 | /usr/share/doc/SOAPpy/tests/alanbushTest.py 68 | /usr/share/doc/SOAPpy/tests/newsTest.py 69 | /usr/share/doc/SOAPpy/tests/weatherTest.py 70 | /usr/share/doc/SOAPpy/tests/fortuneTest.py 71 | /usr/share/doc/SOAPpy/tests/cardClient.py 72 | /usr/share/doc/SOAPpy/tests/quoteTest.py 73 | /usr/share/doc/SOAPpy/tests/storageTest.py 74 | /usr/share/doc/SOAPpy/tests/wordFindTest.py 75 | /usr/share/doc/SOAPpy/tests/itimeTest.py 76 | /usr/share/doc/SOAPpy/tests/whoisTest.py 77 | /usr/share/doc/SOAPpy/tests/translateTest.py 78 | /usr/share/doc/SOAPpy/tools/interop2html.py 79 | /usr/share/doc/SOAPpy/README 80 | /usr/share/doc/SOAPpy/echoServer.py 81 | /usr/share/doc/SOAPpy/speedTest.py 82 | /usr/share/doc/SOAPpy/CHANGELOG 83 | /usr/share/doc/SOAPpy/tests/SOAPtest.py 84 | /usr/share/doc/SOAPpy/excelTest.py 85 | /usr/share/doc/SOAPpy/echoClient.py 86 | /usr/share/doc/SOAPpy/validate/silab.servers 87 | /usr/share/doc/SOAPpy/validate/silabserver.py 88 | /usr/share/doc/SOAPpy/validate/server.pem 89 | /usr/share/doc/SOAPpy/validate/silabclient.py 90 | /usr/share/doc/SOAPpy/validate/soapware.py 91 | /usr/lib/python2.2/site-packages/SOAP.py -------------------------------------------------------------------------------- /tests/speedTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id$' 4 | 5 | import time 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | x=''' 13 | 14 | 15 | USA 16 | japan 17 | 18 | 19 | ''' 20 | 21 | x2=''' 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | West Virginia 33 | -546 34 | -5.398 35 | 36 | 37 | New Mexico 38 | -641 39 | -9.351 40 | 41 | 42 | Missouri 43 | -819 44 | 1.495 45 | 46 | 47 | 48 | ''' 49 | 50 | # Import in function, because for some reason they slow each other 51 | # down in same namespace ??? 52 | def SOAPParse(inxml): 53 | from SOAPpy import parseSOAPRPC 54 | t= time.time() 55 | parseSOAPRPC(inxml) 56 | return time.time()-t 57 | 58 | def SAXParse(inxml): 59 | import xml.sax 60 | y = xml.sax.handler.ContentHandler() 61 | t= time.time() 62 | xml.sax.parseString(inxml,y) 63 | return time.time()-t 64 | 65 | def DOMParse(inxml): 66 | import xml.dom.minidom 67 | t= time.time() 68 | xml.dom.minidom.parseString(inxml) 69 | return time.time()-t 70 | 71 | # Wierd but the SAX parser runs really slow the first time. 72 | # Probably got to load a c module or something 73 | SAXParse(x) 74 | print 75 | print "Simple XML" 76 | print "SAX Parse, no marshalling ", SAXParse(x) 77 | print "SOAP Parse, and marshalling ", SOAPParse(x) 78 | print "DOM Parse, no marshalling ", DOMParse(x) 79 | print 80 | print "Complex XML (references)" 81 | print "SAX Parse, no marshalling ", SAXParse(x2) 82 | print "SOAP Parse, and marshalling ", SOAPParse(x2) 83 | print "DOM Parse, no marshalling ", DOMParse(x2) 84 | -------------------------------------------------------------------------------- /SOAPpy/Errors.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################################################################ 3 | # 4 | # SOAPpy - Cayce Ullman (cayce@actzero.com) 5 | # Brian Matthews (blm@actzero.com) 6 | # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) 7 | # Christopher Blunck (blunck@gst.com) 8 | # 9 | ################################################################################ 10 | # Copyright (c) 2003, Pfizer 11 | # Copyright (c) 2001, Cayce Ullman. 12 | # Copyright (c) 2001, Brian Matthews. 13 | # 14 | # All rights reserved. 15 | # 16 | # Redistribution and use in source and binary forms, with or without 17 | # modification, are permitted provided that the following conditions are met: 18 | # Redistributions of source code must retain the above copyright notice, this 19 | # list of conditions and the following disclaimer. 20 | # 21 | # Redistributions in binary form must reproduce the above copyright notice, 22 | # this list of conditions and the following disclaimer in the documentation 23 | # and/or other materials provided with the distribution. 24 | # 25 | # Neither the name of actzero, inc. nor the names of its contributors may 26 | # be used to endorse or promote products derived from this software without 27 | # specific prior written permission. 28 | # 29 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 30 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 33 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 36 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | # 40 | ################################################################################ 41 | """ 42 | 43 | ident = '$Id$' 44 | from version import __version__ 45 | 46 | import exceptions 47 | 48 | ################################################################################ 49 | # Exceptions 50 | ################################################################################ 51 | class Error(exceptions.Exception): 52 | def __init__(self, msg): 53 | self.msg = msg 54 | def __str__(self): 55 | return "" % self.msg 56 | __repr__ = __str__ 57 | def __call__(self): 58 | return (msg,) 59 | 60 | class RecursionError(Error): 61 | pass 62 | 63 | class UnknownTypeError(Error): 64 | pass 65 | 66 | class HTTPError(Error): 67 | # indicates an HTTP protocol error 68 | def __init__(self, code, msg): 69 | self.code = code 70 | self.msg = msg 71 | def __str__(self): 72 | return "" % (self.code, self.msg) 73 | __repr__ = __str__ 74 | def __call___(self): 75 | return (self.code, self.msg, ) 76 | 77 | class UnderflowError(exceptions.ArithmeticError): 78 | pass 79 | 80 | -------------------------------------------------------------------------------- /docs/UsingHeaders.txt: -------------------------------------------------------------------------------- 1 | Using Headers 2 | ============= 3 | 4 | SOAPpy has a Header class to hold data for the header of a SOAP message. 5 | Each Header instance has methods to set/get the MustUnderstand attribute, and 6 | methods to set/get the Actor attribute. 7 | 8 | SOAPpy also has a SOAPContext class so that each server method can be 9 | implemented in such a way that it gets the context of the connecting client. 10 | This includes both common SOAP information and connection information (see 11 | below for an example). 12 | 13 | CLIENT EXAMPLES 14 | --------------- 15 | 16 | ## CODE 17 | import SOAPpy 18 | test = 42 19 | server = SOAPpy.SOAPProxy("http://localhost:8888") 20 | server = server._sa ("urn:soapinterop") 21 | 22 | hd = SOAPpy.Header() 23 | hd.InteropTestHeader ='This should fault, as you don\'t understand the header.' 24 | hd._setMustUnderstand ('InteropTestHeader', 0) 25 | hd._setActor ('InteropTestHeader','http://schemas.xmlsoap.org/soap/actor/next') 26 | server = server._hd (hd) 27 | 28 | print server.echoInteger (test) 29 | ## /CODE 30 | 31 | This should succeed (provided the server has defined echoInteger), as it 32 | builds a valid header into this client with MustUnderstand set to 0 33 | and then sends the SOAP with this header. 34 | 35 | 36 | ## CODE 37 | import SOAPpy 38 | test = 42 39 | server = SOAPpy.SOAPProxy("http://localhost:8888") 40 | server = server._sa ("urn:soapinterop") 41 | #Header 42 | hd = SOAPpy.Header() 43 | hd.InteropTestHeader = 'This should fault,as you don\'t understand the header.' 44 | hd._setMustUnderstand ('InteropTestHeader', 1) 45 | hd._setActor ('InteropTestHeader','http://schemas.xmlsoap.org/soap/actor/next') 46 | server = server._hd (hd) 47 | 48 | print server.echoInteger (test) 49 | ## /CODE 50 | 51 | This should fail (even if the server has defined 'echoInteger'), as it 52 | builds a valid header into this client, but sets MustUnderstand to 1 53 | for a message that the server presumably won't understand before sending. 54 | 55 | 56 | 57 | 58 | SERVER EXAMPLES 59 | --------------- 60 | 61 | ## CODE 62 | import SOAPpy 63 | def echoInteger (inputInteger): 64 | return inputInteger 65 | server = SOAPpy.SOAPServer ( ('localhost', 8080) ) 66 | server.registerFunction (echoInteger) 67 | server.serve_forever() 68 | ## /CODE 69 | 70 | This is a simple server designed to work with the first 2 clients above. 71 | 72 | 73 | ## CODE 74 | import SOAPpy 75 | def echoInteger (inputInteger, _SOAPContext): 76 | c = _SOAPContext 77 | print c.xmldata 78 | print c.header 79 | print c.body 80 | print c.connection.getpeername() 81 | print c.soapaction 82 | print c.httpheaders 83 | return inputInteger 84 | 85 | host = 'localhost' 86 | port = 8888 87 | 88 | server = SOAPpy.SOAPServer ( (host, port) ) 89 | server.registerFunction (SOAPpy.MethodSig(echoInteger, keywords=0,context=1)) 90 | 91 | server.serve_forever() 92 | ## /CODE 93 | 94 | This is a server which shows off the SOAPContext feature. This 95 | server gets a context from the client that has connected to it, and 96 | prints some of the pertinent aspects of that client before 97 | returning. This server should also work with the code for the two 98 | clients written above. 99 | 100 | 101 | 102 | 103 | 104 | $Id$ 105 | -------------------------------------------------------------------------------- /tools/interop2html.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import string 4 | import cgi 5 | 6 | ident = '$Id$' 7 | 8 | lines = open('output.txt').readlines() 9 | #preserve the tally 10 | tally = lines[-6:] 11 | #whack the tally from lines 12 | lines = lines[:-6] 13 | table={} 14 | for line in lines: 15 | if line[:3] == ' ' or line == '>\n' : continue 16 | line = line[:-1] #delete end of line char 17 | row = [line[:line.find(': ')], line[line.find(': ')+2:]] #split server name from rest of line 18 | restofrow = row[1].split(' ',3) #break out method name, number, status code, status comment 19 | if len(restofrow) > 3: 20 | if restofrow[3].find('as expected') != -1: 21 | restofrow[2] = restofrow[2] + ' (as expected)' 22 | elif restofrow[3][:2] == '- ' : 23 | restofrow[3] = restofrow[3][2:] 24 | try: table[row[0]].append([restofrow[0],restofrow[2:]]) 25 | except KeyError: table[row[0]] = [[restofrow[0],restofrow[2:]]] 26 | 27 | print "" 28 | print "" 34 | print "
" 35 | for x in tally: 36 | z = x[:-1].split(":",1) 37 | print "" 38 | print "
Summary
",z[0],"",z[1],"

" 39 | c = 0 40 | totalmethods = len(table[table.keys()[0]]) 41 | while c < totalmethods: 42 | print "
" 43 | print "" 44 | cols = [c, c + 1, c + 2] 45 | if c != 16: 46 | cols += [c + 3] 47 | for i in cols: 48 | try: header = table[table.keys()[0]][i][0] 49 | except: break 50 | print "" 51 | print "" 52 | l = table.keys() 53 | l.sort() 54 | for key in l: 55 | print "" 56 | for i in cols: 57 | try: status = table[key][i][1][0] 58 | except: break 59 | if status.find("succeed") != -1: 60 | bgcolor = "#339900" 61 | status = "Pass" 62 | elif status.find("expected") != -1: 63 | bgcolor = "#FF9900" 64 | hreftitle = table[key][i][1][1].replace("'","") # remove apostrophes from title properties 65 | popuphtml = '"' + cgi.escape(cgi.escape(table[key][i][1][1]).replace("'","'").replace('"',""")) + '"' 66 | status = "Failed (expected)" 67 | else: 68 | bgcolor = "#CC0000" 69 | hreftitle = table[key][i][1][1].replace("'","") # remove apostrophes from title properties 70 | popuphtml = '"' + cgi.escape(cgi.escape(table[key][i][1][1]).replace("'","'").replace('"',""")) + '"' 71 | status = "Failed" 72 | print "" 73 | print "" 74 | print "
",header,"
", key , "" , status , "
" 75 | c = c + len(cols) 76 | print "" 77 | -------------------------------------------------------------------------------- /tests/cardServer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import string 6 | import sys 7 | 8 | sys.path.insert (1, '..') 9 | 10 | from SOAPpy import * 11 | 12 | ident = '$Id$' 13 | 14 | # create the list of all cards, and keep strings for each suit 15 | __cs = "Clubs" 16 | __ds = "Diamonds" 17 | __hs = "Hearts" 18 | __ss = "Spades" 19 | __cards = [] 20 | for suit in [__cs, __ds, __hs, __ss]: 21 | for num in range(9): 22 | num += 1 23 | __cards.append(str(num+1)+" of "+suit) 24 | for face in ["ace","King","Queen","Jack"]: 25 | __cards.append(face+" of "+suit) 26 | 27 | 28 | def deal(num): 29 | if num not in range(1,53): 30 | return -1 31 | else: 32 | alreadydealt = [] 33 | ignore = 0 34 | handdealt = [] 35 | import whrandom 36 | while num > 0: 37 | idx = int(str(whrandom.random())[2:4]) 38 | if idx in range(52) and idx not in alreadydealt: 39 | handdealt.append(__cards[idx]) 40 | alreadydealt.append(idx) 41 | num -= 1 42 | else: 43 | ignore += 1 44 | continue 45 | return handdealt 46 | 47 | def arrangeHand(hand): 48 | c = [] 49 | d = [] 50 | h = [] 51 | s = [] 52 | import string 53 | for card in hand: 54 | if string.find(card, __cs) != -1: 55 | c.append(card) 56 | elif string.find(card, __ds) != -1: 57 | d.append(card) 58 | elif string.find(card, __hs) != -1: 59 | h.append(card) 60 | elif string.find(card, __ss) != -1: 61 | s.append(card) 62 | for cards, str in ((c, __cs),(d, __ds),(h,__hs), (s,__ss)): 63 | cards.sort() 64 | idx = 0 65 | if "10 of "+str in cards: 66 | cards.remove("10 of "+str) 67 | if "Jack of "+str in cards: idx += 1 68 | if "Queen of "+str in cards: idx += 1 69 | if "King of "+str in cards: idx += 1 70 | if "ace of "+str in cards: idx +=1 71 | cards.insert(len(cards)-idx,"10 of "+str) 72 | if "King of "+str in cards: 73 | cards.remove("King of "+str) 74 | if "ace of "+str in cards: cards.insert(len(cards)-1,"King of "+str) 75 | else: cards.append("King of "+str) 76 | return c+d+h+s 77 | 78 | def dealHand (NumberOfCards, StringSeparator): 79 | hand = deal(NumberOfCards) 80 | return string.join(hand,StringSeparator) 81 | 82 | 83 | def dealArrangedHand (NumberOfCards, StringSeparator): 84 | if NumberOfCards < 1 or NumberOfCards > 52: 85 | raise ValueError, "NumberOfCards must be between 1 and 52" 86 | unarranged = deal(NumberOfCards) 87 | hand = arrangeHand(unarranged) 88 | return string.join(hand, StringSeparator) 89 | 90 | def dealCard (): 91 | return deal(1)[0] 92 | 93 | run = 1 94 | 95 | def quit(): 96 | global run 97 | run=0; 98 | 99 | namespace = 'http://soapinterop.org/' 100 | 101 | server = SOAPServer (("localhost", 12027)) 102 | 103 | server.registerKWFunction (dealHand, namespace) 104 | server.registerKWFunction (dealArrangedHand, namespace) 105 | server.registerKWFunction (dealCard, namespace) 106 | server.registerKWFunction (quit, namespace) 107 | 108 | try: 109 | while run: 110 | server.handle_request() 111 | except KeyboardInterrupt: 112 | pass 113 | -------------------------------------------------------------------------------- /tests/testClient1.py: -------------------------------------------------------------------------------- 1 | import gc 2 | import socket 3 | import threading 4 | import time 5 | import unittest 6 | import sys 7 | sys.path.insert(1, "..") 8 | 9 | import SOAPpy 10 | #SOAPpy.Config.debug=1 11 | 12 | # global to shut down server 13 | quit = 0 14 | 15 | def echoDateTime(dt): 16 | return dt 17 | 18 | def echo(s): 19 | """repeats a string twice""" 20 | return s + s 21 | 22 | def kill(): 23 | """tell the server to quit""" 24 | global quit 25 | quit = 1 26 | 27 | def server1(): 28 | """start a SOAP server on localhost:8000""" 29 | 30 | print "Starting SOAP Server...", 31 | server = SOAPpy.Server.SOAPServer(addr=('127.0.0.1', 8000)) 32 | server.registerFunction(echoDateTime) 33 | server.registerFunction(echo) 34 | server.registerFunction(kill) 35 | print "Done." 36 | 37 | global quit 38 | while not quit: 39 | server.handle_request() 40 | quit = 0 41 | print "Server shut down." 42 | 43 | class ClientTestCase(unittest.TestCase): 44 | 45 | server = None 46 | startup_timeout = 5 # seconds 47 | 48 | def setUp(self): 49 | '''This is run once before each unit test.''' 50 | 51 | serverthread = threading.Thread(target=server1, name="SOAPServer") 52 | serverthread.start() 53 | 54 | start = time.time() 55 | connected = False 56 | server = None 57 | while not connected and time.time() - start < self.startup_timeout: 58 | print "Trying to connect to the SOAP server...", 59 | try: 60 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 61 | server.echo('Hello World') 62 | except socket.error, e: 63 | print "Failure:", e 64 | time.sleep(0.5) 65 | else: 66 | connected = True 67 | self.server = server 68 | print "Success." 69 | 70 | if not connected: raise 'Server failed to start.' 71 | 72 | def tearDown(self): 73 | '''This is run once after each unit test.''' 74 | 75 | print "Trying to shut down SOAP server..." 76 | if self.server is not None: 77 | self.server.kill() 78 | time.sleep(5) 79 | 80 | return 1 81 | 82 | def testEcho(self): 83 | '''Test echo function.''' 84 | 85 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 86 | s = 'Hello World' 87 | self.assertEquals(server.echo(s), s+s) 88 | 89 | def testNamedEcho(self): 90 | '''Test echo function.''' 91 | 92 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 93 | s = 'Hello World' 94 | self.assertEquals(server.echo(s=s), s+s) 95 | 96 | def testEchoDateTime(self): 97 | '''Test passing DateTime objects.''' 98 | 99 | server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 100 | dt = SOAPpy.Types.dateTimeType(data=time.time()) 101 | dt_return = server.echoDateTime(dt) 102 | self.assertEquals(dt_return, dt) 103 | 104 | 105 | # def testNoLeak(self): 106 | # '''Test for memory leak.''' 107 | 108 | # gc.set_debug(gc.DEBUG_SAVEALL) 109 | # for i in range(400): 110 | # server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') 111 | # s = 'Hello World' 112 | # server.echo(s) 113 | # gc.collect() 114 | # self.assertEquals(len(gc.garbage), 0) 115 | 116 | 117 | if __name__ == '__main__': 118 | unittest.main() 119 | -------------------------------------------------------------------------------- /validate/server.pem: -------------------------------------------------------------------------------- 1 | $Id$ 2 | # Test certificate generated using CA.pl written by Steve Hensen 3 | # bundled with OpenSSL. 4 | # 5 | # Steps used to generate server.pem : 6 | # a)CA.pl -newca (creates a new CA heirarchy) 7 | # b)CA.pl -newreq (creates a new certificate request) 8 | # c)CA.pl -sign (sign the certificate request) 9 | # d)openssl rsa newkey.pem (unencrypt the private key) 10 | # e)Copy the certificate from newcert.pem, the unencrypted RSA 11 | # private key from newkey.pem and the certificate request from 12 | # newreq.pem and create server.pem to contain all three of them. 13 | -----BEGIN CERTIFICATE----- 14 | MIIDhjCCAu+gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCVVMx 15 | CzAJBgNVBAgTAkNBMQswCQYDVQQHEwJSQzEQMA4GA1UEChMHYWN0emVybzETMBEG 16 | A1UECxMKdGVjaG5vbG9neTEPMA0GA1UEAxMGc3lzYWRtMR8wHQYJKoZIhvcNAQkB 17 | FhBpbmZvQGFjdHplcm8uY29tMB4XDTAxMDUxNjIyMzkwM1oXDTAyMDUxNjIyMzkw 18 | M1owgYAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UEBxMCUkMxEDAO 19 | BgNVBAoTB2FjdHplcm8xEzARBgNVBAsTCnRlY2hub2xvZ3kxDzANBgNVBAMTBnN5 20 | c2FkbTEfMB0GCSqGSIb3DQEJARYQaW5mb0BhY3R6ZXJvLmNvbTCBnzANBgkqhkiG 21 | 9w0BAQEFAAOBjQAwgYkCgYEAyRBB6l+DI3aMNeYf7IuodvZ9nNxnfQHVnGyRtwhb 22 | 1g2tugTwFsE67oHA5qvwaDBILtsqkr9agXYDbZwJmV58xtBY675tibf7/1R8mcDO 23 | d4Dremdn0CMyk4+n6Z8GpLJ59TZ3y98DXUOqbLvzzltDz0si2XVa8G7f4K5k/xxB 24 | GZcCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5T 25 | U0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT/DGQzyXlwLXMWMaT4 26 | lp9O928tvzCBrQYDVR0jBIGlMIGigBSdjwZua1AI3XoUtwLyW0Optc/4O6GBhqSB 27 | gzCBgDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJSQzEQMA4G 28 | A1UEChMHYWN0emVybzETMBEGA1UECxMKdGVjaG5vbG9neTEPMA0GA1UEAxMGc3lz 29 | YWRtMR8wHQYJKoZIhvcNAQkBFhBpbmZvQGFjdHplcm8uY29tggEAMA0GCSqGSIb3 30 | DQEBBAUAA4GBABQodV+rrwMsvTEEza08EeS1Rf2ISuzh6e9VbfiJLVB5Xv1SeEt1 31 | sOv8ETZyN/4OXvZWQG/5md/5NNkf5K6CeKiwctztkyKTXdPIFS6FJVZdduWhiWPF 32 | 6gutQgOogtpCHTLwdSDk75n5MXFlnehORqOREMqqCJtFlHMEV1211Ssi 33 | -----END CERTIFICATE----- 34 | -----BEGIN RSA PRIVATE KEY----- 35 | MIICWwIBAAKBgQDJEEHqX4Mjdow15h/si6h29n2c3Gd9AdWcbJG3CFvWDa26BPAW 36 | wTrugcDmq/BoMEgu2yqSv1qBdgNtnAmZXnzG0Fjrvm2Jt/v/VHyZwM53gOt6Z2fQ 37 | IzKTj6fpnwaksnn1NnfL3wNdQ6psu/POW0PPSyLZdVrwbt/grmT/HEEZlwIDAQAB 38 | AoGALcho6gBjsRCObrt+63MFokkQY0aAviNLy7mhGIdrufsVYvU64kOPsr2S+jOO 39 | o3rTBPBc6ltuNWp072GHggfU61y4Bvfqxq2IRRDVH+yjmsdKSPYoBSIs3ZKjwJGx 40 | pFAT1nfNP05MfqUwZm8HbTnqqakrWm0p53Zvv6NP3vNjmzECQQD6EK5a7bD7VSVz 41 | MawUgUkZGZUtForbZL5nwIo1j94/TbnxUuuwej0MiCJ0MQsPCY/LML/gYaxTdQOg 42 | qYkGyIAPAkEAzdXbgTc81FflECxc5CXw9Yi1g0+nMkH5drlk+sct5dCzokPJZBQ3 43 | oxIaQcJP/rUMgG0A2mSpOnbAHNHX+z/F+QJAEQGbafGqTJ1wy5HAOzDDsOJNg+B5 44 | lwwV6uZsP9JF8hYuJBxYjQrzJewIM9C2CNLEpbPuCKt71b0qfv2opP5zvwJAMyjh 45 | WveAvgJuo5tzJx2rC0wEWXPVya8OMw0XZSFWbhV2YHFav+4qefSI5ClIurUDO3Rc 46 | TuvQCAD19PPPK9qI+QJADpbLUWw8NsMaHpJgeigXVIsRtJcroDw2r87bJxsgcgQz 47 | CsIH32VLvFOmpJdwnji6GX+vD2i0UH4ythnMCq4NUg== 48 | -----END RSA PRIVATE KEY----- 49 | -----BEGIN CERTIFICATE REQUEST----- 50 | MIIBwTCCASoCAQAwgYAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UE 51 | BxMCUkMxEDAOBgNVBAoTB2FjdHplcm8xEzARBgNVBAsTCnRlY2hub2xvZ3kxDzAN 52 | BgNVBAMTBnN5c2FkbTEfMB0GCSqGSIb3DQEJARYQaW5mb0BhY3R6ZXJvLmNvbTCB 53 | nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyRBB6l+DI3aMNeYf7IuodvZ9nNxn 54 | fQHVnGyRtwhb1g2tugTwFsE67oHA5qvwaDBILtsqkr9agXYDbZwJmV58xtBY675t 55 | ibf7/1R8mcDOd4Dremdn0CMyk4+n6Z8GpLJ59TZ3y98DXUOqbLvzzltDz0si2XVa 56 | 8G7f4K5k/xxBGZcCAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GBAIoUVScm4lAkfo1o 57 | n4b2Mpq3oV+dZnnTgYog4vmn/2UF0OSSTWlWPvINVkRtfg0iskZsbcWGn+RDY5e/ 58 | aTqN7Xz+BV5XlbQLZzuQdKPsfBcZ766El1chmUuO5tELpFtQkmlAgAXRMuh0Xeb+ 59 | A9wmVNyCMU6/+ajqwO642nSPOLM0 60 | -----END CERTIFICATE REQUEST----- 61 | -------------------------------------------------------------------------------- /bid/inventory.servers: -------------------------------------------------------------------------------- 1 | # This list of servers was taken from the SOAPBuilders Interoperability Lab 2 | # (http://www.xmethods.net/ilab/ilab.html) 4/23/01. 3 | # 4 | # $Id$ 5 | 6 | Name: MST Bid (Microsoft SOAP Toolkit 2.0, Microsoft Windows 2000) 7 | Endpoint: http://131.107.72.13/stk/Bid.wsdl 8 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 9 | Namespace: http://www.soapinterop.org/Bid 10 | 11 | Name: KeithBa's BidBuy Service (.NET Web Services) 12 | Endpoint: http://131.107.72.13/test/bidbuy/bidbuy.asmx 13 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 14 | Namespace: http://soapinterop.org/xsd 15 | 16 | Name: JHawk's BidBuyService (.NET Remoting, Win2K) 17 | Endpoint: http://131.107.72.13/DotNetRemotingNI/BidBuy.soap 18 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 19 | Namespace: http://www.soapinterop.org/Bid 20 | 21 | #Name: Idoox WASP 22 | #Endpoint: http://soap.idoox.net:8888/soap/servlet/Bid/ 23 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 24 | #Namespace: http://www.soapinterop.org/Bid 25 | 26 | Name: Paul's Quick Bid (SOAP::Lite) 27 | Endpoint: http://services.soaplite.com/tradeit.cgi 28 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 29 | Namespace: http://www.soapinterop.org/Bid 30 | 31 | Name: Phalanx Bid Service 32 | Endpoint: http://www.phalanxsys.com/ni/listener.asp 33 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 34 | Namespace: http://www.soapinterop.org/Bid 35 | Nonfunctional: Buy admitted problem with the wsdl 36 | 37 | Name: PranishK's BidBuy Service (ATL Web Service) 38 | Endpoint: http://www.mssoapinterop.org/atls_soap/bidbuy.dll?Handler=Default 39 | SOAPAction: "#%(methodname)s" 40 | Namespace: http://www.soapinterop.org/Bid 41 | 42 | Name: GLUE Bid 43 | Endpoint: http://209.61.190.164:8004/glue/http://www.soapinterop.org/Bid 44 | SOAPAction: "http://www.soapinterop.org/Bid#(methodname)s" 45 | Namespace: http://www.soapinterop.org/Bid 46 | 47 | Name: Aumsoft's BidBuy 48 | Endpoint: http://soap.aumsoft.com:8080/soap/BidBuy 49 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 50 | Namespace: http://www.soapinterop.org/Bid 51 | 52 | Name: SOAP.py 0.9 (actzero.com) 53 | Endpoint: http://208.177.157.221:12080/xmethodsInterop 54 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 55 | Namespace: http://www.soapinterop.org/Bid 56 | 57 | Name: HP SOAP 58 | Endpoint: http://soap.bluestone.com/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/BidBuy 59 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 60 | Namespace: http://www.soapinterop.org/Bid 61 | 62 | Name: EasySoap++ Bid Service (San Diego) 63 | Endpoint: http://easysoap.no-ip.com:8080/cgi-bin/bidbuyservice 64 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 65 | Namespace: http://www.soapinterop.org/Bid 66 | 67 | Name: Jake's Frontier 7.0b43 Bid Service (Santa Clara, CA) 68 | Endpoint: http://www.soapware.org/BidBuy 69 | SOAPAction: "http://www.soapinterop.org/%(methodname)s" 70 | Namespace: http://www.soapinterop.org/Bid 71 | 72 | #Name: Pete's Clear Bids (CapeConnect/Win2000) 73 | #Endpoint: http://208.46.17.81/ccx/SOAPServlet 74 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 75 | #Namespace: http://www.soapinterop.org/Bid 76 | 77 | #Name: (PranishK's) ATL Server BidBuy 78 | #Endpoint: http://208.46.17.121/bidbuy/bidbuy.dll?Handler=Default 79 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 80 | #Namespace: http://www.soapinterop.org/Bid 81 | 82 | #Name: HP-SOAP @ N+I 83 | #Endpoint: http://208.46.17.112/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/BidBuy 84 | #SOAPAction: "http://www.soapinterop.org/%(methodname)s" 85 | #Namespace: http://www.soapinterop.org/Bid 86 | 87 | -------------------------------------------------------------------------------- /validate/soapware.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This server validates as of 4/23/01 when run with UserLand's SOAP validator 4 | # (http://validator.soapware.org/). 5 | 6 | import getopt 7 | import sys 8 | 9 | sys.path.insert (1, '..') 10 | 11 | from SOAPpy import SOAP 12 | 13 | ident = '$Id$' 14 | 15 | def whichToolkit (): 16 | return SOAP.SOAPUserAgent () 17 | 18 | def countTheEntities (s): 19 | counts = {'ctLeftAngleBrackets': 0, 'ctRightAngleBrackets': 0, 20 | 'ctAmpersands': 0, 'ctApostrophes': 0, 'ctQuotes': 0} 21 | 22 | for i in s: 23 | if i == '<': 24 | counts['ctLeftAngleBrackets'] += 1 25 | elif i == '>': 26 | counts['ctRightAngleBrackets'] += 1 27 | elif i == '&': 28 | counts['ctAmpersands'] += 1 29 | elif i == "'": 30 | counts['ctApostrophes'] += 1 31 | elif i == '"': 32 | counts['ctQuotes'] += 1 33 | 34 | return counts 35 | 36 | def easyStructTest (stooges): 37 | return stooges['larry'] + stooges['moe'] + stooges['curly'] 38 | 39 | def echoStructTest (myStruct): 40 | return myStruct 41 | 42 | def manyTypesTest (num, bool, state, doub, dat, bin): 43 | return [num, SOAP.booleanType (bool), state, doub, 44 | SOAP.dateTimeType (dat), bin] 45 | 46 | def moderateSizeArrayCheck (myArray): 47 | return myArray[0] + myArray[-1] 48 | 49 | def nestedStructTest (myStruct): 50 | return easyStructTest (myStruct.year2000.month04.day01) 51 | 52 | def simpleStructReturnTest (myNumber): 53 | return {'times10': myNumber * 10, 'times100': myNumber * 100, 54 | 'times1000': myNumber * 1000} 55 | 56 | namespace = 'http://www.soapware.org/' 57 | 58 | DEFAULT_HOST = 'localhost' 59 | DEFAULT_PORT = 8080 60 | 61 | def usage (error = None): 62 | sys.stdout = sys.stderr 63 | 64 | if error != None: 65 | print error 66 | 67 | print """usage: %s [options] 68 | If a long option shows an argument is mandatory, it's mandatory for the 69 | equivalent short option also. The default (if any) is shown in brackets. 70 | 71 | -?, --help display this usage 72 | -h, --host=HOST use HOST in the address to listen on [%s] 73 | -p, --port=PORT listen on PORT [%d] 74 | """ % (sys.argv[0], DEFAULT_HOST, DEFAULT_PORT), 75 | 76 | sys.exit (0) 77 | 78 | def main (): 79 | host = DEFAULT_HOST 80 | port = DEFAULT_PORT 81 | 82 | try: 83 | opts, args = getopt.getopt (sys.argv[1:], '?h:p:', 84 | ['help', 'host', 'port']) 85 | 86 | for opt, arg in opts: 87 | if opt in ('-?', '--help'): 88 | usage () 89 | elif opt in ('-h', '--host'): 90 | host = arg 91 | elif opt in ('-p', '--port'): 92 | port = int (arg) 93 | else: 94 | raise AttributeError, \ 95 | "Recognized but unimplemented option `%s'" % opt 96 | except SystemExit: 97 | raise 98 | except: 99 | usage (sys.exc_info ()[1]) 100 | 101 | server = SOAP.SOAPServer ((host, port)) 102 | 103 | server.registerFunction (whichToolkit, namespace) 104 | server.registerFunction (countTheEntities) 105 | server.registerFunction (easyStructTest) 106 | server.registerFunction (echoStructTest) 107 | server.registerFunction (manyTypesTest) 108 | server.registerFunction (moderateSizeArrayCheck) 109 | server.registerFunction (nestedStructTest) 110 | server.registerFunction (simpleStructReturnTest) 111 | 112 | server.serve_forever() 113 | 114 | if __name__ == '__main__': 115 | try: 116 | sys.exit (main ()) 117 | except KeyboardInterrupt: 118 | sys.exit (0) 119 | -------------------------------------------------------------------------------- /docs/MethodParameterNaming.txt: -------------------------------------------------------------------------------- 1 | 2 | Experimental method for handing ordered vs named method parameters 3 | ------------------------------------------------------------------ 4 | 5 | There is an incompatibility with the way that Python and SOAP handle 6 | method arguments: SOAP requires that all arguments have names and that 7 | they are presented in the same order as the method signature. Python 8 | (like other scripting languages, notably the S language) has the 9 | concept of unnamed arguments. Further Python does not preserve the 10 | order of named arguments, since they are handled using the dictionary 11 | data type. It seems to me that this makes it impossible to fully meet 12 | the SOAP specification without significant modifications to the Python 13 | method of handling named arguments or to the Python dictionary class. 14 | 15 | Historically SOAPpy has attempted to work around this issue by 16 | handling all arguments as unnamed unless the method or function was 17 | explicitly flagged, in which case all arguments were considered named. 18 | This has resulted in a several problems, particularly for a SOAPpy 19 | client communicating with a SOAPpy server. First, when named 20 | arguments were used in call to a non-flagged function, the argument 21 | would silently be reordered by the sender (since they were stored 22 | using a Python dictionary), *and* the names would be ignored by the 23 | receiver, which assumed that the parameters were unnamed and only the 24 | order was significant. This results in incorrect argument matching. 25 | This problem also occurred with mixed named and unnamed arguments. 26 | 27 | For my primary SOAP application, it is not reasonable to flag all of 28 | the SOAPpy methods as requiring named arguments, for a variety of 29 | reasons. One reason is that the available methods are not known 30 | apriori by the client software, hence the names of the arguments are 31 | not known. Second, many of the methods provide a large number of 32 | optional arguments, making it impractical to specify them all. 33 | 34 | In an attempt to overcome this problem, I implemented an experimental 35 | and non-standard method of handling named and unnamed arguments. This 36 | mechanism is enabled in SOAPpy by setting 37 | SOAPpy.SOAP.Config.specialArgs=1, and disabled by setting 38 | SOAPpy.SOAP.Config.specialArgs=0. 39 | 40 | When enabled, parameters with names of the form v#### (i.e., matching 41 | the regexp "^v[0-9]+$") are assumed to be unnamed parameters and are 42 | passed to the method in numeric order. All other parameters are 43 | assumed to be named and are passed using the name. Outgoing SOAP 44 | method calls now always generate names in this way--whether or not 45 | specialArgs is enabled. 46 | 47 | 48 | I selected the form v#### because it is a valid XML name, but is 49 | unlikely to be used as a parameter name. 50 | 51 | [As it turns out, this choice was fortitous because Apache's SOAP tool 52 | uses the same system.] 53 | 54 | In my testing, this mechanism for handling method parameter names 55 | works fine between a SOAPpy client and a SOAPpy server, and resolves 56 | the parameter reordering problems I was experiencing. This system 57 | seems unlikely to have any negative side effects on other SOAP 58 | applications, except in the (hopefully) rare case when v#### might be 59 | used as an actual parameter name. 60 | 61 | **In version 0.9.9-pre1, this feature is enabled by default.** Please 62 | let me know if there are situations where this causes problems. 63 | 64 | Note that this mechanism is only a partial solution, since it is still 65 | impossible to return named parameters in a specified order using 66 | SOAPpy. SOAP applications or implementations which require this 67 | feature are simply not compatible with SOAPpy. 68 | 69 | -Greg Warnes 70 | 2003-03-07 (updated 2003-11-14) 71 | 72 | -------------------------------------------------------------------------------- /SOAPpy/wstools/MIMEAttachment.py: -------------------------------------------------------------------------------- 1 | #TODO add the license 2 | #I had to rewrite this class because the python MIME email.mime (version 2.5) 3 | #are buggy, they use \n instead \r\n for new line which is not compliant 4 | #to standard! 5 | # http://bugs.python.org/issue5525 6 | 7 | #TODO do not load all the message in memory stream it from the disk 8 | 9 | import re 10 | import random 11 | import sys 12 | 13 | 14 | #new line 15 | NL='\r\n' 16 | 17 | _width = len(repr(sys.maxint-1)) 18 | _fmt = '%%0%dd' % _width 19 | 20 | class MIMEMessage: 21 | 22 | def __init__(self): 23 | self._files = [] 24 | self._xmlMessage = "" 25 | self._startCID = "" 26 | self._boundary = "" 27 | 28 | def makeBoundary(self): 29 | #create the boundary 30 | msgparts = [] 31 | msgparts.append(self._xmlMessage) 32 | for i in self._files: 33 | msgparts.append(i.read()) 34 | #this sucks, all in memory 35 | alltext = NL.join(msgparts) 36 | self._boundary = _make_boundary(alltext) 37 | #maybe I can save some memory 38 | del alltext 39 | del msgparts 40 | self._startCID = "<" + (_fmt % random.randrange(sys.maxint)) + (_fmt % random.randrange(sys.maxint)) + ">" 41 | 42 | 43 | def toString(self): 44 | '''it return a string with the MIME message''' 45 | if len(self._boundary) == 0: 46 | #the makeBoundary hasn't been called yet 47 | self.makeBoundary() 48 | #ok we have everything let's start to spit the message out 49 | #first the XML 50 | returnstr = NL + "--" + self._boundary + NL 51 | returnstr += "Content-Type: text/xml; charset=\"us-ascii\"" + NL 52 | returnstr += "Content-Transfer-Encoding: 7bit" + NL 53 | returnstr += "Content-Id: " + self._startCID + NL + NL 54 | returnstr += self._xmlMessage + NL 55 | #then the files 56 | for file in self._files: 57 | returnstr += "--" + self._boundary + NL 58 | returnstr += "Content-Type: application/octet-stream" + NL 59 | returnstr += "Content-Transfer-Encoding: binary" + NL 60 | returnstr += "Content-Id: <" + str(id(file)) + ">" + NL + NL 61 | file.seek(0) 62 | returnstr += file.read() + NL 63 | #closing boundary 64 | returnstr += "--" + self._boundary + "--" + NL 65 | return returnstr 66 | 67 | def attachFile(self, file): 68 | ''' 69 | it adds a file to this attachment 70 | ''' 71 | self._files.append(file) 72 | 73 | def addXMLMessage(self, xmlMessage): 74 | ''' 75 | it adds the XML message. we can have only one XML SOAP message 76 | ''' 77 | self._xmlMessage = xmlMessage 78 | 79 | def getBoundary(self): 80 | ''' 81 | this function returns the string used in the mime message as a 82 | boundary. First the write method as to be called 83 | ''' 84 | return self._boundary 85 | 86 | def getStartCID(self): 87 | ''' 88 | This function returns the CID of the XML message 89 | ''' 90 | return self._startCID 91 | 92 | 93 | def _make_boundary(text=None): 94 | #some code taken from python stdlib 95 | # Craft a random boundary. If text is given, ensure that the chosen 96 | # boundary doesn't appear in the text. 97 | token = random.randrange(sys.maxint) 98 | boundary = ('=' * 10) + (_fmt % token) + '==' 99 | if text is None: 100 | return boundary 101 | b = boundary 102 | counter = 0 103 | while True: 104 | cre = re.compile('^--' + re.escape(b) + '(--)?$', re.MULTILINE) 105 | if not cre.search(text): 106 | break 107 | b = boundary + '.' + str(counter) 108 | counter += 1 109 | return b 110 | 111 | -------------------------------------------------------------------------------- /SOAPpy/NS.py: -------------------------------------------------------------------------------- 1 | from __future__ import nested_scopes 2 | 3 | """ 4 | ################################################################################ 5 | # 6 | # SOAPpy - Cayce Ullman (cayce@actzero.com) 7 | # Brian Matthews (blm@actzero.com) 8 | # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) 9 | # Christopher Blunck (blunck@gst.com) 10 | # 11 | ################################################################################ 12 | # Copyright (c) 2003, Pfizer 13 | # Copyright (c) 2001, Cayce Ullman. 14 | # Copyright (c) 2001, Brian Matthews. 15 | # 16 | # All rights reserved. 17 | # 18 | # Redistribution and use in source and binary forms, with or without 19 | # modification, are permitted provided that the following conditions are met: 20 | # Redistributions of source code must retain the above copyright notice, this 21 | # list of conditions and the following disclaimer. 22 | # 23 | # Redistributions in binary form must reproduce the above copyright notice, 24 | # this list of conditions and the following disclaimer in the documentation 25 | # and/or other materials provided with the distribution. 26 | # 27 | # Neither the name of actzero, inc. nor the names of its contributors may 28 | # be used to endorse or promote products derived from this software without 29 | # specific prior written permission. 30 | # 31 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 35 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 36 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 38 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | # 42 | ################################################################################ 43 | """ 44 | 45 | ident = '$Id$' 46 | from version import __version__ 47 | 48 | ############################################################################## 49 | # Namespace Class 50 | ################################################################################ 51 | def invertDict(dict): 52 | d = {} 53 | 54 | for k, v in dict.items(): 55 | d[v] = k 56 | 57 | return d 58 | 59 | class NS: 60 | XML = "http://www.w3.org/XML/1998/namespace" 61 | 62 | ENV = "http://schemas.xmlsoap.org/soap/envelope/" 63 | ENC = "http://schemas.xmlsoap.org/soap/encoding/" 64 | 65 | XSD = "http://www.w3.org/1999/XMLSchema" 66 | XSD2 = "http://www.w3.org/2000/10/XMLSchema" 67 | XSD3 = "http://www.w3.org/2001/XMLSchema" 68 | 69 | XSD_L = [XSD, XSD2, XSD3] 70 | EXSD_L= [ENC, XSD, XSD2, XSD3] 71 | 72 | XSI = "http://www.w3.org/1999/XMLSchema-instance" 73 | XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance" 74 | XSI3 = "http://www.w3.org/2001/XMLSchema-instance" 75 | XSI_L = [XSI, XSI2, XSI3] 76 | 77 | URN = "http://soapinterop.org/xsd" 78 | 79 | # For generated messages 80 | XML_T = "xml" 81 | ENV_T = "SOAP-ENV" 82 | ENC_T = "SOAP-ENC" 83 | XSD_T = "xsd" 84 | XSD2_T= "xsd2" 85 | XSD3_T= "xsd3" 86 | XSI_T = "xsi" 87 | XSI2_T= "xsi2" 88 | XSI3_T= "xsi3" 89 | URN_T = "urn" 90 | 91 | NSMAP = {ENV_T: ENV, ENC_T: ENC, XSD_T: XSD, XSD2_T: XSD2, 92 | XSD3_T: XSD3, XSI_T: XSI, XSI2_T: XSI2, XSI3_T: XSI3, 93 | URN_T: URN} 94 | NSMAP_R = invertDict(NSMAP) 95 | 96 | STMAP = {'1999': (XSD_T, XSI_T), '2000': (XSD2_T, XSI2_T), 97 | '2001': (XSD3_T, XSI3_T)} 98 | STMAP_R = invertDict(STMAP) 99 | 100 | def __init__(self): 101 | raise Error, "Don't instantiate this" 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /validate/silabserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | # This is a server for the XMethods matrix 6 | # (http://jake.soapware.org/currentXmethodsResults). 7 | 8 | import getopt 9 | import sys 10 | 11 | sys.path.insert (1, '..') 12 | 13 | from SOAPpy import SOAP 14 | 15 | if SOAP.Config.SSLserver: 16 | from M2Crypto import SSL 17 | 18 | ident = '$Id$' 19 | 20 | def echoFloat (inputFloat): 21 | return inputFloat 22 | 23 | def echoFloatArray (inputFloatArray): 24 | return inputFloatArray 25 | 26 | def echoInteger (inputInteger): 27 | return inputInteger 28 | 29 | def echoIntegerArray (inputIntegerArray): 30 | return inputIntegerArray 31 | 32 | def echoString (inputString): 33 | return inputString 34 | 35 | def echoStringArray (inputStringArray): 36 | return inputStringArray 37 | 38 | def echoStruct (inputStruct): 39 | return inputStruct 40 | 41 | def echoStructArray (inputStructArray): 42 | return inputStructArray 43 | 44 | def echoVoid (): 45 | return SOAP.voidType() 46 | 47 | def echoDate (inputDate): 48 | return SOAP.dateTimeType (inputDate) 49 | 50 | def echoBase64 (inputBase64): 51 | return SOAP.binaryType (inputBase64) 52 | 53 | namespace = 'http://soapinterop.org/' 54 | 55 | DEFAULT_HOST = 'localhost' 56 | DEFAULT_HTTP_PORT = 8080 57 | DEFAULT_HTTPS_PORT = 8443 58 | 59 | def usage (error = None): 60 | sys.stdout = sys.stderr 61 | 62 | if error != None: 63 | print error 64 | 65 | print """usage: %s [options] 66 | If a long option shows an argument is mandatory, it's mandatory for the 67 | equivalent short option also. The default (if any) is shown in brackets. 68 | 69 | -?, --help display this usage 70 | -h, --host=HOST use HOST in the address to listen on [%s] 71 | -p, --port=PORT listen on PORT [%d] 72 | """ % (sys.argv[0], DEFAULT_HOST, DEFAULT_HTTP_PORT), 73 | 74 | if SOAP.Config.SSLserver: 75 | print " -s, --ssl serve using SSL" 76 | 77 | sys.exit (0) 78 | 79 | def main (): 80 | host = DEFAULT_HOST 81 | port = None 82 | ssl = 0 83 | 84 | try: 85 | opts = '?h:p:' 86 | args = ['help', 'host', 'port'] 87 | 88 | if SOAP.Config.SSLserver: 89 | opts += 's' 90 | args += ['ssl'] 91 | 92 | opts, args = getopt.getopt (sys.argv[1:], opts, args) 93 | 94 | for opt, arg in opts: 95 | if opt in ('-?', '--help'): 96 | usage () 97 | elif opt in ('-h', '--host'): 98 | host = arg 99 | elif opt in ('-p', '--port'): 100 | port = int (arg) 101 | elif opt in ('-s', '--ssl'): 102 | ssl = 1 103 | else: 104 | raise AttributeError, \ 105 | "Recognized but unimplemented option `%s'" % opt 106 | except SystemExit: 107 | raise 108 | except: 109 | usage (sys.exc_info ()[1]) 110 | 111 | if port == None: 112 | port = [DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT][ssl] 113 | 114 | if ssl: 115 | ssl_context = SSL.Context() 116 | ssl_context.load_cert('server.pem') 117 | else: 118 | ssl_context = None 119 | 120 | server = SOAP.SOAPServer ((host, port), namespace = namespace, 121 | ssl_context = ssl_context) 122 | 123 | server.registerFunction (echoFloat) 124 | server.registerFunction (echoFloatArray) 125 | server.registerFunction (echoInteger) 126 | server.registerFunction (echoIntegerArray) 127 | server.registerFunction (echoString) 128 | server.registerFunction (echoStringArray) 129 | server.registerFunction (echoStruct) 130 | server.registerFunction (echoStructArray) 131 | server.registerFunction (echoVoid) 132 | server.registerFunction (echoDate) 133 | server.registerFunction (echoBase64) 134 | 135 | server.serve_forever() 136 | 137 | if __name__ == '__main__': 138 | try: 139 | sys.exit (main ()) 140 | except KeyboardInterrupt: 141 | sys.exit (0) 142 | -------------------------------------------------------------------------------- /docs/GlobusSupport.txt: -------------------------------------------------------------------------------- 1 | 2 | Globus Support 3 | ============== 4 | 5 | Extensions have been added to the SOAPpy module to allow the use of the 6 | Globus Toolkit v2 for secure transport of SOAP calls. These extensions are 7 | possible by using the Globus Toolkit (http://www.globus.org) and the 8 | pyGlobus software (http://www-itg.lbl.gov/gtg/projects/pyGlobus/), which 9 | exposes the Globus Toolkit via a set of Python interfaces. This enables 10 | bi-directional PKI authentication so that the server and client are both 11 | guaranteed of the identity of the other. Using PKI this way also allows a 12 | more robust authorization solution above the SOAP hosting layer, which 13 | provides better application level authorization control. These tools are 14 | used by the Access Grid Project (http://www.accessgrid.org) to build a 15 | Grid-based, Web Services based, real-time collaboration environment. 16 | 17 | In order to use the SOAPpy module with the Globus Toolkit, you must first 18 | obtain and install the Globus Toolkit and pyGlobus software. Information on 19 | how to do that is at the respective web sites listed below. In order to use 20 | the Globus Toolkit it is necessary to have an x509 identity certificate. 21 | Information on how to obtain one of those is available on the web as well. 22 | 23 | To use GSI with an authorization method, set the SOAPConfig.authMethod = 24 | "methodname". You must have this method defined on any objects you register 25 | with SOAPpy, and/or as a registered method. It should return 0 or 1 to 26 | indicate if authorization is allowed or not. 27 | 28 | Once the software is installed, you have obtained your certificate, and the 29 | SOAPpy module is installed, the following code shows how to run a GSI 30 | secured SOAP server (These snippets are directly from the echoServer.py and 31 | echoClient.py in the test directory). 32 | 33 | Server 34 | ------ 35 | 36 | def _authorize(self, *args, **kw): 37 | return 1 38 | 39 | Config.authMethod = "_authorize" 40 | 41 | addr = ('localhost', 9900) 42 | from SOAPpy.GSIServer import GSISOAPServer 43 | server = GSISOAPServer(addr) 44 | 45 | server.registerFunction(_authorize) 46 | server.registerFunction(echo) 47 | 48 | Then you use the server like the SSL server or the standard server. 49 | 50 | Client 51 | ------ 52 | 53 | import pyGlobus 54 | 55 | # The httpg distinguishes this as a GSI TCP connection, so after 56 | # this you can use the SOAP proxy as you would any other SOAP Proxy. 57 | 58 | server = SOAPProxy("httpg://localhost:9900/") 59 | print server.echo("moo") 60 | 61 | 62 | 63 | Globus Toolkit http://www.globus.org 64 | ------------------------------------ 65 | 66 | The Globus Toolkit is an open source software toolkit used for 67 | building grids. It is being developed by the Globus Alliance and 68 | many others all over the world. A growing number of projects and 69 | companies are using the Globus Toolkit to unlock the potential 70 | of grids for their cause. 71 | 72 | PyGlobus http://www-itg.lbl.gov/gtg/projects/pyGlobus/ 73 | ------------------------------------------------------ 74 | 75 | The goal of this project is to allow the use of the entire 76 | Globus toolkit from Python, a high-level scripting 77 | language. SWIG is used to generate the necessary interface 78 | code. Currently a substantial subset of the 2.2.4 and 2.4 79 | versions of the Globus toolkit has been wrapped. 80 | 81 | The Access Grid http://www.accessgrid.org/ 82 | ------------------------------------------ 83 | 84 | The Access GridT is an ensemble of resources including 85 | multimedia large-format displays, presentation and interactive 86 | environments, and interfaces to Grid middleware and to 87 | visualization environments. These resources are used to support 88 | group-to-group interactions across the Grid. For example, the 89 | Access Grid (AG) is used for large-scale distributed meetings, 90 | collaborative work sessions, seminars, lectures, tutorials, and 91 | training. The Access Grid thus differs from desktop-to-desktop 92 | tools that focus on individual communication. 93 | 94 | - Submitted 2004-01-08 by Ivan R. Judson 95 | 96 | 97 | $Id$ 98 | -------------------------------------------------------------------------------- /SOAPpy/wstools/UserTuple.py: -------------------------------------------------------------------------------- 1 | """ 2 | A more or less complete user-defined wrapper around tuple objects. 3 | Adapted version of the standard library's UserList. 4 | 5 | Taken from Stefan Schwarzer's ftputil library, available at 6 | , and used under this license: 7 | 8 | 9 | 10 | 11 | Copyright (C) 1999, Stefan Schwarzer 12 | All rights reserved. 13 | 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are 16 | met: 17 | 18 | - Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | 21 | - Redistributions in binary form must reproduce the above copyright 22 | notice, this list of conditions and the following disclaimer in the 23 | documentation and/or other materials provided with the distribution. 24 | 25 | - Neither the name of the above author nor the names of the 26 | contributors to the software may be used to endorse or promote 27 | products derived from this software without specific prior written 28 | permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 31 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 33 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 34 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 35 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 36 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 37 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 38 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 39 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 40 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41 | 42 | """ 43 | 44 | 45 | 46 | 47 | # $Id$ 48 | 49 | #XXX tuple instances (in Python 2.2) contain also: 50 | # __class__, __delattr__, __getattribute__, __hash__, __new__, 51 | # __reduce__, __setattr__, __str__ 52 | # What about these? 53 | 54 | class UserTuple: 55 | def __init__(self, inittuple=None): 56 | self.data = () 57 | if inittuple is not None: 58 | # XXX should this accept an arbitrary sequence? 59 | if type(inittuple) == type(self.data): 60 | self.data = inittuple 61 | elif isinstance(inittuple, UserTuple): 62 | # this results in 63 | # self.data is inittuple.data 64 | # but that's ok for tuples because they are 65 | # immutable. (Builtin tuples behave the same.) 66 | self.data = inittuple.data[:] 67 | else: 68 | # the same applies here; (t is tuple(t)) == 1 69 | self.data = tuple(inittuple) 70 | def __repr__(self): return repr(self.data) 71 | def __lt__(self, other): return self.data < self.__cast(other) 72 | def __le__(self, other): return self.data <= self.__cast(other) 73 | def __eq__(self, other): return self.data == self.__cast(other) 74 | def __ne__(self, other): return self.data != self.__cast(other) 75 | def __gt__(self, other): return self.data > self.__cast(other) 76 | def __ge__(self, other): return self.data >= self.__cast(other) 77 | def __cast(self, other): 78 | if isinstance(other, UserTuple): return other.data 79 | else: return other 80 | def __cmp__(self, other): 81 | return cmp(self.data, self.__cast(other)) 82 | def __contains__(self, item): return item in self.data 83 | def __len__(self): return len(self.data) 84 | def __getitem__(self, i): return self.data[i] 85 | def __getslice__(self, i, j): 86 | i = max(i, 0); j = max(j, 0) 87 | return self.__class__(self.data[i:j]) 88 | def __add__(self, other): 89 | if isinstance(other, UserTuple): 90 | return self.__class__(self.data + other.data) 91 | elif isinstance(other, type(self.data)): 92 | return self.__class__(self.data + other) 93 | else: 94 | return self.__class__(self.data + tuple(other)) 95 | # dir( () ) contains no __radd__ (at least in Python 2.2) 96 | def __mul__(self, n): 97 | return self.__class__(self.data*n) 98 | __rmul__ = __mul__ 99 | 100 | -------------------------------------------------------------------------------- /tests/storageTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ident = '$Id$' 4 | 5 | import sys, os, time, signal, re 6 | sys.path.insert(1, "..") 7 | from SOAPpy import SOAPProxy, SOAPConfig, SOAPUserAgent 8 | 9 | # Check for a web proxy definition in environment 10 | try: 11 | proxy_url=os.environ['http_proxy'] 12 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 13 | http_proxy = "%s:%s" % (phost, pport) 14 | except: 15 | http_proxy = None 16 | 17 | 18 | PROXY="http://www.soapware.org/xmlStorageSystem" 19 | EMAIL="SOAPpy@actzero.com" 20 | NAME="test_user" 21 | PASSWORD="mypasswd" 22 | SERIAL=1123214 23 | 24 | MY_PORT=15600 25 | 26 | def resourceChanged (url): 27 | print "\n##### NOTIFICATION MESSAGE: Resource %s has changed #####\n" % url 28 | return booleanType(1) 29 | 30 | def printstatus (cmd, stat): 31 | print 32 | if stat.flError: 33 | print "### %s failed: %s ###" % (cmd, stat.message) 34 | else: 35 | print "### %s successful: %s ###" % (cmd, stat.message) 36 | return not stat.flError 37 | 38 | server = SOAPProxy(encoding="US-ASCII", 39 | proxy=PROXY, 40 | soapaction="/xmlStorageSystem", 41 | http_proxy=http_proxy, 42 | # config=SOAPConfig(debug=1) 43 | ) 44 | 45 | # Register as a new user or update user information 46 | reg = server.registerUser(email=EMAIL, name=NAME, password=PASSWORD, 47 | clientPort=MY_PORT, userAgent=SOAPUserAgent(), 48 | serialnumber=SERIAL) 49 | printstatus("registerUser", reg) 50 | 51 | # See what this server can do 52 | reg = server.getServerCapabilities (email=EMAIL, password=PASSWORD) 53 | if printstatus("getServerCapabilities", reg): 54 | print "Legal file extensions: " + str(reg.legalFileExtensions) 55 | print "Maximum file size: " + str(reg.maxFileSize) 56 | print "Maximum bytes per user: " + str(reg.maxBytesPerUser) 57 | print "Number of bytes in use by the indicated user: " + str(reg.ctBytesInUse) 58 | print "URL of the folder containing your files: " + str(reg.yourUpstreamFolderUrl) 59 | 60 | # Store some files 61 | reg = server.saveMultipleFiles (email=EMAIL, password=PASSWORD, 62 | relativepathList=['index.html','again.html'], 63 | fileTextList=['bennett@actzero.com home page' + 64 | 'Hello Earth', 65 | 'bennett@actzero.com home page' + 66 | 'Hello Earth Again']) 67 | if printstatus("saveMultipleFiles", reg): 68 | print "Files stored:" 69 | for file in reg.urlList: 70 | print " %s" % file 71 | 72 | # Save this for call to test pleaseNotify 73 | mylist = reg.urlList 74 | else: 75 | mylist = [] 76 | 77 | # Check to see what files are stored 78 | reg = server.getMyDirectory (email=EMAIL, password=PASSWORD) 79 | if printstatus("getMyDirectory", reg): 80 | i = 1 81 | while hasattr(reg.directory, "file%05d" % i): 82 | d = getattr(reg.directory, "file%05d" % i) 83 | print "Relative Path: %s" % d.relativePath 84 | print "Size: %d" % d.size 85 | print "Created: %s" % d.whenCreated 86 | print "Last Uploaded: %s" % d.whenLastUploaded 87 | print "URL: %s" % d.url 88 | print 89 | i += 1 90 | 91 | # Set up notification 92 | reg = server.pleaseNotify(notifyProcedure="resourceChanged", port=MY_PORT, path="/", protocol="soap", urlList=mylist) 93 | printstatus("notifyProcedure", reg) 94 | 95 | pid = os.fork() 96 | if pid == 0: 97 | # I am a child process. Set up SOAP server to receive notification 98 | print 99 | print "## Starting notification server ##" 100 | 101 | s = SOAPServer(('localhost', MY_PORT)) 102 | s.registerFunction(resourceChanged) 103 | s.serve_forever() 104 | 105 | else: 106 | 107 | def handler(signum, frame): 108 | # Kill child process 109 | print "Killing child process %d" % pid 110 | os.kill(pid, signal.SIGINT) 111 | 112 | signal.signal(signal.SIGINT, handler) 113 | 114 | # I am a parent process 115 | # Change some files 116 | time.sleep(3) 117 | reg = server.saveMultipleFiles (email=EMAIL, password=PASSWORD, 118 | relativepathList=['index.html'], 119 | fileTextList=['bennett@actzero.com home page' + 120 | 'Hello Bennett']) 121 | if printstatus("saveMultipleFiles", reg): 122 | print "Files stored:" 123 | for file in reg.urlList: 124 | print " %s" % file 125 | 126 | os.waitpid(pid, 0) 127 | -------------------------------------------------------------------------------- /tests/TCtest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import sys, unittest 4 | sys.path.insert(1, "..") 5 | from SOAPpy import * 6 | Config.debug=1 7 | 8 | class ClientTestCase(unittest.TestCase): 9 | def testParseRules(self): 10 | x = """ 11 | 15 | 17 | 18 | 19 | 20 | My Life and Work 21 | 22 | 23 | Henry Ford 24 | 49 25 | 5.5 26 | 27 | 28 | 29 | 30 | 31 | """ 32 | 33 | def negfloat(x): 34 | return float(x) * -1.0 35 | 36 | # parse rules 37 | pr = {'SomeMethod': 38 | {'Result': 39 | { 40 | 'Book': {'title':'string'}, 41 | 'Person': {'age':'int', 42 | 'height':negfloat} 43 | } 44 | } 45 | } 46 | y = parseSOAPRPC(x, rules=pr) 47 | 48 | assert y.Result.Person.age == 49 49 | assert y.Result.Person.height == -5.5 50 | 51 | 52 | x = ''' 58 | 59 | 60 | 61 | 12 62 | 23 63 | 0 64 | -31 65 | 66 | 67 | 68 | 69 | 70 | ''' 71 | 72 | 73 | # parse rules 74 | pr = {'Bounds': 75 | {'param': 'arrayType=string[]', 76 | } 77 | } 78 | 79 | pr2 = {'Bounds': 80 | {'param': 'arrayType=int[4]', 81 | } 82 | } 83 | 84 | y = parseSOAPRPC(x, rules=pr) 85 | assert y.param[1]=='23' 86 | 87 | y = parseSOAPRPC(x, rules=pr2) 88 | assert y.param[1]==23 89 | 90 | x = ''' 96 | 97 | 98 | 99 | 100 | 12 101 | 23 102 | 0 103 | -31 104 | 105 | 106 | 107 | 108 | 109 | ''' 110 | 111 | pr = {'Bounds': 112 | {'param': 'arrayType=ur-type[]' 113 | } 114 | } 115 | y = parseSOAPRPC(x, rules=pr) 116 | assert y.param[0]==12 117 | assert y.param[1]=='23' 118 | assert y.param[2]==float(0) 119 | assert y.param[3]==-31 120 | 121 | # Try the reverse, not implemented yet. 122 | 123 | def testBuildObject(self): 124 | 125 | class Book(structType): 126 | def __init__(self): 127 | self.title = "Title of a book" 128 | 129 | class Person(structType): 130 | def __init__(self): 131 | self.age = "49" 132 | self.height = "5.5" 133 | 134 | class Library(structType): 135 | def __init__(self): 136 | self._name = "Result" 137 | self.Book = Book() 138 | self.Person = Person() 139 | 140 | obj = Library() 141 | 142 | x = buildSOAP( kw={'Library':obj} ) 143 | 144 | print(x) 145 | 146 | if __name__ == '__main__': 147 | unittest.main() 148 | -------------------------------------------------------------------------------- /bid/inventoryServer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2001, actzero, inc. 3 | import sys 4 | sys.path.insert(1,"..") 5 | from SOAPpy import SOAP 6 | #SOAP.Config.debug = 1 7 | serverstring = "SOAP.py (actzero.com) running "+sys.platform 8 | NUMBUYS = 0 9 | NUMSIMPLEBUYS = 0 10 | NUMREQUESTS = 0 11 | NUMPINGS = 0 12 | 13 | def SimpleBuy(Address, ProductName, Quantity): 14 | # currently, this type-checks the params, and makes sure 15 | # the strings are of len > 0 16 | global NUMSIMPLEBUYS 17 | NUMSIMPLEBUYS += 1 18 | if Quantity < 1: raise ValueError, "must order at least one" 19 | else: return "Receipt for %d %s(s) bought from %s" % (int(Quantity), ProductName, serverstring) 20 | 21 | 22 | def RequestForQuote(ProductName, Quantity): 23 | # type-checks and makes sure Quantity >= 1 24 | global NUMREQUESTS 25 | NUMREQUESTS += 1 26 | if Quantity < 1: raise ValueError, "must order at least 1" 27 | else: 28 | import whrandom 29 | mult = whrandom.random() 30 | times = 0 31 | while mult > 0.25: 32 | mult = mult - 0.25 33 | times += 1 34 | mult += 0.5 35 | mult = round(mult, 3) 36 | print mult, times 37 | return SOAP.doubleType(round(mult*int(Quantity),2)) 38 | 39 | 40 | def Buy(**kw): 41 | 42 | global NUMBUYS 43 | NUMBUYS += 1 44 | try: 45 | PurchaseOrder = kw["PurchaseOrder"] 46 | except: 47 | PurchaseOrder = kw["PO"] 48 | try: 49 | POkeys = PurchaseOrder['_keyord'] 50 | POkeys.sort() 51 | POkeys_expected = ["shipTo","billTo","items","poID","createDate"] 52 | POkeys_expected.sort() 53 | if POkeys != POkeys_expected: 54 | raise ValueError, "struct 'PurchaseOrder' needs %s, %s, %s, %s, and %s" % tuple(POkeys_expected) 55 | except: 56 | raise TypeError, "'PurchaseOrder' missing one or more element(s)" 57 | 58 | try: 59 | btkeys = PurchaseOrder["billTo"]["_keyord"] 60 | btkeys.sort() 61 | btkeys_expected = ["address","zipCode","name","state","city"] 62 | btkeys_expected.sort() 63 | except: 64 | raise TypeError, "'billTo' missing one or more elements" 65 | 66 | try: 67 | stkeys = PurchaseOrder["shipTo"]["_keyord"] 68 | stkeys.sort() 69 | stkeys_expected = ["address","zipCode","name","state","city"] 70 | stkeys_expected.sort() 71 | except: 72 | raise TypeError, "'shipTo' missing one or more elements" 73 | 74 | 75 | try: 76 | items = PurchaseOrder["items"].__dict__ 77 | data = items["data"] 78 | retstring = "" 79 | for item in data: 80 | itemdict = item["_asdict"] 81 | q = itemdict["quantity"] 82 | p = itemdict["price"] 83 | name = itemdict["name"] 84 | if retstring != "": 85 | retstring += ", " 86 | else: 87 | retstring = "bought " 88 | retstring += "%d %s(s) for %.2f" % (q,name,p) 89 | retstring += " from "+serverstring 90 | return retstring 91 | 92 | except: 93 | raise TypeError, "items must be an array of 'item' structs" 94 | 95 | def Ping(): 96 | global NUMPINGS 97 | NUMPINGS += 1 98 | return 99 | 100 | def Monitor(str): 101 | if str=="actzero": 102 | global NUMBUYS 103 | global NUMREQUESTS 104 | global NUMSIMPLEBUYS 105 | global NUMPINGS 106 | return "(Buys, RequestForQuote(s),SimpleBuy(s), Ping(s)) = " + \ 107 | repr( (NUMBUYS,NUMREQUESTS,NUMSIMPLEBUYS, NUMPINGS) ) 108 | else: 109 | raise ValueError, "not the right string" 110 | 111 | def Clear(str): 112 | if str=="actzero": 113 | global NUMBUYS 114 | global NUMREQUESTS 115 | global NUMSIMPLEBUYS 116 | global NUMPINGS 117 | NUMBUYS = 0 118 | NUMREQUESTS = 0 119 | NUMSIMPLEBUYS = 0 120 | NUMPINGS = 0 121 | return "(Buys, RequestForQuote(s),SimpleBuy(s), Ping(s)) = " + \ 122 | repr( (NUMBUYS,NUMREQUESTS,NUMSIMPLEBUYS, NUMPINGS) ) 123 | else: 124 | raise ValueError, "not the right string" 125 | 126 | 127 | if __name__ == "__main__": 128 | if len(sys.argv) > 1: 129 | try: 130 | port = int(sys.argv[1]) 131 | if port not in range(2000,15000): raise ValueError 132 | except: 133 | print "port must be a number between 2000 and 15000" 134 | sys.exit(1) 135 | else: port = 9000 136 | namespace = "http://www.soapinterop.org/Bid" 137 | server = SOAP.SOAPServer( ('zoo',port) ) 138 | 139 | server.registerKWFunction(SimpleBuy, namespace ) 140 | server.registerKWFunction(RequestForQuote, namespace ) 141 | server.registerKWFunction(Buy, namespace ) 142 | server.registerKWFunction(Ping, namespace ) 143 | server.registerKWFunction(Monitor, namespace ) 144 | server.registerKWFunction(Clear, namespace ) 145 | 146 | try: 147 | server.serve_forever() 148 | except KeyboardInterrupt: 149 | pass 150 | -------------------------------------------------------------------------------- /tests/testWSDL.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import unittest 4 | import os, re 5 | import sys 6 | sys.path.insert (1, '..') 7 | import SOAPpy 8 | 9 | ident = '$Id$' 10 | 11 | # Check for a web proxy definition in environment 12 | try: 13 | proxy_url=os.environ['http_proxy'] 14 | phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) 15 | http_proxy = "%s:%s" % (phost, pport) 16 | except: 17 | http_proxy = None 18 | 19 | 20 | 21 | class IntegerArithmenticTestCase(unittest.TestCase): 22 | 23 | def setUp(self): 24 | self.wsdlstr1 = ''' 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Returns current temperature in a given U.S. zipcode 52 | 53 | 54 | 55 | 56 | 57 | ''' 58 | 59 | def testParseWsdlString(self): 60 | '''Parse XMethods TemperatureService wsdl from a string.''' 61 | 62 | wsdl = SOAPpy.WSDL.Proxy(self.wsdlstr1, http_proxy=http_proxy) 63 | self.assertEquals(len(wsdl.methods), 1) 64 | method = wsdl.methods.values()[0] 65 | self.assertEquals(method.methodName, 'getTemp') 66 | self.assertEquals(method.namespace, 'urn:xmethods-Temperature') 67 | self.assertEquals(method.location, 68 | 'http://services.xmethods.net:80/soap/servlet/rpcrouter') 69 | 70 | def testParseWsdlFile(self): 71 | '''Parse XMethods TemperatureService wsdl from a file.''' 72 | 73 | # figure out path to the test directory 74 | dir = os.path.abspath('.') 75 | fname = './TemperatureService.wsdl' 76 | 77 | try: 78 | f = file(fname) 79 | except (IOError, OSError): 80 | self.assert_(0, 'Cound not find wsdl file "%s"' % file) 81 | 82 | wsdl = SOAPpy.WSDL.Proxy(fname, http_proxy=http_proxy) 83 | self.assertEquals(len(wsdl.methods), 1) 84 | method = wsdl.methods.values()[0] 85 | self.assertEquals(method.methodName, 'getTemp') 86 | self.assertEquals(method.namespace, 'urn:xmethods-Temperature') 87 | self.assertEquals(method.location, 88 | 'http://services.xmethods.net:80/soap/servlet/rpcrouter') 89 | 90 | def testParseWsdlUrl(self): 91 | '''Parse XMethods TemperatureService wsdl from a url.''' 92 | 93 | wsdl = SOAPpy.WSDL.Proxy('http://www.xmethods.net/sd/2001/TemperatureService.wsdl', http_proxy=http_proxy) 94 | self.assertEquals(len(wsdl.methods), 1) 95 | method = wsdl.methods.values()[0] 96 | self.assertEquals(method.methodName, 'getTemp') 97 | self.assertEquals(method.namespace, 'urn:xmethods-Temperature') 98 | self.assertEquals(method.location, 99 | 'http://services.xmethods.net:80/soap/servlet/rpcrouter') 100 | 101 | def testGetTemp(self): 102 | '''Parse TemperatureService and call getTemp.''' 103 | 104 | zip = '01072' 105 | proxy = SOAPpy.WSDL.Proxy(self.wsdlstr1, http_proxy=http_proxy) 106 | temp = proxy.getTemp(zip) 107 | print 'Temperature at', zip, 'is', temp 108 | 109 | 110 | if __name__ == '__main__': 111 | unittest.main() 112 | 113 | -------------------------------------------------------------------------------- /SOAPpy/WSDL.py: -------------------------------------------------------------------------------- 1 | """Parse web services description language to get SOAP methods. 2 | 3 | Rudimentary support.""" 4 | 5 | ident = '$Id$' 6 | from version import __version__ 7 | 8 | import wstools 9 | import xml 10 | from Errors import Error 11 | from Client import SOAPProxy, SOAPAddress 12 | from Config import Config 13 | import urllib 14 | 15 | class Proxy: 16 | """WSDL Proxy. 17 | 18 | SOAPProxy wrapper that parses method names, namespaces, soap actions from 19 | the web service description language (WSDL) file passed into the 20 | constructor. The WSDL reference can be passed in as a stream, an url, a 21 | file name, or a string. 22 | 23 | Loads info into self.methods, a dictionary with methodname keys and values 24 | of WSDLTools.SOAPCallinfo. 25 | 26 | For example, 27 | 28 | url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' 29 | wsdl = WSDL.Proxy(url) 30 | print len(wsdl.methods) # 1 31 | print wsdl.methods.keys() # getTemp 32 | 33 | 34 | See WSDLTools.SOAPCallinfo for more info on each method's attributes. 35 | """ 36 | 37 | def __init__(self, wsdlsource, config=Config, **kw ): 38 | 39 | reader = wstools.WSDLTools.WSDLReader() 40 | self.wsdl = None 41 | 42 | # From Mark Pilgrim's "Dive Into Python" toolkit.py--open anything. 43 | if self.wsdl is None and hasattr(wsdlsource, "read"): 44 | print 'stream:', wsdlsource 45 | try: 46 | self.wsdl = reader.loadFromStream(wsdlsource) 47 | except xml.parsers.expat.ExpatError, e: 48 | newstream = urllib.urlopen(wsdlsource) 49 | buf = newstream.readlines() 50 | raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ 51 | (wsdlsource, "\t".join(buf)) 52 | 53 | 54 | # NOT TESTED (as of April 17, 2003) 55 | #if self.wsdl is None and wsdlsource == '-': 56 | # import sys 57 | # self.wsdl = reader.loadFromStream(sys.stdin) 58 | # print 'stdin' 59 | 60 | if self.wsdl is None: 61 | try: 62 | file(wsdlsource) 63 | self.wsdl = reader.loadFromFile(wsdlsource) 64 | #print 'file' 65 | except (IOError, OSError): pass 66 | except xml.parsers.expat.ExpatError, e: 67 | newstream = urllib.urlopen(wsdlsource) 68 | buf = newstream.readlines() 69 | raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ 70 | (wsdlsource, "\t".join(buf)) 71 | 72 | if self.wsdl is None: 73 | try: 74 | stream = urllib.urlopen(wsdlsource) 75 | self.wsdl = reader.loadFromStream(stream, wsdlsource) 76 | except (IOError, OSError): pass 77 | except xml.parsers.expat.ExpatError, e: 78 | newstream = urllib.urlopen(wsdlsource) 79 | buf = newstream.readlines() 80 | raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ 81 | (wsdlsource, "\t".join(buf)) 82 | 83 | if self.wsdl is None: 84 | import StringIO 85 | self.wsdl = reader.loadFromString(str(wsdlsource)) 86 | #print 'string' 87 | 88 | # Package wsdl info as a dictionary of remote methods, with method name 89 | # as key (based on ServiceProxy.__init__ in ZSI library). 90 | self.methods = {} 91 | service = self.wsdl.services[0] 92 | port = service.ports[0] 93 | name = service.name 94 | binding = port.getBinding() 95 | portType = binding.getPortType() 96 | for operation in portType.operations: 97 | callinfo = wstools.WSDLTools.callInfoFromWSDL(port, operation.name) 98 | self.methods[callinfo.methodName] = callinfo 99 | 100 | self.soapproxy = SOAPProxy('http://localhost/dummy.webservice', 101 | config=config, **kw) 102 | 103 | def __str__(self): 104 | s = '' 105 | for method in self.methods.values(): 106 | s += str(method) 107 | return s 108 | 109 | def __getattr__(self, name): 110 | """Set up environment then let parent class handle call. 111 | 112 | Raises AttributeError is method name is not found.""" 113 | 114 | if not self.methods.has_key(name): raise AttributeError, name 115 | 116 | callinfo = self.methods[name] 117 | self.soapproxy.proxy = SOAPAddress(callinfo.location) 118 | self.soapproxy.namespace = callinfo.namespace 119 | self.soapproxy.soapaction = callinfo.soapAction 120 | return self.soapproxy.__getattr__(name) 121 | 122 | def show_methods(self): 123 | for key in self.methods.keys(): 124 | method = self.methods[key] 125 | print "Method Name:", key.ljust(15) 126 | print 127 | inps = method.inparams 128 | for parm in range(len(inps)): 129 | details = inps[parm] 130 | print " In #%d: %s (%s)" % (parm, details.name, details.type) 131 | print 132 | outps = method.outparams 133 | for parm in range(len(outps)): 134 | details = outps[parm] 135 | print " Out #%d: %s (%s)" % (parm, details.name, details.type) 136 | print 137 | 138 | -------------------------------------------------------------------------------- /SOAPpy/GSIServer.py: -------------------------------------------------------------------------------- 1 | from __future__ import nested_scopes 2 | 3 | """ 4 | GSIServer - Contributed by Ivan R. Judson 5 | 6 | 7 | ################################################################################ 8 | # 9 | # SOAPpy - Cayce Ullman (cayce@actzero.com) 10 | # Brian Matthews (blm@actzero.com) 11 | # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) 12 | # Christopher Blunck (blunck@gst.com) 13 | # 14 | ################################################################################ 15 | # Copyright (c) 2003, Pfizer 16 | # Copyright (c) 2001, Cayce Ullman. 17 | # Copyright (c) 2001, Brian Matthews. 18 | # 19 | # All rights reserved. 20 | # 21 | # Redistribution and use in source and binary forms, with or without 22 | # modification, are permitted provided that the following conditions are met: 23 | # Redistributions of source code must retain the above copyright notice, this 24 | # list of conditions and the following disclaimer. 25 | # 26 | # Redistributions in binary form must reproduce the above copyright notice, 27 | # this list of conditions and the following disclaimer in the documentation 28 | # and/or other materials provided with the distribution. 29 | # 30 | # Neither the name of actzero, inc. nor the names of its contributors may 31 | # be used to endorse or promote products derived from this software without 32 | # specific prior written permission. 33 | # 34 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 35 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 38 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 40 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 41 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 42 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 43 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | # 45 | ################################################################################ 46 | """ 47 | 48 | ident = '$Id$' 49 | from version import __version__ 50 | 51 | #import xml.sax 52 | import re 53 | import socket 54 | import sys 55 | import SocketServer 56 | from types import * 57 | import BaseHTTPServer 58 | 59 | # SOAPpy modules 60 | from Parser import parseSOAPRPC 61 | from Config import SOAPConfig 62 | from Types import faultType, voidType, simplify 63 | from NS import NS 64 | from SOAPBuilder import buildSOAP 65 | from Utilities import debugHeader, debugFooter 66 | 67 | try: from M2Crypto import SSL 68 | except: pass 69 | 70 | ##### 71 | 72 | from Server import * 73 | 74 | from pyGlobus.io import GSITCPSocketServer, ThreadingGSITCPSocketServer 75 | from pyGlobus import ioc 76 | 77 | def GSIConfig(): 78 | config = SOAPConfig() 79 | config.channel_mode = ioc.GLOBUS_IO_SECURE_CHANNEL_MODE_GSI_WRAP 80 | config.delegation_mode = ioc.GLOBUS_IO_SECURE_DELEGATION_MODE_FULL_PROXY 81 | config.tcpAttr = None 82 | config.authMethod = "_authorize" 83 | return config 84 | 85 | Config = GSIConfig() 86 | 87 | class GSISOAPServer(GSITCPSocketServer, SOAPServerBase): 88 | def __init__(self, addr = ('localhost', 8000), 89 | RequestHandler = SOAPRequestHandler, log = 0, 90 | encoding = 'UTF-8', config = Config, namespace = None): 91 | 92 | # Test the encoding, raising an exception if it's not known 93 | if encoding != None: 94 | ''.encode(encoding) 95 | 96 | self.namespace = namespace 97 | self.objmap = {} 98 | self.funcmap = {} 99 | self.encoding = encoding 100 | self.config = config 101 | self.log = log 102 | 103 | self.allow_reuse_address= 1 104 | 105 | GSITCPSocketServer.__init__(self, addr, RequestHandler, 106 | self.config.channel_mode, 107 | self.config.delegation_mode, 108 | tcpAttr = self.config.tcpAttr) 109 | 110 | def get_request(self): 111 | sock, addr = GSITCPSocketServer.get_request(self) 112 | 113 | return sock, addr 114 | 115 | class ThreadingGSISOAPServer(ThreadingGSITCPSocketServer, SOAPServerBase): 116 | 117 | def __init__(self, addr = ('localhost', 8000), 118 | RequestHandler = SOAPRequestHandler, log = 0, 119 | encoding = 'UTF-8', config = Config, namespace = None): 120 | 121 | # Test the encoding, raising an exception if it's not known 122 | if encoding != None: 123 | ''.encode(encoding) 124 | 125 | self.namespace = namespace 126 | self.objmap = {} 127 | self.funcmap = {} 128 | self.encoding = encoding 129 | self.config = config 130 | self.log = log 131 | 132 | self.allow_reuse_address= 1 133 | 134 | ThreadingGSITCPSocketServer.__init__(self, addr, RequestHandler, 135 | self.config.channel_mode, 136 | self.config.delegation_mode, 137 | tcpAttr = self.config.tcpAttr) 138 | 139 | def get_request(self): 140 | sock, addr = ThreadingGSITCPSocketServer.get_request(self) 141 | 142 | return sock, addr 143 | 144 | -------------------------------------------------------------------------------- /tests/echoServer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2001 actzero, inc. All rights reserved. 4 | 5 | import sys 6 | sys.path.insert(1, "..") 7 | 8 | from SOAPpy import * 9 | 10 | # Uncomment to see outgoing HTTP headers and SOAP and incoming 11 | Config.dumpSOAPIn = 1 12 | Config.dumpSOAPOut = 1 13 | Config.debug = 1 14 | 15 | # specify name of authorization function 16 | Config.authMethod = "_authorize" 17 | 18 | # Set this to 0 to test authorization 19 | allowAll = 1 20 | 21 | # ask for returned SOAP responses to be converted to basic python types 22 | Config.simplify_objects = 1 23 | 24 | 25 | # provide a mechanism to stop the server 26 | run = 1 27 | def quit(): 28 | global run 29 | run=0; 30 | 31 | 32 | if Config.SSLserver: 33 | from M2Crypto import SSL 34 | 35 | def _authorize(*args, **kw): 36 | global allowAll, Config 37 | 38 | if Config.debug: 39 | print "Authorize (function) called! (result = %d)" % allowAll 40 | print "Arguments: %s" % kw 41 | 42 | if allowAll: 43 | return 1 44 | else: 45 | return 0 46 | 47 | # Simple echo 48 | def echo(s): 49 | global Config 50 | 51 | # Test of context retrieval 52 | ctx = Server.GetSOAPContext() 53 | if Config.debug: 54 | print "SOAP Context: ", ctx 55 | 56 | return s + s 57 | 58 | # An echo class 59 | class echoBuilder2: 60 | def echo2(self, val): 61 | return val * 3 62 | 63 | # A class that has an instance variable which is an echo class 64 | class echoBuilder: 65 | def __init__(self): 66 | self.prop = echoBuilder2() 67 | 68 | def echo_ino(self, val): 69 | return val + val 70 | def _authorize(self, *args, **kw): 71 | global allowAll, Config 72 | 73 | if Config.debug: 74 | print "Authorize (method) called with arguments:" 75 | print "*args=%s" % str(args) 76 | print "**kw =%s" % str(kw) 77 | print "Approved -> %d" % allowAll 78 | 79 | if allowAll: 80 | return 1 81 | else: 82 | return 0 83 | 84 | # Echo with context 85 | def echo_wc(s, _SOAPContext): 86 | global Config 87 | 88 | c = _SOAPContext 89 | 90 | sep = '-' * 72 91 | 92 | # The Context object has extra info about the call 93 | if Config.debug: 94 | print "-- XML", sep[7:] 95 | # The original XML request 96 | print c.xmldata 97 | 98 | print "-- Header", sep[10:] 99 | # The SOAP Header or None if not present 100 | print c.header 101 | 102 | if c.header: 103 | print "-- Header.mystring", sep[19:] 104 | # An element of the SOAP Header 105 | print c.header.mystring 106 | 107 | print "-- Body", sep[8:] 108 | # The whole Body object 109 | print c.body 110 | 111 | print "-- Peer", sep[8:] 112 | if not GSI: 113 | # The socket object, useful for 114 | print c.connection.getpeername() 115 | else: 116 | # The socket object, useful for 117 | print c.connection.get_remote_address() 118 | ctx = c.connection.get_security_context() 119 | print ctx.inquire()[0].display() 120 | 121 | print "-- SOAPAction", sep[14:] 122 | # The SOAPaction HTTP header 123 | print c.soapaction 124 | 125 | print "-- HTTP headers", sep[16:] 126 | # All the HTTP headers 127 | print c.httpheaders 128 | 129 | return s + s 130 | 131 | # Echo with keyword arguments 132 | def echo_wkw(**kw): 133 | return kw['first'] + kw['second'] + kw['third'] 134 | 135 | # Simple echo 136 | def echo_simple(*arg): 137 | return arg 138 | 139 | def echo_header(s, _SOAPContext): 140 | global Config 141 | 142 | c = _SOAPContext 143 | return s, c.header 144 | 145 | 146 | addr = ('localhost', 9900) 147 | GSI = 0 148 | SSL = 0 149 | if len(sys.argv) > 1 and sys.argv[1] == '-s': 150 | SSL = 1 151 | if not Config.SSLserver: 152 | raise RuntimeError, \ 153 | "this Python installation doesn't have OpenSSL and M2Crypto" 154 | ssl_context = SSL.Context() 155 | ssl_context.load_cert('validate/server.pem') 156 | server = SOAPServer(addr, ssl_context = ssl_context) 157 | prefix = 'https' 158 | elif len(sys.argv) > 1 and sys.argv[1] == '-g': 159 | GSI = 1 160 | from SOAPpy.GSIServer import GSISOAPServer 161 | server = GSISOAPServer(addr) 162 | prefix = 'httpg' 163 | else: 164 | server = SOAPServer(addr) 165 | prefix = 'http' 166 | 167 | print "Server listening at: %s://%s:%d/" % (prefix, addr[0], addr[1]) 168 | 169 | # register the method 170 | server.registerFunction(echo) 171 | server.registerFunction(echo, path = "/pathtest") 172 | server.registerFunction(_authorize) 173 | server.registerFunction(_authorize, path = "/pathtest") 174 | 175 | # Register a whole object 176 | o = echoBuilder() 177 | server.registerObject(o, path = "/pathtest") 178 | server.registerObject(o) 179 | 180 | # Register a function which gets called with the Context object 181 | server.registerFunction(MethodSig(echo_wc, keywords = 0, context = 1), 182 | path = "/pathtest") 183 | server.registerFunction(MethodSig(echo_wc, keywords = 0, context = 1)) 184 | 185 | # Register a function that takes keywords 186 | server.registerKWFunction(echo_wkw, path = "/pathtest") 187 | server.registerKWFunction(echo_wkw) 188 | 189 | server.registerFunction(echo_simple) 190 | server.registerFunction(MethodSig(echo_header, keywords=0, context=1)) 191 | server.registerFunction(quit) 192 | 193 | # Start the server 194 | try: 195 | while run: 196 | server.handle_request() 197 | except KeyboardInterrupt: 198 | pass 199 | -------------------------------------------------------------------------------- /SOAPpy/Utilities.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################################################################ 3 | # Copyright (c) 2003, Pfizer 4 | # Copyright (c) 2001, Cayce Ullman. 5 | # Copyright (c) 2001, Brian Matthews. 6 | # 7 | # All rights reserved. 8 | # 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | # Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # Neither the name of actzero, inc. nor the names of its contributors may 19 | # be used to endorse or promote products derived from this software without 20 | # specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 26 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | # 33 | ################################################################################ 34 | """ 35 | 36 | ident = '$Id$' 37 | from version import __version__ 38 | 39 | import re 40 | import string 41 | import sys 42 | from types import * 43 | 44 | # SOAPpy modules 45 | from Errors import * 46 | 47 | ################################################################################ 48 | # Utility infielders 49 | ################################################################################ 50 | def collapseWhiteSpace(s): 51 | return re.sub('\s+', ' ', s).strip() 52 | 53 | def decodeHexString(data): 54 | conv = { 55 | '0': 0x0, '1': 0x1, '2': 0x2, '3': 0x3, '4': 0x4, 56 | '5': 0x5, '6': 0x6, '7': 0x7, '8': 0x8, '9': 0x9, 57 | 58 | 'a': 0xa, 'b': 0xb, 'c': 0xc, 'd': 0xd, 'e': 0xe, 59 | 'f': 0xf, 60 | 61 | 'A': 0xa, 'B': 0xb, 'C': 0xc, 'D': 0xd, 'E': 0xe, 62 | 'F': 0xf, 63 | } 64 | 65 | ws = string.whitespace 66 | 67 | bin = '' 68 | 69 | i = 0 70 | 71 | while i < len(data): 72 | if data[i] not in ws: 73 | break 74 | i += 1 75 | 76 | low = 0 77 | 78 | while i < len(data): 79 | c = data[i] 80 | 81 | if c in string.whitespace: 82 | break 83 | 84 | try: 85 | c = conv[c] 86 | except KeyError: 87 | raise ValueError, \ 88 | "invalid hex string character `%s'" % c 89 | 90 | if low: 91 | bin += chr(high * 16 + c) 92 | low = 0 93 | else: 94 | high = c 95 | low = 1 96 | 97 | i += 1 98 | 99 | if low: 100 | raise ValueError, "invalid hex string length" 101 | 102 | while i < len(data): 103 | if data[i] not in string.whitespace: 104 | raise ValueError, \ 105 | "invalid hex string character `%s'" % c 106 | 107 | i += 1 108 | 109 | return bin 110 | 111 | def encodeHexString(data): 112 | h = '' 113 | 114 | for i in data: 115 | h += "%02X" % ord(i) 116 | 117 | return h 118 | 119 | def leapMonth(year, month): 120 | return month == 2 and \ 121 | year % 4 == 0 and \ 122 | (year % 100 != 0 or year % 400 == 0) 123 | 124 | def cleanDate(d, first = 0): 125 | ranges = (None, (1, 12), (1, 31), (0, 23), (0, 59), (0, 61)) 126 | months = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) 127 | names = ('year', 'month', 'day', 'hours', 'minutes', 'seconds') 128 | 129 | if len(d) != 6: 130 | raise ValueError, "date must have 6 elements" 131 | 132 | for i in range(first, 6): 133 | s = d[i] 134 | 135 | if type(s) == FloatType: 136 | if i < 5: 137 | try: 138 | s = int(s) 139 | except OverflowError: 140 | if i > 0: 141 | raise 142 | s = long(s) 143 | 144 | if s != d[i]: 145 | raise ValueError, "%s must be integral" % names[i] 146 | 147 | d[i] = s 148 | elif type(s) == LongType: 149 | try: s = int(s) 150 | except: pass 151 | elif type(s) != IntType: 152 | raise TypeError, "%s isn't a valid type" % names[i] 153 | 154 | if i == first and s < 0: 155 | continue 156 | 157 | if ranges[i] != None and \ 158 | (s < ranges[i][0] or ranges[i][1] < s): 159 | raise ValueError, "%s out of range" % names[i] 160 | 161 | if first < 6 and d[5] >= 61: 162 | raise ValueError, "seconds out of range" 163 | 164 | if first < 2: 165 | leap = first < 1 and leapMonth(d[0], d[1]) 166 | 167 | if d[2] > months[d[1]] + leap: 168 | raise ValueError, "day out of range" 169 | 170 | def debugHeader(title): 171 | s = '*** ' + title + ' ' 172 | print s + ('*' * (72 - len(s))) 173 | 174 | def debugFooter(title): 175 | print '*' * 72 176 | sys.stdout.flush() 177 | -------------------------------------------------------------------------------- /docs/GettingStarted.txt: -------------------------------------------------------------------------------- 1 | 2 | Getting Started 3 | =============== 4 | 5 | NEW: 6 | 7 | Mark Pilgrims' online book _Dive Into Python_ at 8 | http://diveintopython.org includes a nice tutorial for SOAPpy in 9 | Chapter 12. "SOAP Web Services" at 10 | http://diveintopython.org/soap_web_services. 11 | 12 | 13 | 14 | The easiest way to get up to speed is to run and read the scripts in the 15 | tests directory. Better documentation is coming. 16 | 17 | Here are some examples of how to use SOAPpy: 18 | 19 | 20 | CLIENT EXAMPLES: 21 | 22 | ## CODE 23 | from SOAPpy import SOAPProxy 24 | server = SOAPProxy("http://localhost:8080/") 25 | print server.echo("Hello world") 26 | ## /CODE 27 | 28 | This opens a connection to the server listening on localhost:8080, calls the 29 | method echo with the ordered parameter of "Hello World", and prints the 30 | results. 31 | 32 | 33 | ## CODE 34 | from SOAPpy import SOAPProxy 35 | server = SOAPProxy("https://localhost:8443/") 36 | print server.echo("Hello world") 37 | ## /CODE 38 | 39 | This opens a secure connection to the SSL server listening on 40 | localhost:8443, calls the method echo with the ordered parameter of 41 | "Hello World" and prints the results. Python must be built with OpenSSL. 42 | 43 | 44 | ## CODE 45 | from SOAPpy import SOAPProxy 46 | server = SOAPProxy("http://services.xmethods.com/soap", 47 | namespace = "urn:xmethods-delayed-quotes") 48 | print server.getQuote(symbol = "IBM") 49 | ## /CODE 50 | 51 | This calls method getQuote that is in the namespace URI of 52 | urn:xmethods-delayed-quotes on server services.xmethods.com. getQuote is 53 | passed a named parameter, symbol. 54 | 55 | 56 | ## CODE 57 | from SOAPpy import SOAPProxy 58 | server = SOAPProxy("http://services.xmethods.com/soap") 59 | 60 | print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM") 61 | ## /CODE 62 | 63 | This does the same thing as the previous example, however namespace is 64 | specified inline on a per call basis rather than at the server level. 65 | 66 | 67 | ## CODE 68 | from SOAPpy import SOAPProxy 69 | server = SOAPProxy("http://services.xmethods.com/soap", 70 | soapaction = "http://somesite.com/myaction") 71 | 72 | print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM") 73 | ## /CODE 74 | 75 | This is the same quote call with a soapaction specified. 76 | 77 | 78 | ## CODE 79 | from SOAPpy import SOAPProxy 80 | server = SOAPProxy("http://services.xmethods.com:80/soap") 81 | 82 | ns = "urn:xmethods-delayed-quotes") 83 | sa = "http://somesite.com/myaction" 84 | my_call = server._ns(ns)._sa(sa) 85 | my_call.getQuote(symbol = "IBM") 86 | my_call.getQuote(symbol = "IBM") 87 | my_call.getQuote(symbol = "IBM") 88 | ## /CODE 89 | 90 | The same example, this time with both the soapaction and the namespace 91 | specified inline and saved in a local variable for getQuote to be called 92 | against. 93 | 94 | ** What SOAPpy does with the results of a call could seem surprising. If 95 | there is only one element in the structType that has the return value and 96 | unwrap_results is turned on (the default) it will bubble up the single 97 | attribute, otherwise it will return you a structType object with all of the 98 | attributes. 99 | 100 | 101 | 102 | SERVER EXAMPLES: 103 | 104 | ## CODE 105 | from SOAPpy import SOAPServer 106 | def echo(s): 107 | return s + s # repeats a string twice 108 | 109 | server = SOAPServer(("localhost", 8080)) 110 | server.registerFunction(echo) 111 | server.serve_forever() 112 | ## /CODE 113 | 114 | This exposes the function echo (that takes an unnamed arguement) on a server 115 | running on localhost:8080. 116 | 117 | 118 | ## CODE 119 | from SOAPpy import SOAPServer 120 | def echo(s): 121 | return s + s # repeats a string twice 122 | 123 | server = SOAPServer() 124 | server.registerFunction(echo, "echo-space") 125 | server.serve_forever() 126 | ## /CODE 127 | 128 | The same as above, but this time the method is available in the namespace 129 | "echo-space". 130 | 131 | 132 | ## CODE 133 | from SOAPpy import SOAPServer 134 | 135 | class echoBuilder: 136 | def echo(self, val): 137 | return val + val 138 | 139 | server = SOAPServer() 140 | e = echoBuilder() 141 | server.registerObject(e) 142 | server.serve_forever() 143 | ## /CODE 144 | 145 | This registers the whole instance of the object echoBuilder, e. Every 146 | method of the instance is exposed on the server. 147 | 148 | 149 | ## CODE 150 | from SOAPpy import SOAPServer 151 | 152 | def echo(**kw): 153 | return kw['first'] + kw['second'] + kw['third'] 154 | 155 | server = SOAPServer() 156 | server.registerKWFunction(echo) 157 | server.serve_forever() 158 | ## /CODE 159 | 160 | This time the method echo is exposed and it expects named arguments. The 161 | main thing to notice here is the use of the method registerKWFunction over 162 | registerFunction. 163 | 164 | 165 | ## CODE 166 | from SOAPpy import SOAPServer 167 | 168 | from M2Crypto import SSL 169 | 170 | def echo(s): 171 | return s+s # repeats a string twice 172 | 173 | ssl_context = SSL.Context() 174 | ssl_context.load_cert('server.pem') 175 | 176 | server = SOAPServer(("localhost",8443), ssl_context = ssl_context) 177 | server.registerFunction(echo) 178 | server.serve_forever() 179 | ## /CODE 180 | 181 | This exposes the function echo (taking an unnamed arguement) on a server 182 | accepting SSL connections at localhost:8443. Ng Pheng Siong's M2Crypto 183 | package (available at ) must be 184 | installed. Also see tests/silabserver.py. 185 | 186 | $Id$ 187 | -------------------------------------------------------------------------------- /SOAPpy/wstools/TimeoutSocket.py: -------------------------------------------------------------------------------- 1 | """Based on code from timeout_socket.py, with some tweaks for compatibility. 2 | These tweaks should really be rolled back into timeout_socket, but it's 3 | not totally clear who is maintaining it at this point. In the meantime, 4 | we'll use a different module name for our tweaked version to avoid any 5 | confusion. 6 | 7 | The original timeout_socket is by: 8 | 9 | Scott Cotton 10 | Lloyd Zusman 11 | Phil Mayes 12 | Piers Lauder 13 | Radovan Garabik 14 | """ 15 | 16 | ident = "$Id$" 17 | 18 | import string, socket, select, errno 19 | 20 | WSAEINVAL = getattr(errno, 'WSAEINVAL', 10022) 21 | 22 | 23 | class TimeoutSocket: 24 | """A socket imposter that supports timeout limits.""" 25 | 26 | def __init__(self, timeout=20, sock=None): 27 | self.timeout = float(timeout) 28 | self.inbuf = '' 29 | if sock is None: 30 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 31 | self.sock = sock 32 | self.sock.setblocking(0) 33 | self._rbuf = '' 34 | self._wbuf = '' 35 | 36 | def __getattr__(self, name): 37 | # Delegate to real socket attributes. 38 | return getattr(self.sock, name) 39 | 40 | def connect(self, *addr): 41 | timeout = self.timeout 42 | sock = self.sock 43 | try: 44 | # Non-blocking mode 45 | sock.setblocking(0) 46 | apply(sock.connect, addr) 47 | sock.setblocking(timeout != 0) 48 | return 1 49 | except socket.error,why: 50 | if not timeout: 51 | raise 52 | sock.setblocking(1) 53 | if len(why.args) == 1: 54 | code = 0 55 | else: 56 | code, why = why 57 | if code not in ( 58 | errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK 59 | ): 60 | raise 61 | r,w,e = select.select([],[sock],[],timeout) 62 | if w: 63 | try: 64 | apply(sock.connect, addr) 65 | return 1 66 | except socket.error,why: 67 | if len(why.args) == 1: 68 | code = 0 69 | else: 70 | code, why = why 71 | if code in (errno.EISCONN, WSAEINVAL): 72 | return 1 73 | raise 74 | raise TimeoutError('socket connect() timeout.') 75 | 76 | def send(self, data, flags=0): 77 | total = len(data) 78 | next = 0 79 | while 1: 80 | r, w, e = select.select([],[self.sock], [], self.timeout) 81 | if w: 82 | buff = data[next:next + 8192] 83 | sent = self.sock.send(buff, flags) 84 | next = next + sent 85 | if next == total: 86 | return total 87 | continue 88 | raise TimeoutError('socket send() timeout.') 89 | 90 | def recv(self, amt, flags=0): 91 | if select.select([self.sock], [], [], self.timeout)[0]: 92 | return self.sock.recv(amt, flags) 93 | raise TimeoutError('socket recv() timeout.') 94 | 95 | buffsize = 4096 96 | handles = 1 97 | 98 | def makefile(self, mode="r", buffsize=-1): 99 | self.handles = self.handles + 1 100 | self.mode = mode 101 | return self 102 | 103 | def close(self): 104 | self.handles = self.handles - 1 105 | if self.handles == 0 and self.sock.fileno() >= 0: 106 | self.sock.close() 107 | 108 | def read(self, n=-1): 109 | if not isinstance(n, type(1)): 110 | n = -1 111 | if n >= 0: 112 | k = len(self._rbuf) 113 | if n <= k: 114 | data = self._rbuf[:n] 115 | self._rbuf = self._rbuf[n:] 116 | return data 117 | n = n - k 118 | L = [self._rbuf] 119 | self._rbuf = "" 120 | while n > 0: 121 | new = self.recv(max(n, self.buffsize)) 122 | if not new: break 123 | k = len(new) 124 | if k > n: 125 | L.append(new[:n]) 126 | self._rbuf = new[n:] 127 | break 128 | L.append(new) 129 | n = n - k 130 | return "".join(L) 131 | k = max(4096, self.buffsize) 132 | L = [self._rbuf] 133 | self._rbuf = "" 134 | while 1: 135 | new = self.recv(k) 136 | if not new: break 137 | L.append(new) 138 | k = min(k*2, 1024**2) 139 | return "".join(L) 140 | 141 | def readline(self, limit=-1): 142 | data = "" 143 | i = self._rbuf.find('\n') 144 | while i < 0 and not (0 < limit <= len(self._rbuf)): 145 | new = self.recv(self.buffsize) 146 | if not new: break 147 | i = new.find('\n') 148 | if i >= 0: i = i + len(self._rbuf) 149 | self._rbuf = self._rbuf + new 150 | if i < 0: i = len(self._rbuf) 151 | else: i = i+1 152 | if 0 <= limit < len(self._rbuf): i = limit 153 | data, self._rbuf = self._rbuf[:i], self._rbuf[i:] 154 | return data 155 | 156 | def readlines(self, sizehint = 0): 157 | total = 0 158 | list = [] 159 | while 1: 160 | line = self.readline() 161 | if not line: break 162 | list.append(line) 163 | total += len(line) 164 | if sizehint and total >= sizehint: 165 | break 166 | return list 167 | 168 | def writelines(self, list): 169 | self.send(''.join(list)) 170 | 171 | def write(self, data): 172 | self.send(data) 173 | 174 | def flush(self): 175 | pass 176 | 177 | 178 | class TimeoutError(Exception): 179 | pass 180 | -------------------------------------------------------------------------------- /SOAPpy/wstools/test/test_wsdl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ############################################################################ 4 | # Joshua R. Boverhof, David W. Robertson, LBNL 5 | # See LBNLCopyright for copyright notice! 6 | ########################################################################### 7 | 8 | import sys, unittest 9 | import ConfigParser 10 | from ZSI.wstools.Utility import DOM 11 | from ZSI.wstools.WSDLTools import WSDLReader 12 | from ZSI.wstools.TimeoutSocket import TimeoutError 13 | 14 | class WSDLToolsTestCase(unittest.TestCase): 15 | 16 | def __init__(self, methodName='runTest'): 17 | unittest.TestCase.__init__(self, methodName) 18 | 19 | def setUp(self): 20 | self.path = nameGenerator.next() 21 | print self.path 22 | sys.stdout.flush() 23 | 24 | def __str__(self): 25 | teststr = unittest.TestCase.__str__(self) 26 | if hasattr(self, "path"): 27 | return "%s: %s" % (teststr, self.path ) 28 | else: 29 | return "%s" % (teststr) 30 | 31 | def checkWSDLCollection(self, tag_name, component, key='name'): 32 | if self.wsdl is None: 33 | return 34 | definition = self.wsdl.document.documentElement 35 | version = DOM.WSDLUriToVersion(definition.namespaceURI) 36 | nspname = DOM.GetWSDLUri(version) 37 | for node in DOM.getElements(definition, tag_name, nspname): 38 | name = DOM.getAttr(node, key) 39 | comp = component[name] 40 | self.failUnlessEqual(eval('comp.%s' %key), name) 41 | 42 | def checkXSDCollection(self, tag_name, component, node, key='name'): 43 | for cnode in DOM.getElements(node, tag_name): 44 | name = DOM.getAttr(cnode, key) 45 | component[name] 46 | 47 | def test_all(self): 48 | try: 49 | if self.path[:7] == 'http://': 50 | self.wsdl = WSDLReader().loadFromURL(self.path) 51 | else: 52 | self.wsdl = WSDLReader().loadFromFile(self.path) 53 | 54 | except TimeoutError: 55 | print "connection timed out" 56 | sys.stdout.flush() 57 | return 58 | except: 59 | self.path = self.path + ": load failed, unable to start" 60 | raise 61 | 62 | try: 63 | self.checkWSDLCollection('service', self.wsdl.services) 64 | except: 65 | self.path = self.path + ": wsdl.services" 66 | raise 67 | 68 | try: 69 | self.checkWSDLCollection('message', self.wsdl.messages) 70 | except: 71 | self.path = self.path + ": wsdl.messages" 72 | raise 73 | 74 | try: 75 | self.checkWSDLCollection('portType', self.wsdl.portTypes) 76 | except: 77 | self.path = self.path + ": wsdl.portTypes" 78 | raise 79 | 80 | try: 81 | self.checkWSDLCollection('binding', self.wsdl.bindings) 82 | except: 83 | self.path = self.path + ": wsdl.bindings" 84 | raise 85 | 86 | try: 87 | self.checkWSDLCollection('import', self.wsdl.imports, key='namespace') 88 | except: 89 | self.path = self.path + ": wsdl.imports" 90 | raise 91 | 92 | try: 93 | for key in self.wsdl.types.keys(): 94 | schema = self.wsdl.types[key] 95 | self.failUnlessEqual(key, schema.getTargetNamespace()) 96 | 97 | definition = self.wsdl.document.documentElement 98 | version = DOM.WSDLUriToVersion(definition.namespaceURI) 99 | nspname = DOM.GetWSDLUri(version) 100 | for node in DOM.getElements(definition, 'types', nspname): 101 | for snode in DOM.getElements(node, 'schema'): 102 | tns = DOM.findTargetNS(snode) 103 | schema = self.wsdl.types[tns] 104 | self.schemaAttributesDeclarations(schema, snode) 105 | self.schemaAttributeGroupDeclarations(schema, snode) 106 | self.schemaElementDeclarations(schema, snode) 107 | self.schemaTypeDefinitions(schema, snode) 108 | except: 109 | self.path = self.path + ": wsdl.types" 110 | raise 111 | 112 | if self.wsdl.extensions: 113 | print 'No check for WSDLTools(%s) Extensions:' %(self.wsdl.name) 114 | for ext in self.wsdl.extensions: print '\t', ext 115 | 116 | def schemaAttributesDeclarations(self, schema, node): 117 | self.checkXSDCollection('attribute', schema.attr_decl, node) 118 | 119 | def schemaAttributeGroupDeclarations(self, schema, node): 120 | self.checkXSDCollection('group', schema.attr_groups, node) 121 | 122 | def schemaElementDeclarations(self, schema, node): 123 | self.checkXSDCollection('element', schema.elements, node) 124 | 125 | def schemaTypeDefinitions(self, schema, node): 126 | self.checkXSDCollection('complexType', schema.types, node) 127 | self.checkXSDCollection('simpleType', schema.types, node) 128 | 129 | 130 | def setUpOptions(section): 131 | cp = ConfigParser.ConfigParser() 132 | cp.read('config.txt') 133 | if not cp.sections(): 134 | print 'fatal error: configuration file config.txt not present' 135 | sys.exit(0) 136 | if not cp.has_section(section): 137 | print '%s section not present in configuration file, exiting' % section 138 | sys.exit(0) 139 | return cp, len(cp.options(section)) 140 | 141 | def getOption(cp, section): 142 | for name, value in cp.items(section): 143 | yield value 144 | 145 | def makeTestSuite(section='services_by_file'): 146 | global nameGenerator 147 | 148 | cp, numTests = setUpOptions(section) 149 | nameGenerator = getOption(cp, section) 150 | suite = unittest.TestSuite() 151 | for i in range(0, numTests): 152 | suite.addTest(unittest.makeSuite(WSDLToolsTestCase, 'test_')) 153 | return suite 154 | 155 | 156 | def main(): 157 | unittest.main(defaultTest="makeTestSuite") 158 | 159 | 160 | if __name__ == "__main__" : main() 161 | -------------------------------------------------------------------------------- /SOAPpy/fpconst.py: -------------------------------------------------------------------------------- 1 | """Utilities for handling IEEE 754 floating point special values 2 | 3 | This python module implements constants and functions for working with 4 | IEEE754 double-precision special values. It provides constants for 5 | Not-a-Number (NaN), Positive Infinity (PosInf), and Negative Infinity 6 | (NegInf), as well as functions to test for these values. 7 | 8 | The code is implemented in pure python by taking advantage of the 9 | 'struct' standard module. Care has been taken to generate proper 10 | results on both big-endian and little-endian machines. Some efficiency 11 | could be gained by translating the core routines into C. 12 | 13 | See 14 | for reference material on the IEEE 754 floating point standard. 15 | 16 | Further information on this package is available at 17 | . 18 | 19 | ------------------------------------------------------------------ 20 | Author: Gregory R. Warnes 21 | Date: 2005-02-24 22 | Version: 0.7.2 23 | Copyright: (c) 2003-2005 Pfizer, Licensed to PSF under a Contributor Agreement 24 | License: Licensed under the Apache License, Version 2.0 (the"License"); 25 | you may not use this file except in compliance with the License. 26 | You may obtain a copy of the License at 27 | 28 | http://www.apache.org/licenses/LICENSE-2.0 29 | 30 | Unless required by applicable law or agreed to in 31 | writing, software distributed under the License is 32 | distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 33 | CONDITIONS OF ANY KIND, either express or implied. See 34 | the License for the specific language governing 35 | permissions and limitations under the License. 36 | ------------------------------------------------------------------ 37 | """ 38 | 39 | __version__ = "0.7.2" 40 | ident = "$Id: fpconst.py,v 1.16 2005/02/24 17:42:03 warnes Exp $" 41 | 42 | import struct, operator 43 | 44 | # check endianess 45 | _big_endian = struct.pack('i',1)[0] != '\x01' 46 | 47 | # and define appropriate constants 48 | if(_big_endian): 49 | NaN = struct.unpack('d', '\x7F\xF8\x00\x00\x00\x00\x00\x00')[0] 50 | PosInf = struct.unpack('d', '\x7F\xF0\x00\x00\x00\x00\x00\x00')[0] 51 | NegInf = -PosInf 52 | else: 53 | NaN = struct.unpack('d', '\x00\x00\x00\x00\x00\x00\xf8\xff')[0] 54 | PosInf = struct.unpack('d', '\x00\x00\x00\x00\x00\x00\xf0\x7f')[0] 55 | NegInf = -PosInf 56 | 57 | def _double_as_bytes(dval): 58 | "Use struct.unpack to decode a double precision float into eight bytes" 59 | tmp = list(struct.unpack('8B',struct.pack('d', dval))) 60 | if not _big_endian: 61 | tmp.reverse() 62 | return tmp 63 | 64 | ## 65 | ## Functions to extract components of the IEEE 754 floating point format 66 | ## 67 | 68 | def _sign(dval): 69 | "Extract the sign bit from a double-precision floating point value" 70 | bb = _double_as_bytes(dval) 71 | return bb[0] >> 7 & 0x01 72 | 73 | def _exponent(dval): 74 | """Extract the exponentent bits from a double-precision floating 75 | point value. 76 | 77 | Note that for normalized values, the exponent bits have an offset 78 | of 1023. As a consequence, the actual exponentent is obtained 79 | by subtracting 1023 from the value returned by this function 80 | """ 81 | bb = _double_as_bytes(dval) 82 | return (bb[0] << 4 | bb[1] >> 4) & 0x7ff 83 | 84 | def _mantissa(dval): 85 | """Extract the _mantissa bits from a double-precision floating 86 | point value.""" 87 | 88 | bb = _double_as_bytes(dval) 89 | mantissa = bb[1] & 0x0f << 48 90 | mantissa += bb[2] << 40 91 | mantissa += bb[3] << 32 92 | mantissa += bb[4] 93 | return mantissa 94 | 95 | def _zero_mantissa(dval): 96 | """Determine whether the mantissa bits of the given double are all 97 | zero.""" 98 | bb = _double_as_bytes(dval) 99 | return ((bb[1] & 0x0f) | reduce(operator.or_, bb[2:])) == 0 100 | 101 | ## 102 | ## Functions to test for IEEE 754 special values 103 | ## 104 | 105 | def isNaN(value): 106 | "Determine if the argument is a IEEE 754 NaN (Not a Number) value." 107 | return (_exponent(value)==0x7ff and not _zero_mantissa(value)) 108 | 109 | def isInf(value): 110 | """Determine if the argument is an infinite IEEE 754 value (positive 111 | or negative inifinity)""" 112 | return (_exponent(value)==0x7ff and _zero_mantissa(value)) 113 | 114 | def isFinite(value): 115 | """Determine if the argument is an finite IEEE 754 value (i.e., is 116 | not NaN, positive or negative inifinity)""" 117 | return (_exponent(value)!=0x7ff) 118 | 119 | def isPosInf(value): 120 | "Determine if the argument is a IEEE 754 positive infinity value" 121 | return (_sign(value)==0 and _exponent(value)==0x7ff and \ 122 | _zero_mantissa(value)) 123 | 124 | def isNegInf(value): 125 | "Determine if the argument is a IEEE 754 negative infinity value" 126 | return (_sign(value)==1 and _exponent(value)==0x7ff and \ 127 | _zero_mantissa(value)) 128 | 129 | ## 130 | ## Functions to test public functions. 131 | ## 132 | 133 | def test_isNaN(): 134 | assert( not isNaN(PosInf) ) 135 | assert( not isNaN(NegInf) ) 136 | assert( isNaN(NaN ) ) 137 | assert( not isNaN( 1.0) ) 138 | assert( not isNaN( -1.0) ) 139 | 140 | def test_isInf(): 141 | assert( isInf(PosInf) ) 142 | assert( isInf(NegInf) ) 143 | assert( not isInf(NaN ) ) 144 | assert( not isInf( 1.0) ) 145 | assert( not isInf( -1.0) ) 146 | 147 | def test_isFinite(): 148 | assert( not isFinite(PosInf) ) 149 | assert( not isFinite(NegInf) ) 150 | assert( not isFinite(NaN ) ) 151 | assert( isFinite( 1.0) ) 152 | assert( isFinite( -1.0) ) 153 | 154 | def test_isPosInf(): 155 | assert( isPosInf(PosInf) ) 156 | assert( not isPosInf(NegInf) ) 157 | assert( not isPosInf(NaN ) ) 158 | assert( not isPosInf( 1.0) ) 159 | assert( not isPosInf( -1.0) ) 160 | 161 | def test_isNegInf(): 162 | assert( not isNegInf(PosInf) ) 163 | assert( isNegInf(NegInf) ) 164 | assert( not isNegInf(NaN ) ) 165 | assert( not isNegInf( 1.0) ) 166 | assert( not isNegInf( -1.0) ) 167 | 168 | # overall test 169 | def test(): 170 | test_isNaN() 171 | test_isInf() 172 | test_isFinite() 173 | test_isPosInf() 174 | test_isNegInf() 175 | 176 | if __name__ == "__main__": 177 | test() 178 | 179 | -------------------------------------------------------------------------------- /zope/zope-2.5.0-soappy.diff: -------------------------------------------------------------------------------- 1 | diff -urN Zope-2.5.0-linux2-x86/lib/python/ZPublisher/HTTPRequest.py Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2 | --- Zope-2.5.0-linux2-x86/lib/python/ZPublisher/HTTPRequest.py 2002-01-03 20:41:05.000000000 +0100 3 | +++ Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2003-11-12 13:17:57.000000000 +0100 4 | @@ -21,6 +21,7 @@ 5 | from Converters import get_converter 6 | from maybe_lock import allocate_lock 7 | xmlrpc=None # Placeholder for module that we'll import if we have to. 8 | +soap=None 9 | 10 | #cgi hotfix: 11 | if not hasattr(cgi, 'valid_boundary'): 12 | @@ -347,18 +348,28 @@ 13 | meth=None 14 | fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1) 15 | if not hasattr(fs,'list') or fs.list is None: 16 | - # Hm, maybe it's an XML-RPC 17 | - if (fs.headers.has_key('content-type') and 18 | - fs.headers['content-type'] == 'text/xml' and 19 | + # Hm, maybe it's an XML-RPC or SOAP 20 | + if (fs.headers.has_key('content-type') and 21 | + fs.headers['content-type'][:8] == 'text/xml' and 22 | method == 'POST'): 23 | - # Ye haaa, XML-RPC! 24 | - global xmlrpc 25 | - if xmlrpc is None: import xmlrpc 26 | - meth, self.args = xmlrpc.parse_input(fs.value) 27 | - response=xmlrpc.response(response) 28 | - other['RESPONSE']=self.response=response 29 | - other['REQUEST_METHOD']='' # We don't want index_html! 30 | - self.maybe_webdav_client = 0 31 | + if environ.has_key('HTTP_SOAPACTION'): 32 | + # this is a SOAP request 33 | + global soap 34 | + if soap is None: 35 | + import soap 36 | + meth, self.args = soap.parse_input(fs.value) 37 | + response = soap.response(response) 38 | + other['RESPONSE'] = self.response = response 39 | + other['REQUEST_METHOD'] = '' 40 | + else: 41 | + # Ye haaa, XML-RPC! 42 | + global xmlrpc 43 | + if xmlrpc is None: import xmlrpc 44 | + meth, self.args = xmlrpc.parse_input(fs.value) 45 | + response=xmlrpc.response(response) 46 | + other['RESPONSE']=self.response=response 47 | + other['REQUEST_METHOD']='' # We don't want index_html! 48 | + self.maybe_webdav_client = 0 49 | else: 50 | self._file=fs.file 51 | else: 52 | diff -urN Zope-2.5.0-linux2-x86/lib/python/ZPublisher/soap.py Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/soap.py 53 | --- Zope-2.5.0-linux2-x86/lib/python/ZPublisher/soap.py 1970-01-01 01:00:00.000000000 +0100 54 | +++ Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/soap.py 2003-11-12 13:20:39.000000000 +0100 55 | @@ -0,0 +1,108 @@ 56 | +"""SOAP support module 57 | + 58 | +by Antonio Beamud Montero 59 | + 60 | +Based on the XML-RPC Zope support module written by Eric Kidd at UserLand 61 | +software and the modifications made by Petru Paler, with much help 62 | +from Jim Fulton at DC. 63 | + 64 | +This code hooks Zope up to SOAPpy library. 65 | +""" 66 | + 67 | +import sys 68 | +from string import replace 69 | +from HTTPResponse import HTTPResponse 70 | +from SOAPpy import * 71 | +from zLOG import LOG, PROBLEM, ERROR, DEBUG, INFO,TRACE 72 | + 73 | +Config.specialArgs=0. 74 | + 75 | +def parse_input(data): 76 | + """Parse input data and return a method path and argument tuple 77 | + 78 | + The data is a string. 79 | + """ 80 | + obj = Parser.parseSOAPRPC(data) 81 | + method = obj._name 82 | + args = tuple(obj._aslist) 83 | + 84 | + # Translate '.' to '/' in meth to represent object traversal. 85 | + method = replace(method, '.', '/') 86 | + return method, args 87 | + 88 | +####################################################################### 89 | +# New Object response based on SOAPpy 90 | +# 91 | +class SOAPResponse: 92 | + def __init__(self, real): self.__dict__['_real']=real 93 | + def __getattr__(self, name): return getattr(self._real, name) 94 | + def __setattr__(self, name, v): return setattr(self._real, name, v) 95 | + def __delattr__(self, name): return delattr(self._real, name) 96 | + 97 | + def setBody(self, body, title='', is_error=0, bogus_str_search=None): 98 | + # Marshall our body as an SOAP response. Strings will be sent 99 | + # strings, integers as integers, etc. We do *not* convert 100 | + # everything to a string first. 101 | + status = 200 102 | + if isinstance(body, Types.faultType): 103 | + status = 500 104 | + # Convert Fault object to SOAP response. 105 | + soapbody = Types.faulType("%s:Server" % NS.ENV_T, body) 106 | + body = buildSOAP(soapbody,encoding=None) 107 | + else: 108 | + try: 109 | + body = buildSOAP((body,),encoding=None) 110 | + except Exception,e: 111 | + self.exception() 112 | + return self 113 | + 114 | + t = 'text/xml' 115 | + # Set our body to the XML-RPC message, and fix our MIME type. 116 | + self._real.setBody(body) 117 | + self._real.setHeader('content-type', t) 118 | + self._real.setHeader("content-length", str(len(body))) 119 | + self._real.setStatus(status) 120 | + return self 121 | + 122 | + def exception(self, fatal=0, info=None, 123 | + absuri_match=None, tag_search=None): 124 | + # Fetch our exception info. t is type, v is value and tb is the 125 | + # traceback object. 126 | + 127 | + if type(info) is type(()) and len(info)==3: t,v,tb = info 128 | + else: t,v,tb = sys.exc_info() 129 | + LOG('SOAPException', TRACE, tb) 130 | + # Create an appropriate Fault object. Unfortunately, we throw away 131 | + # most of the debugging information. More useful error reporting is 132 | + # left as an exercise for the reader. 133 | + Fault=Types.faultType 134 | + f=None 135 | + try: 136 | + if isinstance(v, Fault): 137 | + f=v 138 | + elif isinstance(v, Exception): 139 | + f=Fault("%s:Server" % NS.ENV_T, 140 | + "Unexpected Zope exception: %s"%str(v)) 141 | + else: 142 | + f=Fault("%s:Server" % NS.ENV_T, 143 | + "Unexpected Zope error value: %s"%str(v)) 144 | + except: 145 | + f=Fault("%s:Server" % NS.ENV_T, 146 | + "Unknown Zope fault type") 147 | + 148 | + # Do the damage. 149 | + body = buildSOAP(f) 150 | + self._real.setBody(body) 151 | + self._real.setHeader('content-type', 'text/xml') 152 | + self._real.setStatus(500) 153 | + return tb 154 | + 155 | +response=SOAPResponse 156 | + 157 | + 158 | + 159 | + 160 | + 161 | + 162 | + 163 | + 164 | -------------------------------------------------------------------------------- /zope/zope-2.6.2-soappy.diff: -------------------------------------------------------------------------------- 1 | diff -urN Zope-2.6.2-linux2-x86/lib/python/ZPublisher/HTTPRequest.py Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2 | --- Zope-2.6.2-linux2-x86/lib/python/ZPublisher/HTTPRequest.py 2003-04-09 16:00:27.000000000 +0200 3 | +++ Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2003-11-12 14:51:01.000000000 +0100 4 | @@ -24,6 +24,7 @@ 5 | from TaintedString import TaintedString 6 | from maybe_lock import allocate_lock 7 | xmlrpc=None # Placeholder for module that we'll import if we have to. 8 | +soap=None # Placeholder for module that we'll import if we have to. 9 | 10 | #cgi hotfix: 11 | if not hasattr(cgi, 'valid_boundary'): 12 | @@ -369,16 +370,26 @@ 13 | meth=None 14 | fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1) 15 | if not hasattr(fs,'list') or fs.list is None: 16 | - # Hm, maybe it's an XML-RPC 17 | + # Hm, maybe it's an XML-RPC or SOAP 18 | if (fs.headers.has_key('content-type') and 19 | - fs.headers['content-type'] == 'text/xml' and 20 | + fs.headers['content-type'][:8] == 'text/xml' and 21 | method == 'POST'): 22 | - # Ye haaa, XML-RPC! 23 | - global xmlrpc 24 | - if xmlrpc is None: import xmlrpc 25 | - meth, self.args = xmlrpc.parse_input(fs.value) 26 | - response=xmlrpc.response(response) 27 | - other['RESPONSE']=self.response=response 28 | + if environ.has_key('HTTP_SOAPACTION'): 29 | + # this is a SOAP request 30 | + global soap 31 | + if soap is None: 32 | + import soap 33 | + meth, self.args = soap.parse_input(fs.value) 34 | + response = soap.response(response) 35 | + other['RESPONSE'] = self.response = response 36 | + other['REQUEST_METHOD'] = '' 37 | + else: 38 | + # Ye haaa, XML-RPC! 39 | + global xmlrpc 40 | + if xmlrpc is None: import xmlrpc 41 | + meth, self.args = xmlrpc.parse_input(fs.value) 42 | + response=xmlrpc.response(response) 43 | + other['RESPONSE']=self.response=response 44 | self.maybe_webdav_client = 0 45 | else: 46 | self._file=fs.file 47 | diff -urN Zope-2.6.2-linux2-x86/lib/python/ZPublisher/soap.py Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/soap.py 48 | --- Zope-2.6.2-linux2-x86/lib/python/ZPublisher/soap.py 1970-01-01 01:00:00.000000000 +0100 49 | +++ Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/soap.py 2003-11-12 14:51:01.000000000 +0100 50 | @@ -0,0 +1,125 @@ 51 | +"""SOAP support module 52 | + 53 | +by Antonio Beamud Montero 54 | + 55 | +Based on the XML-RPC Zope support module written by Eric Kidd at UserLand 56 | +software and the modifications made by Petru Paler, with much help 57 | +from Jim Fulton at DC. 58 | + 59 | +This code hooks Zope up to SOAPpy library. 60 | +""" 61 | + 62 | +import sys 63 | +from string import replace 64 | +from HTTPResponse import HTTPResponse 65 | +from SOAPpy import * 66 | +from zLOG import LOG, PROBLEM, ERROR, DEBUG, INFO,TRACE 67 | + 68 | +Config.specialArgs=0. 69 | + 70 | +def parse_input(data): 71 | + """Parse input data and return a method path and argument tuple 72 | + 73 | + The data is a string. 74 | + """ 75 | + obj = Parser.parseSOAPRPC(data) 76 | + method = obj._name 77 | + args = tuple(obj._aslist) 78 | + 79 | + # Translate '.' to '/' in meth to represent object traversal. 80 | + method = replace(method, '.', '/') 81 | + return method, args 82 | + 83 | +# See below 84 | +# 85 | +# def response(anHTTPResponse): 86 | +# """Return a valid ZPublisher response object 87 | +# 88 | +# Use data already gathered by the existing response. 89 | +# The new response will replace the existing response. 90 | +# """ 91 | +# # As a first cut, lets just clone the response and 92 | +# # put all of the logic in our refined response class below. 93 | +# r=Response() 94 | +# r.__dict__.update(anHTTPResponse.__dict__) 95 | +# return r 96 | + 97 | + 98 | + 99 | + 100 | +####################################################################### 101 | +# New Object response based on SoapPy 102 | +# 103 | +class SOAPResponse: 104 | + def __init__(self, real): self.__dict__['_real']=real 105 | + def __getattr__(self, name): return getattr(self._real, name) 106 | + def __setattr__(self, name, v): return setattr(self._real, name, v) 107 | + def __delattr__(self, name): return delattr(self._real, name) 108 | + 109 | + def setBody(self, body, title='', is_error=0, bogus_str_search=None): 110 | + # Marshall our body as an SOAP response. Strings will be sent 111 | + # strings, integers as integers, etc. We do *not* convert 112 | + # everything to a string first. 113 | + status = 200 114 | + if isinstance(body, Types.faultType): 115 | + status = 500 116 | + # Convert Fault object to SOAP response. 117 | + soapbody = Types.faulType("%s:Server" % NS.ENV_T, body) 118 | + body = buildSOAP(soapbody,encoding=None) 119 | + else: 120 | + try: 121 | + body = buildSOAP((body,),encoding=None) 122 | + except Exception,e: 123 | + self.exception() 124 | + return self 125 | + 126 | + t = 'text/xml' 127 | + # Set our body to the XML-RPC message, and fix our MIME type. 128 | + self._real.setBody(body) 129 | + self._real.setHeader('content-type', t) 130 | + self._real.setHeader("content-length", str(len(body))) 131 | + self._real.setStatus(status) 132 | + return self 133 | + 134 | + def exception(self, fatal=0, info=None, 135 | + absuri_match=None, tag_search=None): 136 | + # Fetch our exception info. t is type, v is value and tb is the 137 | + # traceback object. 138 | + 139 | + if type(info) is type(()) and len(info)==3: t,v,tb = info 140 | + else: t,v,tb = sys.exc_info() 141 | + LOG('SOAPException', TRACE, tb) 142 | + # Create an appropriate Fault object. Unfortunately, we throw away 143 | + # most of the debugging information. More useful error reporting is 144 | + # left as an exercise for the reader. 145 | + Fault=Types.faultType 146 | + f=None 147 | + try: 148 | + if isinstance(v, Fault): 149 | + f=v 150 | + elif isinstance(v, Exception): 151 | + f=Fault("%s:Server" % NS.ENV_T, 152 | + "Unexpected Zope exception: %s"%str(v)) 153 | + else: 154 | + f=Fault("%s:Server" % NS.ENV_T, 155 | + "Unexpected Zope error value: %s"%str(v)) 156 | + except: 157 | + f=Fault("%s:Server" % NS.ENV_T, 158 | + "Unknown Zope fault type") 159 | + 160 | + # Do the damage. 161 | + body = buildSOAP(f) 162 | + self._real.setBody(body) 163 | + self._real.setHeader('content-type', 'text/xml') 164 | + self._real.setStatus(500) 165 | + return tb 166 | + 167 | +response=SOAPResponse 168 | + 169 | + 170 | + 171 | + 172 | + 173 | + 174 | + 175 | + 176 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ============================================== 2 | SOAPpy - Simple to use SOAP library for Python 3 | ============================================== 4 | 5 | Current Maintainer: 6 | 7 | Gregory R. Warnes 8 | 9 | Original Authors: 10 | 11 | Cayce Ullman 12 | Brian Matthews 13 | 14 | Contributions by: 15 | 16 | Christopher Blunck 17 | Brad Knotwell 18 | Mark Bucciarelli (ported WSDL 19 | client from ZSI) 20 | Ivan R. Judson (Globus support) 21 | Kirk Strauser 22 | Antonio Beamud Montero (patches 23 | for integrating SOAPpy into Zope) 24 | And others. 25 | 26 | Copyright (c) 2002-2005, Pfizer, Inc. 27 | Copyright (c) 2001, Cayce Ullman. 28 | Copyright (c) 2001, Brian Matthews. 29 | All rights reserved, see the file LICENSE for conditions of use. 30 | 31 | INTRODUCTION 32 | ============ 33 | 34 | The goal of the SOAPpy team is to provide a full-featured SOAP library 35 | for Python that is very simple to use and that fully supports dynamic 36 | interaction between clients and servers. 37 | 38 | INCLUDED 39 | -------- 40 | 41 | - General SOAP Parser based on sax.xml 42 | - General SOAP Builder 43 | - SOAP Proxy for RPC client code 44 | - SOAP Server framework for RPC server code 45 | 46 | FEATURES 47 | -------- 48 | 49 | - Handles all SOAP 1.0 types 50 | - Handles faults 51 | - Allows namespace specification 52 | - Allows SOAPAction specification 53 | - Homogeneous typed arrays 54 | - Supports multiple schemas 55 | - Header support (mustUnderstand and actor) 56 | - XML attribute support 57 | - Multi-referencing support (Parser/Builder) 58 | - Understands SOAP-ENC:root attribute 59 | - Good interop, passes all client tests for Frontier, SOAP::LITE, SOAPRMI 60 | - Encodings 61 | - SSL clients (with Python compiled with OpenSSL support) 62 | - SSL servers (with Python compiled with OpenSSL support and M2Crypto 63 | installed) 64 | - Encodes XML tags per SOAP 1.2 name mangling specification (Gregory Warnes) 65 | - Automatic stateful SOAP server support (Apache v2.x) (blunck2) 66 | - WSDL client support 67 | - WSDL server support 68 | 69 | TODO (See RELEASE_INFO and CHANGELOG for recent changes) 70 | ---- 71 | 72 | - Timeout on method calls 73 | - Advanced arrays (sparse, multidimensional and partial) 74 | - Attachments 75 | - mod_python example 76 | - medusa example 77 | - Improved documentation 78 | 79 | MANIFEST 80 | -------- 81 | 82 | Files 83 | 84 | 85 | README This file 86 | RELEASE_NOTES General information about each release 87 | ChangeLog Detailed list of changes 88 | TODO List of tasks that need to be done 89 | 90 | setup.py Python installation control files 91 | MANIFEST 92 | MANIFEST.in 93 | 94 | SOAPpy.spec* RPM package control file 95 | 96 | Directories 97 | 98 | SOAPpy/* Source code for the package 99 | SOAPpy/wstools/* Source code for WSDL tools 100 | tests/* unit tests and examples 101 | validate/* interop client and servers 102 | bid/* N+I interop client and server 103 | doc/* Documentation 104 | contrib/ Contributed examples (also see test/) 105 | docs/ Documentation 106 | tools/ Misc tools useful for the SOAPpy developers 107 | zope/ Patches to Zope allowing it to provide SOAP services 108 | 109 | 110 | INSTALLATION 111 | ============ 112 | 113 | REQUIRED PACKAGES: 114 | ----------------- 115 | 116 | - fpconst 0.6.0 or later, available from PyPI: 117 | 118 | 119 | - pyXML 0.8.3 or later, 120 | 121 | OPTIONAL PACKAGES 122 | ----------------- 123 | 124 | - pyGlobus, optional support for Globus, 125 | 126 | 127 | - M2Crypto.SSL, optional support for server-side SSL 128 | 129 | 130 | - If Python is compiled with SSL support (Python 2.3 does so by 131 | default), client-side use of SSL is supported 132 | 133 | INSTALLATION STEPS 134 | ------------------ 135 | 136 | As of version 0.9.8 SOAPpy can be installed using the standard python 137 | package installation tools. 138 | 139 | To install: 140 | 141 | 1) Unpack the distribution package: 142 | 143 | On Windows, use your favorite zip file uncompression tool. 144 | 145 | On Unix: 146 | 147 | $ tar -xvzf SOAPpy-$VERSION$.tar.gz 148 | 149 | if you have gnu tar, otherwise 150 | 151 | $ gzcat SOAPpy-$VERSION$.tar.gz | tar -xvf - 152 | 153 | 2) Change into the source directory 154 | 155 | $ cd SOAPpy-$VERSION$ 156 | 157 | 3) Compile the package 158 | 159 | $ python setup.py build 160 | 161 | 4) Install the package 162 | 163 | On Windows: 164 | 165 | $ python setup.py install 166 | 167 | On Unix install as the owner of the python directories 168 | (usally root): 169 | 170 | $ su root 171 | Password: XXXXXX 172 | $ python setup.py install 173 | 174 | 175 | DOCUMENTATION 176 | ============= 177 | 178 | QUICK START 179 | ----------- 180 | 181 | A simple "Hello World" http SOAP server: 182 | 183 | import SOAPpy 184 | def hello(): 185 | return "Hello World" 186 | 187 | server = SOAPpy.SOAPServer(("localhost", 8080)) 188 | server.registerFunction(hello) 189 | server.serve_forever() 190 | 191 | And the corresponding client: 192 | 193 | import SOAPpy 194 | server = SOAPpy.SOAPProxy("http://localhost:8080/") 195 | print server.hello() 196 | 197 | BASIC TUTORIAL 198 | -------------- 199 | 200 | Mark Pilgrims' _Dive Into Python_, published in printed form by 201 | Apress and online at at http://diveintopython.org provides a 202 | nice tutorial for SOAPpy in Chapter 12, "SOAP Web Services". 203 | See http://diveintopython.org/soap_web_services . 204 | 205 | OTHER DOCUMENTATION 206 | ------------------- 207 | 208 | For further information see the files in the docs/ directory. 209 | 210 | Note that documentation is one of SOAPpy's current weak points. 211 | Please help us out! 212 | 213 | 214 | GETTING HELP 215 | ============ 216 | 217 | REPORTING BUGS 218 | -------------- 219 | 220 | Please submit bug reports, feature requests, patches, etc at the 221 | Python Web Services web site: http://pywebsvcs.sourceforge.net. 222 | 223 | MAILING LIST 224 | ============ 225 | 226 | Please address questions and general discussion to the 227 | pywebsvcs-talk mailing list, pywebsvcs-talk@lists.sourceforge.net. 228 | 229 | For subscription information visit 230 | http://lists.sourceforge.net/lists/listinfo/pywebsvcs-talk. 231 | List archives are available at 232 | http://sourceforge.net/mailarchive/forum.php?forum=pywebsvcs-talk 233 | 234 | Please remember that the authors do have day jobs, so please try 235 | the mailing list before contacting them directy. 236 | 237 | $Id$ 238 | -------------------------------------------------------------------------------- /SOAPpy/Config.py: -------------------------------------------------------------------------------- 1 | """ 2 | ################################################################################ 3 | # Copyright (c) 2003, Pfizer 4 | # Copyright (c) 2001, Cayce Ullman. 5 | # Copyright (c) 2001, Brian Matthews. 6 | # 7 | # All rights reserved. 8 | # 9 | # Redistribution and use in source and binary forms, with or without 10 | # modification, are permitted provided that the following conditions are met: 11 | # Redistributions of source code must retain the above copyright notice, this 12 | # list of conditions and the following disclaimer. 13 | # 14 | # Redistributions in binary form must reproduce the above copyright notice, 15 | # this list of conditions and the following disclaimer in the documentation 16 | # and/or other materials provided with the distribution. 17 | # 18 | # Neither the name of actzero, inc. nor the names of its contributors may 19 | # be used to endorse or promote products derived from this software without 20 | # specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 26 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | # 33 | ################################################################################ 34 | """ 35 | 36 | ident = '$Id$' 37 | from version import __version__ 38 | 39 | import socket 40 | from types import * 41 | 42 | from NS import NS 43 | 44 | ################################################################################ 45 | # Configuration class 46 | ################################################################################ 47 | 48 | class SOAPConfig: 49 | __readonly = ('SSLserver', 'SSLclient', 'GSIserver', 'GSIclient') 50 | 51 | def __init__(self, config = None, **kw): 52 | d = self.__dict__ 53 | 54 | if config: 55 | if not isinstance(config, SOAPConfig): 56 | raise AttributeError, \ 57 | "initializer must be SOAPConfig instance" 58 | 59 | s = config.__dict__ 60 | 61 | for k, v in s.items(): 62 | if k[0] != '_': 63 | d[k] = v 64 | else: 65 | # Setting debug also sets returnFaultInfo, 66 | # dumpHeadersIn, dumpHeadersOut, dumpSOAPIn, and dumpSOAPOut 67 | self.debug = 0 68 | self.dumpFaultInfo = 1 69 | # Setting namespaceStyle sets typesNamespace, typesNamespaceURI, 70 | # schemaNamespace, and schemaNamespaceURI 71 | self.namespaceStyle = '1999' 72 | self.strictNamespaces = 0 73 | self.typed = 1 74 | self.buildWithNamespacePrefix = 1 75 | self.returnAllAttrs = 0 76 | 77 | # Strict checking of range for floats and doubles 78 | self.strict_range = 0 79 | 80 | # Default encoding for dictionary keys 81 | self.dict_encoding = 'ascii' 82 | 83 | # New argument name handling mechanism. See 84 | # README.MethodParameterNaming for details 85 | self.specialArgs = 1 86 | 87 | # If unwrap_results=1 and there is only element in the struct, 88 | # SOAPProxy will assume that this element is the result 89 | # and return it rather than the struct containing it. 90 | # Otherwise SOAPproxy will return the struct with all the 91 | # elements as attributes. 92 | self.unwrap_results = 1 93 | 94 | # Automatically convert SOAP complex types, and 95 | # (recursively) public contents into the corresponding 96 | # python types. (Private subobjects have names that start 97 | # with '_'.) 98 | # 99 | # Conversions: 100 | # - faultType --> raise python exception 101 | # - arrayType --> array 102 | # - compoundType --> dictionary 103 | # 104 | self.simplify_objects = 0 105 | 106 | # Per-class authorization method. If this is set, before 107 | # calling a any class method, the specified authorization 108 | # method will be called. If it returns 1, the method call 109 | # will proceed, otherwise the call will throw with an 110 | # authorization error. 111 | self.authMethod = None 112 | 113 | # Globus Support if pyGlobus.io available 114 | try: 115 | from pyGlobus import io; 116 | d['GSIserver'] = 1 117 | d['GSIclient'] = 1 118 | except: 119 | d['GSIserver'] = 0 120 | d['GSIclient'] = 0 121 | 122 | 123 | # Server SSL support if M2Crypto.SSL available 124 | try: 125 | from M2Crypto import SSL 126 | d['SSLserver'] = 1 127 | except: 128 | d['SSLserver'] = 0 129 | 130 | # Client SSL support if socket.ssl available 131 | try: 132 | from socket import ssl 133 | d['SSLclient'] = 1 134 | except: 135 | d['SSLclient'] = 0 136 | 137 | for k, v in kw.items(): 138 | if k[0] != '_': 139 | setattr(self, k, v) 140 | 141 | def __setattr__(self, name, value): 142 | if name in self.__readonly: 143 | raise AttributeError, "readonly configuration setting" 144 | 145 | d = self.__dict__ 146 | 147 | if name in ('typesNamespace', 'typesNamespaceURI', 148 | 'schemaNamespace', 'schemaNamespaceURI'): 149 | 150 | if name[-3:] == 'URI': 151 | base, uri = name[:-3], 1 152 | else: 153 | base, uri = name, 0 154 | 155 | if type(value) == StringType: 156 | if NS.NSMAP.has_key(value): 157 | n = (value, NS.NSMAP[value]) 158 | elif NS.NSMAP_R.has_key(value): 159 | n = (NS.NSMAP_R[value], value) 160 | else: 161 | raise AttributeError, "unknown namespace" 162 | elif type(value) in (ListType, TupleType): 163 | if uri: 164 | n = (value[1], value[0]) 165 | else: 166 | n = (value[0], value[1]) 167 | else: 168 | raise AttributeError, "unknown namespace type" 169 | 170 | d[base], d[base + 'URI'] = n 171 | 172 | try: 173 | d['namespaceStyle'] = \ 174 | NS.STMAP_R[(d['typesNamespace'], d['schemaNamespace'])] 175 | except: 176 | d['namespaceStyle'] = '' 177 | 178 | elif name == 'namespaceStyle': 179 | value = str(value) 180 | 181 | if not NS.STMAP.has_key(value): 182 | raise AttributeError, "unknown namespace style" 183 | 184 | d[name] = value 185 | n = d['typesNamespace'] = NS.STMAP[value][0] 186 | d['typesNamespaceURI'] = NS.NSMAP[n] 187 | n = d['schemaNamespace'] = NS.STMAP[value][1] 188 | d['schemaNamespaceURI'] = NS.NSMAP[n] 189 | 190 | elif name == 'debug': 191 | d[name] = \ 192 | d['returnFaultInfo'] = \ 193 | d['dumpHeadersIn'] = \ 194 | d['dumpHeadersOut'] = \ 195 | d['dumpSOAPIn'] = \ 196 | d['dumpSOAPOut'] = value 197 | 198 | else: 199 | d[name] = value 200 | 201 | 202 | Config = SOAPConfig() 203 | --------------------------------------------------------------------------------