pax_global_header00006660000000000000000000000064123507770010014514gustar00rootroot0000000000000052 comment=cc9788d4ecbe1142c020f78cd10e6c8cbeddb756 SOAPpy-0.12.22/000077500000000000000000000000001235077700100127735ustar00rootroot00000000000000SOAPpy-0.12.22/.gitignore000066400000000000000000000000721235077700100147620ustar00rootroot00000000000000*.egg-info MANIFEST.in build/ dist/ setup.cfg venv/ *.pyc SOAPpy-0.12.22/CHANGES.txt000066400000000000000000000554471235077700100146230ustar00rootroot00000000000000CHANGELOG ===================== 0.12.22 (2014-06-20) -------------------- - proper usage of config property inside objects. [Davorin Kunstelj] - dump user defined types with handler functions (can be used to override dump of built-in types). [Davorin Kunstelj] 0.12.21 (2014-05-27) -------------------- - Dispatching custom objects, slots supported. [Davorin Kunstelj] 0.12.20 (2014-05-15) -------------------- - better version handling [kiorky] - display summary on pypi [kiorky] - non disclosed intermediate release to polish pypi output [kiorky] 0.12.6 (2014-05-15) ------------------- - fix cve CVE Request ---- SOAPpy 0.12.5 Multiple Vulnerabilities -- LOL part [kiorky] - fix cve CVE Request ---- SOAPpy 0.12.5 Multiple Vulnerabilities -- XXE part [kiorky] - Remove dependency on fpconst. - adding maptype [Sandro Knauß] - Support / (and other reserved characters) in the password. [Ionut Turturica] - Client.HTTPWithTimeout: fixed constructor's docstring and comments -named the diferences with respect to the overriden method -fixed wrong reference to class in module 'httplib' -added documentation of param 't[German Larrain - fixed module docstring location (all imports must be below them)[German Larrain]f - fix error "Bad types (class java.math.BigInteger -> class java.lang.Integer)" - Clayton Caetano de Sousa] 0.12.5 (2011-08-01) ------------------- - Fix for multi-dimensional arrays. [Ionut Turturica] - Credits 0.12.3 (2011-02-21) ------------------- - Fixed url 0.12.2 (2011-02-21) ------------------- - Fixed url 0.12.1 (2011-02-21) ------------------- - Forked intially from https://github.com/pelletier/SOAPpy - main interresting enhancements grabbed: - from __future__ imports must occur at the beginning of the file - try install requires - Grabbed others changeset from https://bitbucket.org/cmclaughlin/soappy-0.12.0/ (fpconst) - Grabbed others changeset from https://bitbucket.org/zeus/soappy (ssl key support) - Depend directly on wstools not to bundle a duplicated version. - Grabbed from original svn: - rpm spec file - tools/ - zope/ - bid/ - .cvsignore files - Make it proper packaged, specially toward setuptools. Release 0.12.0 of SOAPpy ------------------------ This release primarily foces on bug fixes. Primary changes: - Fixes for bug reports that have accumulated over the last year [ 916265] "Arrays of unicode do not serialize correctly (patch included)" [ 918216] "Parsing faults in SOAPpy 0.11.3" [ 925077] "SOAPpy prints out SOAP fault" (even when Config.debug is off). [1001646] "SOAPpy stomps headers when sending multirefs" [1001646] "SOAPpy stomps headers when sending multirefs. [1064233] "Bug fixes for complex types" [1064248] "Bugs in _asdict() and _asarray() in Types.py" [1078051] "Arrays of complex types (doc/lit)" [1096971] "Parse error: missing HTTP header 'Content-length'" [1106450] "Floats are truncated to 10 digits, causing precision loss" [1122991] "error from SOAPpy/Client.py for content_length evaluation?" - Fixes for 'rules' which allow control of the data types of *incoming* messages. As a consequence TCtest.py now passes all tests. - WSDL support has been improving, due to work on the 'wstools' module which is shared between ZSI and SOAPpy. - Some work has been done to improve documentation. Release 0.11.6 of SOAPpy ------------------------ Changes to URLs and email addresses in documentation. Release 0.11.5 of SOAPpy ------------------------ - Bug fixes - Fix string format error in fault handling Release 0.11.4 of SOAPpy ------------------------ - Bug fixes - SOAPpy/Server.py: Check if header information contains SOAPAction key before checking its value. - Fixes for generating SOAP from complexType arrays, contributed by antonio.beamud@linkend.com - Fixed bug that caused typedArrayTypes to lose their type information when rendered to SOAP and added corresponding test case. - New Features - Enhancements to fault handling: The faultType Faultstring is now a non-variable string (i.e. no nsmethod in it) so that it can be programmatically checked. In addition fault handlers can now be registered to handle specific types of faults. - SOAPpy/Server.py: Modified unregsiterObject function to take optional namespace/path args to be consistent with registerObject. - SOAPpy/Server.py: Added an unregisterObject function - Changes to allow SOAPBuilder so it can handle a 'raw' Python object. Release 0.11.2 of SOAPpy ------------------------ - News: Ivan R. Judson has joined the SOAPpy team. He is focused on Globus support but is also responsible for a lot of other work for this release, - Bug fixes: - Code in Types.py assumes nested scopes, so I added the proper import so this will work under python 2.2.x - Fixing namespace collision - Fixed handing of named arguments bug introduced in 0.11.1. - Fix memory leak when exceptions are raised. - Fix bug when content-length is not present in parsed SOAP message. - Fix bug #888345: Python 2.3 boolean type serialized as int - Fix bug #875977: no escaping of bad tagnames for NoneTypes - New features: - Improved Globus support and documentation. Thanks Ivan! - Added context handling - Changed the use of SOAPAction, it used to default to setting it to "", now it defaults to setting it to the method (not the nsmethod). There is a clause in Server.py that catches 'old style' SOAPActions (aka "") and sets them to the method. When this is confirmed to be what everyone wants and we decide it's alright to (possibly) break client/server interop, we can take the clause out of Server.py and just handle SOAPActions of "" as a possible error/warning. - Additional test code. - Raise a SOAPException instead of returning a SOAPpy.faultType when a SOAP Fault is encountered and simplify_objects is enabled. Release 0.11.1 of SOAPpy ------------------------ - Bug fixes: - Fixed bug [ 792258 ] "SOAPBuilder.SOAPBuilder.dump can catch wrong exceptions" in SOAPBuilder.dump() submitted by Greg Chapman (glchapman). - Changes suggested by Richard Au (richardau) to fix ssl support. See bug report [ 752882 ] "SSL SOAP Server no longer working." - Remove call to gentag from 'dump' and add to 'dump_float', per bug report [ 792600 ] "SOAPBuilder.SOAPBuilder.dump possibly should not call gentag" by Greg Chapman (glchapman). - Add a tests for handling of nil="true" and nil="false". This fixes bug [ pywebsvcs-Bugs-858168 ] 'xsi:nil="true" causes exception' reported by Robert Zimmermann (robertzett): - testClient1.py now works properly. It had been failing to start the server thread on the second unit test. It turned out that the variable 'quit' needed to be reset to zero after the SOAP server thread for the first unit test exited. With the solution of this problem testClient1 can now be extended to run unit tests of both client and server components. - Added 'strict' option to the WSDL class. If strict is true, a RuntimeException will be raised if an unrecogned message is recieved. If strict is false, a warning will be printed to the console, the message type will be added to the WSDL schema, and processing will continue. This is in response to the second half of bug report [ 817331 ] "Some WSDL.py changes", submitted by Rudolf Ruland. Release 0.11.0 of SOAPpy ------------------------ - New/Changed configuration settings: - Config.simplify_objects=1 now converts all SOAPpy objects into basic Python types (list, dictionary, tuple, double, float, etc.). By default, Config.simplify_objects=0 for backward compatibility. - Config.dict_encoding='ascii' converts the keys of dictionaries (e.g. created when Config.simplify_objects=1) to ascii == plain python strings instead of unicode strings. This variable can be set to any encoding known to string.encode(). - Config.strict_range=1 forces the SOAP parsing routines to perform range checks on recieved SOAP float and double objects. When Config.strict_range=0, the default, parsing does not perform range checking (except for detecting overflows, which always occurs). In either case, range checking is performed when generating SOAP float and double objects. - Fixes for WSDLProxy. - Scripts in the test/ directory - Verbose debugging messages have been turned off.. - SOAPtest.py now functions when Config.simplify_objects=1 - SOAPtest.py now sets Config.strict_range=1 so that range checks are be properly tested. - New README file listing what test scripts fail and why. - Initial support for Globus via pyGlobus contributed by Ivan R. Judson . Release 0.10.4 of SOAPpy ------------------------ Dramatic performance improvements for large data transfers. Release 0.10.1 of SOAPpy ------------------------ only minor changes 1) Code now uses a single file to store version number 2) Client and server now report 'SOAPpy' as the server/user-agent. 3) All test scripts now use the local SOAPpy source instead of the globally installed version. Release 0.10.0 of SOAPpy ------------------------ Enhancements: 1) The new name handling mechanism has been enabled by default. The primary purpose of this release is to allow users to test this to see if it causes problems. Please take the time to do so. If there are no problems reported by April 15, 2003, 0.9.9 will be released with this feature enabled by default. Note that running a client under an old release of SOAPpy and a server under this release will be likely to generate errors due to the different name handling mechanisms. 2) MS-Windows systems should now be fully supported. This required implementing a new module, ieee754, which provides functions for detecting and generating IEEE 754 special floating point values (+Inf, -Inf, NaN) which are not properly handled by the Windows implementation of the float() function. 3) Code reorganization: The huge file SOAPpy/SOAP.py (4,122 lines, 131K) has been split into 10 separate files. In addition code shared with ZSI has been moved into a separate subdirectory and a separate CVS module. 4) Fixed bug 678239 which caused loss of namespace information in the client. 5) Mark Bucciarelli's has ported client support for WSDL from ZSI, as well as providing a mechanism for SOAPpy servers to provide WSDL on properly structured .GET requests. 6) Added ThreadingSOAPServer which inherits from ThreadingTCPServer server so that multiple clients will be automatically multiplexed. VERSION 0.10.4 -------------- - Integrated a simple patch submitted by Erik Westra that dramatically improves parser performance. - WSDL tools now uses m2crypto for SSL if it's installed. - Various other WSDL changes. VERSION 0.10.3 -------------- - Removed import of obsoleted ieee753.py. Now use the fpconst module proposed by PEP 754, available from - SOAPpy should no longer depend on pyXML. VERSION 0.10.2 -------------- - Fixed client support for basic authentication - Fixed import error in Client.py - Improved Client parsing of namespaces to support stateful SOAP servers. VERSION 0.10.1 -------------- - Modified setup.py, Server.py, and Client.py to obtain SOAPpy version number from a new file, version.py. - SOAP server/user-agent is now to 'SOAPpy' instead of 'SOAP.py'. - Added ident string containing CVS version to all files that were lacking this. VERSION 0.10.0 -------------- CHANGES SINCE VERSION 0.9.9-pre5 - Major Change: The huge file SOAPpy/SOAP.py (4,122 lines, 131K) has been split into 10 separate files:: Client.py NS.py SOAPBuilder.py Utilities.py Config.py Parser.py Server.py Errors.py SOAP.py Types.py This should ease navigation and maintenance. - A new CVS module 'wstools' was created to hold code which is used by both ZSI and SOAPpy. While this module is stored separately in CVS, it will be distributed as an integral part of both ZSI and SOAPpy, and will be included as an 'internal' module by both. In the SOAPpy source, it lives in the directory SOAPpy/wstools. - The files XMLname.py, ieee754.py, have been moved into SOAPpy/wstools. - Added TODO file - Fix bug in getNS that caused loss of namespace by using better pattern matching to find the namespace in the SOAP message. Fixes bug 678239 - Added Mark Bucciarelli's patch to provide wsdl code on properly structured .GET requests to the server. - Added client support for WSDL, ported from ZSI by Mark Bucciarelli - Added ThreadingSOAPServer which inherits from ThreadingTCPServer server so that muliple clients will be automatically multiplexed. - Removed some files from /test for services that no longer exist. CHANGES SINCE VERSION 0.9.9-pre4 -------------------------------- - Added client support for WSDL, ported from ZSI by Mark Bucciarelli . CHANGES SINCE VERSION 0.9.9-pre3 -------------------------------- - Code shared between SOAPpy and ZSI now lives in SOAPpy/SOAPpy/wstools and is stored in a separate CVS package. This will allow ZSI and SOAPpy to keep these files synchronized. CHANGES SINCE VERSION 0.9.9-pre2 -------------------------------- - Fixed trivial compilation bug on Win32: Only define SOAPUnixSocketServer if the Unix domain sockets are supported CHANGES SINCE VERSION 0.9.9-pre1 -------------------------------- - Added request for nested scopes, should now work properly in python 2.1 with named argument calls. - Fixed bug caused by omission of the ieee754 module from __init__.py. - SOAPpy now provides a SOAPUnixSocketServer class, which uses a unix domain socket instead of a network TCP/IP socket for communication. A corresponding client will be provided in the future. [This class has not yet been tested.] CHANGES SINCE VERSION 0.9.8 --------------------------- - IEEE 754 floating point specials (Inf, -Inf, NaN) should now be properly and consistently handled on all platforms. Added code to explicitly check for and handle IEEE 754 floating point specials (Inf, -Inf, NaN). This replaces an ugly hack for systems whose python float() doesn't understand the strings "Inf", "NaN", etc. Floating point specials should now be properly handled on all operating systems. ***SOAPpy should now work properly on all versions of Microsoft Windows.*** A new module, ieee754 contains the functions required to detect and create NaN, Inf, and -Inf values. This module should be usable in other contexts. - *** The new argument handling method (via SOAPpy.SOAP.Config.specialArgs=1) is now enabled by default.*** - Changed all references to actzero.com in SOAP.py to pywebscvs.sf.net. - Fixed a bug where lists included as parameters to SOAP method calls were being incorrectly named 'Results' even when another name was given. CHANGES SINCE VERSION 0.9.7 --------------------------- - Modified structure to allow installation using Python distutils (i.e. setup.py). Access to the SOAPpy library now requires: from SOAPpy import SOAP - I (Gregory R. Warnes) have implemented an experimental and non-standard method of handling named and unnamed arguments. This mechanism is enabled in SOAPpy by setting SOAPpy.SOAP.Config.specialArgs=1. When enabled, parameters with names of the form _#### (i.e., matching the regexp "^_[0-9]+") are assumed to be unnamed parameters and are passed to the method in numeric order. All other parameters are assumed to be named and are passed using the xml tag id as the parameter name. Outgoing SOAP method calls now always generate names in this way--whether or not specialArgs is enabled--instead of using the pattern v#####. See the file README.MethodParameterNaming for more details. - Added noroot parameter to the SOAPBuilder and SOAPProxy objects in order to provide compatibility with an older version of EasySOAP (v0.2) that balked if the SOAP-ENC:root parameter was included.(Brad Knotwell) - Added support for namespace-rewriting (used by Apache v2.x SOAP server for error conditions as well as stateful communication) (Christopher Blunck) - Added string <-> str conversion for array types (Python 2.2+) (Christopher Blunck) - Added convenience method (invoke) to SOAPProxy that calls __call (not sure if it is necessary - feel free to remove if you want) (Christopher Blunck) - Python 'float' are equivalent to SOAP 'double'. Modified dump_float and dump_list to use SOAP type string 'double' appropriately. (Gregory R. Warnes) - Add basic authentication (Brad Knotwell) - Fixes to enable proper handling of SOAP faults by the client: - Fixed test of whether message content is text/xml when recieving a fault. - Added __call__ method to exception classes to match the current API. - The faultType.__repr__() method now print details if present (Gregory R. Warnes) - Added XMLnam.py which provides toXMLname() and fromXMLname() for properly encoding xml tag names per the SOAP 2.1 (draft) specification. (Gregory R. Warnes) - Added calls to toXMLname() and fromXMLname() so that tags names are properly encoded. This resolves bug [ 548785 ] 'Error passing dict keys containing space.' (Gregory R. Warnes) - Added code to cgi encode contents of tags when they are not a recognized type. Fixes bug [ 549551 ] 'Error when passing non-standard types'. (Gregory R. Warnes) - Added __init__.py, so that SOAPpy can be used like a standard python module. (Gregory R. Warnes) VERSION 0.9.7 (6/27/01) ----------------------- - Fixed the unamed ordered parameters bug - Added the ability to specify a http_proxy - Added a patch provided by Tim MiddelKoop to allow printing of proxy objects - Added the contrib directory and included a medusa implementation of a SOAP.py server by Ng Pheng Siong VERSION 0.9.6 (6/08/01) ----------------------- - The date and time types now check their initial values when the type is created, not when the data is marshalled. - The date and time types are now parsed and returned as tuples (for multi-element types) or scalars (for single element types) in UTC and thus can represent the entire range of SOAP dates. - If an element doesn't have a type but has a name with a namespace, the name is tried as the type. - Untyped compound types with more than one element and all the elements the same name are turned into an array when parsing. - When parsing a structType, elements with the same name are placed in a list instead of saving just the last one. _getItemsAsList can be used to get an element of a structure as a list, whether there was one or many occurances of the item. - Added schemaNamespace, schemaNamespaceURI, and namespaceStyle configuration options. namespaceStyle takes one of 1999, 2000, or 2001, and sets typesNamespace, typesNamespaceURI, schemaNamespace, and schemaNamespaceURI. - Normalized the type class names, replacing Compound with compoundType, Struct with structType, Header with headerType, Body with bodyType, Array with arrayType, TypedArray with typedArrayType, Fault with faultType, and urType with anyType. - Attributes now appear on an element itself instead of the element's parent. For elements parsed to builtin python types, the attributes are stored in a dictionary keyed by the element's python id. The dictionary is in the Context object, can be returned from parseSOAP*, and can be returned from method calls if the returnAllAttrs configuration option is set. - isinstance is used to check for a class, so classes can be subtyped. - An encoding of None can be specified to not include encoding information. - Problems with the SOAPProxy URL are now reported when the SOAPProxy instance is created instead of when the first method call is made. - The Binary, Boolean and DateTime types have been removed in favor of binaryType, booleanType, and dateTimeType. VERSION 0.9.5 (5/16/01) ----------------------- - Should parse and build all 1999, 2000, 2001, and SOAP-ENC datatypes. - Initial handling of multi-dimensional, partial, and sparse arrays. - Supports SSL clients (if Python built with OpenSSL). - Supports SSL servers (if M2Crypto installed). - Applies defaults to SOAPproxy URLs (nice for command-line tools). - Added the _SOAPContext object, gives registered server functions more info about the current call. - Now assumes that any type that isn't in a schema could be a struct. - Added the Config object, now config options can be set globally or on an individual call level. - Deprecated the DateTime, Binary and Boolean types, should now use dateTimeType, binaryType and booleanType. - Includes N+I interop suite. - Various bug fixes and improvements. VERSION 0.9 (5/01/01) ----------------------- - The Envelope now just contains definitions for namespaces actually used (Builder) - Namespace definitions are inherited by children but not siblings (Builder) - Further improved multi-reference parsing -- it handles circular references (Parser) - Added support for building recursive and circular types using references (Builder) - More types - Proper handling of overflow and underflow integral and floating point types (Parser) - More interop - Various bug fixes and improvements VERSION 0.8.5 (4/25/01) ----------------------- - buildSOAP, SOAPProxy, SOAPServer now taking encoding argument - Much improved multi-referencing (Parser) - Added base64 and dateTime to interop suite - Various bug fixes VERSION 0.8 (4/23/01) ----------------------- - Added more types - Early multi-referencing support (Parser) - Reorganized the parser, much cleaner now - Preserve whitepsace in strings (per the standard) - Full XML attribute support (Parser/Builder) - Object (de)serialization now maintains element order - Fixed the zero-length array problem - Made indentation uniform (spaces not tabs) - Made Header and Body work more like real structs - Changed the parseSOAP api, now returns the body structure, instead of a list of body elements - Changed the soapaction and namespaces for the interop server - New silabclient options - Initial encoding support VERSION 0.7 (4/19/01) ----------------------- - Fixed a bug that caused nothing to work with Python 2.1 - Float work arounds for WIN32 (others?) - DateTime parsing for WIN32 - Beginnings of XML attribute support - Better interop VERSION 0.6 (4/18/01) ----------------------- - Fixed numerous bugs (dateTime, float precision, Response Element, null strings) - Added more types - Homogeneous typed arrays - Added support for more schemas - Early Header support and mustUnderstand and actor - Added interop suite - Passes validator - Interop greatly improved, passes all client tests for Frontier, SOAP::LITE. VERSION 0.5 (4/17/01) ----------------------- - Initial public release SOAPpy-0.12.22/LICENSE000066400000000000000000000044061235077700100140040ustar00rootroot00000000000000============================================== SOAPpy - Simple to use SOAP library for Python ============================================== Current Maintainers: Gregory R. Warnes Christopher Blunck Original Authors: Cayce Ullman Brian Matthews Contributions by: Brad Knotwell Mark Bucciarelli (ported WSDL client from ZSI) Ivan R. Judson (Globus support) Kirk Strauser Antonio Beamud Montero (patches for integrating SOAPpy into Zope) Copyright (c) 2002-2003, Pfizer, Inc. Copyright (c) 2001, Cayce Ullman. Copyright (c) 2001, Brian Matthews. All rights reserved. LICENSE: ---------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of actzero, inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOAPpy-0.12.22/MANIFEST.in000066400000000000000000000003751235077700100145360ustar00rootroot00000000000000include *.txt *.cfg *.rst recursive-include validate * recursive-include contrib * recursive-include src * recursive-include tests * recursive-include tools * recursive-include zope * recursive-include docs * recursive-include bid * global-exclude *pyc SOAPpy-0.12.22/README.txt000066400000000000000000000142011235077700100144670ustar00rootroot00000000000000============================================== SOAPpy - Simple to use SOAP library for Python ============================================== .. contents:: Disclaimer ========== Please use `suds `_ rather than SOAPpy. SOAPpy is old and clamsy. Credits ======== Companies --------- |makinacom|_ * `Planet Makina Corpus `_ * `Contact us `_ .. |makinacom| image:: http://depot.makina-corpus.org/public/logo.gif .. _makinacom: http://www.makina-corpus.com Authors ------------ - Cayce Ullman - Brian Matthews - Gregory R. Warnes - Makina Corpus - Mathieu Le Marec - Pasquet Contributors ---------------- - Christopher Blunck - Brad Knotwell - Mark Bucciarelli (ported WSDL client from ZSI) - Ivan R. Judson (Globus support) - Kirk Strauser - Antonio Beamud Montero (patches for integrating SOAPpy into Zope) - And others. Copyright (c) 20011 Makina Corpus Copyright (c) 2002-2005, Pfizer, Inc. Copyright (c) 2001, Cayce Ullman. Copyright (c) 2001, Brian Matthews. All rights reserved, see the file LICENSE for conditions of use. INTRODUCTION ============== The goal of the SOAPpy team is to provide a full-featured SOAP library for Python that is very simple to use and that fully supports dynamic interaction between clients and servers. INCLUDED -------- - General SOAP Parser based on sax.xml - General SOAP Builder - SOAP Proxy for RPC client code - SOAP Server framework for RPC server code FEATURES -------- - Handles all SOAP 1.0 types - Handles faults - Allows namespace specification - Allows SOAPAction specification - Homogeneous typed arrays - Supports multiple schemas - Header support (mustUnderstand and actor) - XML attribute support - Multi-referencing support (Parser/Builder) - Understands SOAP-ENC:root attribute - Good interop, passes all client tests for Frontier, SOAP::LITE, SOAPRMI - Encodings - SSL clients (with Python compiled with OpenSSL support) - SSL servers (with Python compiled with OpenSSL support and M2Crypto installed) - Encodes XML tags per SOAP 1.2 name mangling specification (Gregory Warnes) - Automatic stateful SOAP server support (Apache v2.x) (blunck2) - WSDL client support - WSDL server support TODO (See RELEASE_INFO and CHANGELOG for recent changes) ---------------------------------------------------------- - Timeout on method calls - Advanced arrays (sparse, multidimensional and partial) - Attachments - mod_python example - medusa example - Improved documentation MANIFEST -------- :: Files README This file RELEASE_NOTES General information about each release ChangeLog Detailed list of changes TODO List of tasks that need to be done setup.py Python installation control files SOAPpy.spec RPM package control file Directories SOAPpy/ Source code for the package SOAPpy/wstools/ Source code for WSDL tools tests/ unit tests and examples validate/ interop client and servers bid/ N+I interop client and server contrib/ Contributed examples (also see test/) docs/ Documentation tools/ Misc tools useful for the SOAPpy developers zope/ Patches to Zope allowing it to provide SOAP services INSTALLATION ============ USING GITHUB ------------ You can install SOAPpy and its dependencies directly from GitHub using PIP: pip install -e "git+http://github.com/kiroky/SOAPpy.git@develop#egg=SOAPpy" REQUIRED PACKAGES ------------------ - wstools OPTIONAL PACKAGES ----------------- - pyGlobus, optional support for Globus, - M2Crypto.SSL, optional support for server-side SSL - If Python is compiled with SSL support (Python 2.3 does so by default), client-side use of SSL is supported INSTALLATION STEPS ------------------ As of version 0.9.8 SOAPpy can be installed using the standard python package installation tools. To install: 1) Unpack the distribution package: On Windows, use your favorite zip file uncompression tool. On Unix:: $ tar -xvzf SOAPpy-$VERSION$.tar.gz If you have gnu tar, otherwise :: $ gzcat SOAPpy-$VERSION$.tar.gz | tar -xvf - 2) Change into the source directory :: cd SOAPpy-$VERSION$ 3) Compile the package:: $ python setup.py build 4) Install the package On Windows:: $ python setup.py install On Unix install as the owner of the python directories (usally root):: $ su root Password: XXXXXX $ python setup.py install DOCUMENTATION ============= QUICK START ----------- A simple "Hello World" http SOAP server:: import SOAPpy def hello(): return "Hello World" server = SOAPpy.SOAPServer(("localhost", 8080)) server.registerFunction(hello) server.serve_forever() And the corresponding client:: import SOAPpy server = SOAPpy.SOAPProxy("http://localhost:8080/") print server.hello() BASIC TUTORIAL -------------- Mark Pilgrims _Dive Into Python, published in printed form by Apress and online at at http://diveintopython.org provides a nice tutorial for SOAPpy in Chapter 12, "SOAP Web Services". See http://diveintopython.org/soap_web_services . OTHER DOCUMENTATION ------------------- For further information see the files in the docs/ directory. Note that documentation is one of SOAPpy's current weak points. Please help us out! Support ============ Github: https://github.com/kiorky/SOAPpy Issues: https://github.com/kiorky/SOAPpy/issues SOAPpy-0.12.22/SOAPpy.spec000066400000000000000000000055051235077700100147670ustar00rootroot00000000000000Summary: SOAPpy Name: SOAPpy Version: 0.9.7 Release: 2 License: Copyright (c) 2001, Cayce Ullman. Group: Productivity/Networking/Web/Applications Source: SOAPpy-%{version}.tgz Requires: python >= 2.2 BuildArch: noarch AutoReq: no Packager: Antonio Beamud Montero %description SOAP implementation by Cayce Ullman and Brian Matthews. %prep %setup SOAPpy-%{version} %build %install mkdir -p /usr/share/doc/SOAPpy/bid cp -a bid/* /usr/share/doc/SOAPpy/bid mkdir -p /usr/share/doc/SOAPpy/tests cp -a tests/* /usr/share/doc/SOAPpy/tests cp -a TCtest.py /usr/share/doc/SOAPpy/tests mkdir -p /usr/share/doc/SOAPpy/contrib cp contrib/* /usr/share/doc/SOAPpy/contrib/ cp docs/* /usr/share/doc/SOAPpy/ mkdir -p /usr/share/doc/SOAPpy/tools cp -a tools/* /usr/share/doc/SOAPpy/tools cp README /usr/share/doc/SOAPpy/ cp echoServer.py /usr/share/doc/SOAPpy/ cp speedTest.py /usr/share/doc/SOAPpy/ cp CHANGELOG /usr/share/doc/SOAPpy/ cp SOAPtest.py /usr/share/doc/SOAPpy/tests cp excelTest.py /usr/share/doc/SOAPpy/ cp echoClient.py /usr/share/doc/SOAPpy/ mkdir -p /usr/share/doc/SOAPpy/validate cp -a validate/* /usr/share/doc/SOAPpy/validate cp SOAP.py /usr/lib/python/site-packages/ %clean %pre %post %preun %postun %files %defattr(-,root,root) /usr/share/doc/SOAPpy/bid/monitorClient.py /usr/share/doc/SOAPpy/bid/inventoryServer.py /usr/share/doc/SOAPpy/bid/inventory.servers /usr/share/doc/SOAPpy/bid/inventoryClient.py /usr/share/doc/SOAPpy/tests/TCtest.py /usr/share/doc/SOAPpy/simpleTypes.txt /usr/share/doc/SOAPpy/attrs.txt /usr/share/doc/SOAPpy/quickstart.txt /usr/share/doc/SOAPpy/complexTypes.txt /usr/share/doc/SOAPpy/contrib/soap_cli.py /usr/share/doc/SOAPpy/contrib/soap_handler.py /usr/share/doc/SOAPpy/tests/cardServer.py /usr/share/doc/SOAPpy/tests/guidTest.py /usr/share/doc/SOAPpy/tests/alanbushTest.py /usr/share/doc/SOAPpy/tests/newsTest.py /usr/share/doc/SOAPpy/tests/weatherTest.py /usr/share/doc/SOAPpy/tests/fortuneTest.py /usr/share/doc/SOAPpy/tests/cardClient.py /usr/share/doc/SOAPpy/tests/quoteTest.py /usr/share/doc/SOAPpy/tests/storageTest.py /usr/share/doc/SOAPpy/tests/wordFindTest.py /usr/share/doc/SOAPpy/tests/itimeTest.py /usr/share/doc/SOAPpy/tests/whoisTest.py /usr/share/doc/SOAPpy/tests/translateTest.py /usr/share/doc/SOAPpy/tools/interop2html.py /usr/share/doc/SOAPpy/README /usr/share/doc/SOAPpy/echoServer.py /usr/share/doc/SOAPpy/speedTest.py /usr/share/doc/SOAPpy/CHANGELOG /usr/share/doc/SOAPpy/tests/SOAPtest.py /usr/share/doc/SOAPpy/excelTest.py /usr/share/doc/SOAPpy/echoClient.py /usr/share/doc/SOAPpy/validate/silab.servers /usr/share/doc/SOAPpy/validate/silabserver.py /usr/share/doc/SOAPpy/validate/server.pem /usr/share/doc/SOAPpy/validate/silabclient.py /usr/share/doc/SOAPpy/validate/soapware.py /usr/lib/python2.2/site-packages/SOAP.pySOAPpy-0.12.22/TODO000066400000000000000000000005361235077700100134670ustar00rootroot00000000000000# $Id: TODO,v 1.6 2003/12/23 10:19:12 warnes Exp $ - figure out why parsing rules are broken - generate a test harness that will run all of the test code. - create unit-tests for all features, as well as for reported bugs. - write better documentation (!!!) - topics: WSDL, Globus, Authentication, ... - general introduction article - ... SOAPpy-0.12.22/bid/000077500000000000000000000000001235077700100135315ustar00rootroot00000000000000SOAPpy-0.12.22/bid/.cvsignore000066400000000000000000000000061235077700100155250ustar00rootroot00000000000000*.pyc SOAPpy-0.12.22/bid/inventory.servers000066400000000000000000000065111235077700100172040ustar00rootroot00000000000000# This list of servers was taken from the SOAPBuilders Interoperability Lab # (http://www.xmethods.net/ilab/ilab.html) 4/23/01. # # $Id: inventory.servers 4 2001-06-27 21:36:11Z cullman $ Name: MST Bid (Microsoft SOAP Toolkit 2.0, Microsoft Windows 2000) Endpoint: http://131.107.72.13/stk/Bid.wsdl SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: KeithBa's BidBuy Service (.NET Web Services) Endpoint: http://131.107.72.13/test/bidbuy/bidbuy.asmx SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://soapinterop.org/xsd Name: JHawk's BidBuyService (.NET Remoting, Win2K) Endpoint: http://131.107.72.13/DotNetRemotingNI/BidBuy.soap SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid #Name: Idoox WASP #Endpoint: http://soap.idoox.net:8888/soap/servlet/Bid/ #SOAPAction: "http://www.soapinterop.org/%(methodname)s" #Namespace: http://www.soapinterop.org/Bid Name: Paul's Quick Bid (SOAP::Lite) Endpoint: http://services.soaplite.com/tradeit.cgi SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: Phalanx Bid Service Endpoint: http://www.phalanxsys.com/ni/listener.asp SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid Nonfunctional: Buy admitted problem with the wsdl Name: PranishK's BidBuy Service (ATL Web Service) Endpoint: http://www.mssoapinterop.org/atls_soap/bidbuy.dll?Handler=Default SOAPAction: "#%(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: GLUE Bid Endpoint: http://209.61.190.164:8004/glue/http://www.soapinterop.org/Bid SOAPAction: "http://www.soapinterop.org/Bid#(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: Aumsoft's BidBuy Endpoint: http://soap.aumsoft.com:8080/soap/BidBuy SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: SOAP.py 0.9 (actzero.com) Endpoint: http://208.177.157.221:12080/xmethodsInterop SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: HP SOAP Endpoint: http://soap.bluestone.com/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/BidBuy SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: EasySoap++ Bid Service (San Diego) Endpoint: http://easysoap.no-ip.com:8080/cgi-bin/bidbuyservice SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid Name: Jake's Frontier 7.0b43 Bid Service (Santa Clara, CA) Endpoint: http://www.soapware.org/BidBuy SOAPAction: "http://www.soapinterop.org/%(methodname)s" Namespace: http://www.soapinterop.org/Bid #Name: Pete's Clear Bids (CapeConnect/Win2000) #Endpoint: http://208.46.17.81/ccx/SOAPServlet #SOAPAction: "http://www.soapinterop.org/%(methodname)s" #Namespace: http://www.soapinterop.org/Bid #Name: (PranishK's) ATL Server BidBuy #Endpoint: http://208.46.17.121/bidbuy/bidbuy.dll?Handler=Default #SOAPAction: "http://www.soapinterop.org/%(methodname)s" #Namespace: http://www.soapinterop.org/Bid #Name: HP-SOAP @ N+I #Endpoint: http://208.46.17.112/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/BidBuy #SOAPAction: "http://www.soapinterop.org/%(methodname)s" #Namespace: http://www.soapinterop.org/Bid SOAPpy-0.12.22/bid/inventoryClient.py000077500000000000000000000215131235077700100173040ustar00rootroot00000000000000#!/usr/bin/env python import getopt import sys import string import re import time sys.path.insert(1,"..") from SOAPpy import SOAP import traceback DEFAULT_SERVERS_FILE = './inventory.servers' DEFAULT_METHODS = ('SimpleBuy', 'RequestForQuote','Buy','Ping') def usage (error = None): sys.stdout = sys.stderr if error != None: print error print """usage: %s [options] [server ...] If a long option shows an argument is mandatory, it's mandatory for the equivalent short option also. -?, --help display this usage -d, --debug turn on debugging in the SOAP library -i, --invert test servers *not* in the list of servers given -m, --method=METHOD#[,METHOD#...] call only the given methods, specify a METHOD# of ? for the list of method numbers -o, --output=TYPE turn on output, TYPE is one or more of s(uccess), f(ailure), n(ot implemented), F(ailed (as expected)), a(ll) [f] -s, --servers=FILE use FILE as list of servers to test [%s] -t, --stacktrace print a stack trace on each unexpected failure -T, --always-stacktrace print a stack trace on any failure """ % (sys.argv[0], DEFAULT_SERVERS_FILE), sys.exit (0) def methodUsage (): sys.stdout = sys.stderr print "Methods are specified by number. Multiple methods can be " \ "specified using a\ncomma-separated list of numbers or ranges. " \ "For example 1,4-6,8 specifies\nmethods 1, 4, 5, 6, and 8.\n" print "The available methods are:\n" half = (len (DEFAULT_METHODS) + 1) / 2 for i in range (half): print "%4d. %-25s" % (i + 1, DEFAULT_METHODS[i]), if i + half < len (DEFAULT_METHODS): print "%4d. %-25s" % (i + 1 + half, DEFAULT_METHODS[i + half]), print sys.exit (0) def readServers (file): servers = [] f = open (file, 'r') while 1: line = f.readline () if line == '': break if line[0] in ('#', '\n') or line[0] in string.whitespace: continue cur = {'nonfunctional': {}} tag = None servers.append (cur) while 1: if line[0] in string.whitespace: if tag == 'nonfunctional': value = method + ' ' + cur[tag][method] else: value = cur[tag] value += ' ' + line.strip () else: tag, value = line.split (':', 1) tag = tag.strip ().lower () value = value.strip () if value[0] == '"' and value[-1] == '"': value = value[1:-1] if tag == 'nonfunctional': value = value.split (' ', 1) + [''] method = value[0] cur[tag][method] = value[1] else: cur[tag] = value line = f.readline () if line == '' or line[0] == '\n': break return servers def str2list (s): l = {} for i in s.split (','): if i.find ('-') != -1: i = i.split ('-') for i in range (int (i[0]),int (i[1]) + 1): l[i] = 1 else: l[int (i)] = 1 l = l.keys () l.sort () return l def SimpleBuy(serv, sa, epname): serv = serv._sa (sa % {'methodname':'SimpleBuy'}) return serv.SimpleBuy(ProductName="widget", Quantity = 50, Address = "this is my address") #JHawk, Phalanx require this order of params def RequestForQuote(serv, sa, epname): serv = serv._sa (sa % {'methodname':'RequestForQuote'}) return serv.RequestForQuote(Quantity=3, ProductName = "thing") # for Phalanx, JHawk def Buy(serv, sa, epname): import copy serv = serv._sa (sa % {'methodname':'Buy'}) billTo_d = {"name":"Buyer One", "address":"1 1st Street", "city":"New York", "state":"NY", "zipCode":"10000"} shipTo_d = {"name":"Buyer One ", "address":"1 1st Street ", "city":"New York ", "state":"NY ", "zipCode":"10000 "} for k,v in shipTo_d.items(): shipTo_d[k] = v[:-1] itemd1 = SOAP.structType( {"name":"widg1","quantity":200,"price":SOAP.decimalType(45.99), "_typename":"LineItem"}) itemd2 = SOAP.structType( {"name":"widg2","quantity":400,"price":SOAP.decimalType(33.45), "_typename":"LineItem"}) items_d = SOAP.arrayType( [itemd1, itemd2] ) items_d._ns = "http://www.soapinterop.org/Bid" po_d = SOAP.structType( data = {"poID":"myord","createDate":SOAP.dateTimeType(),"shipTo":shipTo_d, "billTo":billTo_d, "items":items_d}) try: # it's called PO by MST (MS SOAP Toolkit), JHawk (.NET Remoting), # Idoox WASP, Paul (SOAP::Lite), PranishK (ATL), GLUE, Aumsoft, # HP, EasySoap, and Jake (Frontier). [Actzero accepts either] return serv.Buy(PO=po_d) except: # called PurchaseOrder by KeithBa return serv.Buy(PurchaseOrder=po_d) def Ping(serv, sa, epname): serv = serv._sa (sa % {'methodname':'Ping'}) return serv.Ping() def main(): servers = DEFAULT_SERVERS_FILE methodnums = None output = 'f' invert = 0 succeed = 0 printtrace = 0 stats = 1 total = 0 fail = 0 failok = 0 notimp = 0 try: opts,args = getopt.getopt (sys.argv[1:], '?dm:io:s:t', ['help', 'method', 'debug', 'invert', 'output', 'servers=']) for opt, arg in opts: if opt in ('-?', '--help'): usage () elif opt in ('-d', '--debug'): SOAP.Config.debug = 1 elif opt in ('-i', '--invert'): invert = 1 elif opt in ('-m', '--method'): if arg == '?': methodUsage () methodnums = str2list (arg) elif opt in ('-o', '--output'): output = arg elif opt in ('-s', '--servers'): servers = arg else: raise AttributeError, \ "Recognized but unimplemented option `%s'" % opt except SystemExit: raise except: usage (sys.exc_info ()[1]) if 'a' in output: output = 'fFns' servers = readServers(servers) if methodnums == None: methodnums = range (1, len (DEFAULT_METHODS) + 1) limitre = re.compile ('|'.join (args), re.IGNORECASE) for s in servers: if (not not limitre.match (s['name'])) == invert: continue serv = SOAP.SOAPProxy(s['endpoint'], namespace = s['namespace']) for num in (methodnums): if num > len(DEFAULT_METHODS): break total += 1 name = DEFAULT_METHODS[num - 1] title = '%s: %s (#%d)' % (s['name'], name, num) try: fn = globals ()[name] except KeyboardInterrupt: raise except: if 'n' in output: print title, "test not yet implemented" notimp += 1 continue try: res = fn (serv, s['soapaction'], s['name']) if s['nonfunctional'].has_key (name): print title, "succeeded despite marked nonfunctional" elif 's' in output: print title, "succeeded " succeed += 1 except KeyboardInterrupt: print "fail" raise except: if s['nonfunctional'].has_key (name): if 'F' in output: t = 'as expected' if s['nonfunctional'][name] != '': t += ', ' + s['nonfunctional'][name] print title, "failed (%s) -" %t, sys.exc_info()[1] failok += 1 else: if 'f' in output: print title, "failed -", str (sys.exc_info()[1]) fail += 1 if stats: print " Tests ended at:", time.ctime (time.time()) if stats > 0: print " Total tests: %d" % total print " Successes: %d (%3.2f%%)" % \ (succeed, 100.0 * succeed / total) if stats > 0 or fail > 0: print "Failed unexpectedly: %d (%3.2f%%)" % \ (fail, 100.0 * fail / total) if stats > 0: print " Failed as expected: %d (%3.2f%%)" % \ (failok, 100.0 * failok / total) if stats > 0 or notimp > 0: print " Not implemented: %d (%3.2f%%)" % \ (notimp, 100.0 * notimp / total) return fail + notimp if __name__ == "__main__": main() SOAPpy-0.12.22/bid/inventoryServer.py000077500000000000000000000105671235077700100173430ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001, actzero, inc. import sys sys.path.insert(1,"..") from SOAPpy import SOAP #SOAP.Config.debug = 1 serverstring = "SOAP.py (actzero.com) running "+sys.platform NUMBUYS = 0 NUMSIMPLEBUYS = 0 NUMREQUESTS = 0 NUMPINGS = 0 def SimpleBuy(Address, ProductName, Quantity): # currently, this type-checks the params, and makes sure # the strings are of len > 0 global NUMSIMPLEBUYS NUMSIMPLEBUYS += 1 if Quantity < 1: raise ValueError, "must order at least one" else: return "Receipt for %d %s(s) bought from %s" % (int(Quantity), ProductName, serverstring) def RequestForQuote(ProductName, Quantity): # type-checks and makes sure Quantity >= 1 global NUMREQUESTS NUMREQUESTS += 1 if Quantity < 1: raise ValueError, "must order at least 1" else: import whrandom mult = whrandom.random() times = 0 while mult > 0.25: mult = mult - 0.25 times += 1 mult += 0.5 mult = round(mult, 3) print mult, times return SOAP.doubleType(round(mult*int(Quantity),2)) def Buy(**kw): global NUMBUYS NUMBUYS += 1 try: PurchaseOrder = kw["PurchaseOrder"] except: PurchaseOrder = kw["PO"] try: POkeys = PurchaseOrder['_keyord'] POkeys.sort() POkeys_expected = ["shipTo","billTo","items","poID","createDate"] POkeys_expected.sort() if POkeys != POkeys_expected: raise ValueError, "struct 'PurchaseOrder' needs %s, %s, %s, %s, and %s" % tuple(POkeys_expected) except: raise TypeError, "'PurchaseOrder' missing one or more element(s)" try: btkeys = PurchaseOrder["billTo"]["_keyord"] btkeys.sort() btkeys_expected = ["address","zipCode","name","state","city"] btkeys_expected.sort() except: raise TypeError, "'billTo' missing one or more elements" try: stkeys = PurchaseOrder["shipTo"]["_keyord"] stkeys.sort() stkeys_expected = ["address","zipCode","name","state","city"] stkeys_expected.sort() except: raise TypeError, "'shipTo' missing one or more elements" try: items = PurchaseOrder["items"].__dict__ data = items["data"] retstring = "" for item in data: itemdict = item["_asdict"] q = itemdict["quantity"] p = itemdict["price"] name = itemdict["name"] if retstring != "": retstring += ", " else: retstring = "bought " retstring += "%d %s(s) for %.2f" % (q,name,p) retstring += " from "+serverstring return retstring except: raise TypeError, "items must be an array of 'item' structs" def Ping(): global NUMPINGS NUMPINGS += 1 return def Monitor(str): if str=="actzero": global NUMBUYS global NUMREQUESTS global NUMSIMPLEBUYS global NUMPINGS return "(Buys, RequestForQuote(s),SimpleBuy(s), Ping(s)) = " + \ repr( (NUMBUYS,NUMREQUESTS,NUMSIMPLEBUYS, NUMPINGS) ) else: raise ValueError, "not the right string" def Clear(str): if str=="actzero": global NUMBUYS global NUMREQUESTS global NUMSIMPLEBUYS global NUMPINGS NUMBUYS = 0 NUMREQUESTS = 0 NUMSIMPLEBUYS = 0 NUMPINGS = 0 return "(Buys, RequestForQuote(s),SimpleBuy(s), Ping(s)) = " + \ repr( (NUMBUYS,NUMREQUESTS,NUMSIMPLEBUYS, NUMPINGS) ) else: raise ValueError, "not the right string" if __name__ == "__main__": if len(sys.argv) > 1: try: port = int(sys.argv[1]) if port not in range(2000,15000): raise ValueError except: print "port must be a number between 2000 and 15000" sys.exit(1) else: port = 9000 namespace = "http://www.soapinterop.org/Bid" server = SOAP.SOAPServer( ('zoo',port) ) server.registerKWFunction(SimpleBuy, namespace ) server.registerKWFunction(RequestForQuote, namespace ) server.registerKWFunction(Buy, namespace ) server.registerKWFunction(Ping, namespace ) server.registerKWFunction(Monitor, namespace ) server.registerKWFunction(Clear, namespace ) try: server.serve_forever() except KeyboardInterrupt: pass SOAPpy-0.12.22/bid/monitorClient.py000077500000000000000000000022301235077700100167310ustar00rootroot00000000000000from SOAPpy import SOAP import sys import getopt def usage(): print """usage: %s [options] -m, --method=METHOD#[,METHOD#...] specify METHOD# of ? for the list -p, --port=PORT# allows to specify PORT# of server """ sys.exit(1) def methodUsage(): print "The available methods are:" print "1. Monitor \t\t2. Clear" sys.exit(0) port = 12080 methodnum = 1 try: opts, args = getopt.getopt (sys.argv[1:], 'p:m:', ['method','port']) for opt, arg in opts: if opt in ('-m','--method'): if arg == '?': methodUsage() methodnum = int(arg) elif opt in ('-p', '--port'): port = int(arg) else: raise AttributeError, "Recognized but unimpl option '%s'" % opt except SystemExit: raise except: usage () ep = "http://208.177.157.221:%d/xmethodsInterop" % (port) sa = "urn:soapinterop" ns = "http://www.soapinterop.org/Bid" serv = SOAP.SOAPProxy(ep, namespace =ns, soapaction = sa) if methodnum == 1: print serv.Monitor(str="actzero") elif methodnum == 2: print serv.Clear(str="actzero") else: print "invalid methodnum" methodUsage() SOAPpy-0.12.22/contrib/000077500000000000000000000000001235077700100144335ustar00rootroot00000000000000SOAPpy-0.12.22/contrib/.cvsignore000066400000000000000000000000061235077700100164270ustar00rootroot00000000000000*.pyc SOAPpy-0.12.22/contrib/soap_cli.py000077500000000000000000000005141235077700100166010ustar00rootroot00000000000000#!/usr/bin/env python import time from SOAPpy import SOAP srv = SOAP.SOAPProxy('http://localhost:10080/') for p in ('good param', 'ok param'): ret = srv.badparam(p) if isinstance(ret, SOAP.faultType): print ret else: print 'ok' dt = SOAP.dateTimeType(time.localtime(time.time())) print srv.dt(dt) SOAPpy-0.12.22/contrib/soap_handler.py000077500000000000000000000176431235077700100174620ustar00rootroot00000000000000 import http_server from SOAPpy.SOAP import * Fault = faultType import string, sys Config = SOAPConfig(debug=1) class soap_handler: def __init__(self, encoding='UTF-8', config=Config, namespace=None): self.namespace = namespace self.objmap = {} self.funcmap = {} self.config = config self.encoding = encoding def match (self, request): return 1 def handle_request (self, request): [path, params, query, fragment] = request.split_uri() if request.command == 'post': request.collector = collector(self, request) else: request.error(400) def continue_request(self, data, request): # Everthing that follows is cripped from do_POST(). if self.config.debug: print "\n***RECEIVING***\n", data, "*" * 13 + "\n" sys.stdout.flush() try: r, header, body = parseSOAPRPC(data, header=1, body=1) method = r._name args = r._aslist kw = r._asdict ns = r._ns resp = "" # For faults messages if ns: nsmethod = "%s:%s" % (ns, method) else: nsmethod = method try: # First look for registered functions if self.funcmap.has_key(ns) and \ self.funcmap[ns].has_key(method): f = self.funcmap[ns][method] else: # Now look at registered objects # Check for nested attributes if method.find(".") != -1: t = self.objmap[ns] l = method.split(".") for i in l: t = getattr(t,i) f = t else: f = getattr(self.objmap[ns], method) except: if self.config.debug: import traceback traceback.print_exc () resp = buildSOAP(Fault("%s:Client" % NS.ENV_T, "No method %s found" % nsmethod, "%s %s" % tuple(sys.exc_info()[0:2])), encoding = self.encoding, config = self.config) status = 500 else: try: # If it's wrapped to indicate it takes keywords # send it keywords if header: x = HeaderHandler(header) if isinstance(f,MethodSig): c = None if f.context: # Build context object c = SOAPContext(header, body, d, self.connection, self.headers, self.headers["soapaction"]) if f.keywords: tkw = {} # This is lame, but have to de-unicode keywords for (k,v) in kw.items(): tkw[str(k)] = v if c: tkw["_SOAPContext"] = c fr = apply(f,(),tkw) else: if c: fr = apply(f,args,{'_SOAPContext':c}) else: fr = apply(f,args,{}) else: fr = apply(f,args,{}) if type(fr) == type(self) and isinstance(fr, voidType): resp = buildSOAP(kw = {'%sResponse' % method:fr}, encoding = self.encoding, config = self.config) else: resp = buildSOAP(kw = {'%sResponse' % method:{'Result':fr}}, encoding = self.encoding, config = self.config) except Fault, e: resp = buildSOAP(e, config = self.config) status = 500 except: if self.config.debug: import traceback traceback.print_exc () resp = buildSOAP(Fault("%s:Server" % NS.ENV_T, \ "Method %s failed." % nsmethod, "%s %s" % tuple(sys.exc_info()[0:2])), encoding = self.encoding, config = self.config) status = 500 else: status = 200 except Fault,e: resp = buildSOAP(e, encoding = self.encoding, config = self.config) status = 500 except: # internal error, report as HTTP server error if self.config.debug: import traceback traceback.print_exc () request.error(500) #self.send_response(500) #self.end_headers() else: request['Content-Type'] = 'text/xml; charset="%s"' % self.encoding request.push(resp) request.done() # got a valid SOAP response #self.send_response(status) #self.send_header("Content-type", # 'text/xml; charset="%s"' % self.encoding) #self.send_header("Content-length", str(len(resp))) #self.end_headers() if self.config.debug: print "\n***SENDING***\n", resp, "*" * 13 + "\n" sys.stdout.flush() """ # We should be able to shut down both a regular and an SSL # connection, but under Python 2.1, calling shutdown on an # SSL connections drops the output, so this work-around. # This should be investigated more someday. if self.config.SSLserver and \ isinstance(self.connection, SSL.Connection): self.connection.set_shutdown(SSL.SSL_SENT_SHUTDOWN | SSL.SSL_RECEIVED_SHUTDOWN) else: self.connection.shutdown(1) """ def registerObject(self, object, namespace = ''): if namespace == '': namespace = self.namespace self.objmap[namespace] = object def registerFunction(self, function, namespace = '', funcName = None): if not funcName : funcName = function.__name__ if namespace == '': namespace = self.namespace if self.funcmap.has_key(namespace): self.funcmap[namespace][funcName] = function else: self.funcmap[namespace] = {funcName : function} class collector: "gathers input for POST and PUT requests" def __init__ (self, handler, request): self.handler = handler self.request = request self.data = '' # make sure there's a content-length header cl = request.get_header ('content-length') if not cl: request.error (411) else: cl = string.atoi (cl) # using a 'numeric' terminator self.request.channel.set_terminator (cl) def collect_incoming_data (self, data): self.data = self.data + data def found_terminator (self): # set the terminator back to the default self.request.channel.set_terminator ('\r\n\r\n') self.handler.continue_request (self.data, self.request) if __name__ == '__main__': import asyncore import http_server class Thing: def badparam(self, param): if param == 'good param': return 1 else: return Fault(faultstring='bad param') def dt(self, aDateTime): return aDateTime thing = Thing() soaph = soap_handler() soaph.registerObject(thing) hs = http_server.http_server('', 10080) hs.install_handler(soaph) asyncore.loop() SOAPpy-0.12.22/docs/000077500000000000000000000000001235077700100137235ustar00rootroot00000000000000SOAPpy-0.12.22/docs/GettingStarted.txt000066400000000000000000000120401235077700100174110ustar00rootroot00000000000000 Getting Started =============== NEW: Mark Pilgrims' online book _Dive Into Python_ at http://diveintopython.org includes a nice tutorial for SOAPpy in Chapter 12. "SOAP Web Services" at http://diveintopython.org/soap_web_services. The easiest way to get up to speed is to run and read the scripts in the tests directory. Better documentation is coming. Here are some examples of how to use SOAPpy: CLIENT EXAMPLES: ## CODE from SOAPpy import SOAPProxy server = SOAPProxy("http://localhost:8080/") print server.echo("Hello world") ## /CODE This opens a connection to the server listening on localhost:8080, calls the method echo with the ordered parameter of "Hello World", and prints the results. ## CODE from SOAPpy import SOAPProxy server = SOAPProxy("https://localhost:8443/") print server.echo("Hello world") ## /CODE This opens a secure connection to the SSL server listening on localhost:8443, calls the method echo with the ordered parameter of "Hello World" and prints the results. Python must be built with OpenSSL. ## CODE from SOAPpy import SOAPProxy server = SOAPProxy("http://services.xmethods.com/soap", namespace = "urn:xmethods-delayed-quotes") print server.getQuote(symbol = "IBM") ## /CODE This calls method getQuote that is in the namespace URI of urn:xmethods-delayed-quotes on server services.xmethods.com. getQuote is passed a named parameter, symbol. ## CODE from SOAPpy import SOAPProxy server = SOAPProxy("http://services.xmethods.com/soap") print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM") ## /CODE This does the same thing as the previous example, however namespace is specified inline on a per call basis rather than at the server level. ## CODE from SOAPpy import SOAPProxy server = SOAPProxy("http://services.xmethods.com/soap", soapaction = "http://somesite.com/myaction") print server._ns("urn:xmethods-delayed-quotes").getQuote(symbol = "IBM") ## /CODE This is the same quote call with a soapaction specified. ## CODE from SOAPpy import SOAPProxy server = SOAPProxy("http://services.xmethods.com:80/soap") ns = "urn:xmethods-delayed-quotes") sa = "http://somesite.com/myaction" my_call = server._ns(ns)._sa(sa) my_call.getQuote(symbol = "IBM") my_call.getQuote(symbol = "IBM") my_call.getQuote(symbol = "IBM") ## /CODE The same example, this time with both the soapaction and the namespace specified inline and saved in a local variable for getQuote to be called against. ** What SOAPpy does with the results of a call could seem surprising. If there is only one element in the structType that has the return value and unwrap_results is turned on (the default) it will bubble up the single attribute, otherwise it will return you a structType object with all of the attributes. SERVER EXAMPLES: ## CODE from SOAPpy import SOAPServer def echo(s): return s + s # repeats a string twice server = SOAPServer(("localhost", 8080)) server.registerFunction(echo) server.serve_forever() ## /CODE This exposes the function echo (that takes an unnamed arguement) on a server running on localhost:8080. ## CODE from SOAPpy import SOAPServer def echo(s): return s + s # repeats a string twice server = SOAPServer() server.registerFunction(echo, "echo-space") server.serve_forever() ## /CODE The same as above, but this time the method is available in the namespace "echo-space". ## CODE from SOAPpy import SOAPServer class echoBuilder: def echo(self, val): return val + val server = SOAPServer() e = echoBuilder() server.registerObject(e) server.serve_forever() ## /CODE This registers the whole instance of the object echoBuilder, e. Every method of the instance is exposed on the server. ## CODE from SOAPpy import SOAPServer def echo(**kw): return kw['first'] + kw['second'] + kw['third'] server = SOAPServer() server.registerKWFunction(echo) server.serve_forever() ## /CODE This time the method echo is exposed and it expects named arguments. The main thing to notice here is the use of the method registerKWFunction over registerFunction. ## CODE from SOAPpy import SOAPServer from M2Crypto import SSL def echo(s): return s+s # repeats a string twice ssl_context = SSL.Context() ssl_context.load_cert('server.pem') server = SOAPServer(("localhost",8443), ssl_context = ssl_context) server.registerFunction(echo) server.serve_forever() ## /CODE This exposes the function echo (taking an unnamed arguement) on a server accepting SSL connections at localhost:8443. Ng Pheng Siong's M2Crypto package (available at ) must be installed. Also see tests/silabserver.py. $Id: GettingStarted.txt,v 1.4 2005/02/21 20:09:29 warnes Exp $ SOAPpy-0.12.22/docs/GlobusSupport.txt000066400000000000000000000076001235077700100173170ustar00rootroot00000000000000 Globus Support ============== Extensions have been added to the SOAPpy module to allow the use of the Globus Toolkit v2 for secure transport of SOAP calls. These extensions are possible by using the Globus Toolkit (http://www.globus.org) and the pyGlobus software (http://www-itg.lbl.gov/gtg/projects/pyGlobus/), which exposes the Globus Toolkit via a set of Python interfaces. This enables bi-directional PKI authentication so that the server and client are both guaranteed of the identity of the other. Using PKI this way also allows a more robust authorization solution above the SOAP hosting layer, which provides better application level authorization control. These tools are used by the Access Grid Project (http://www.accessgrid.org) to build a Grid-based, Web Services based, real-time collaboration environment. In order to use the SOAPpy module with the Globus Toolkit, you must first obtain and install the Globus Toolkit and pyGlobus software. Information on how to do that is at the respective web sites listed below. In order to use the Globus Toolkit it is necessary to have an x509 identity certificate. Information on how to obtain one of those is available on the web as well. To use GSI with an authorization method, set the SOAPConfig.authMethod = "methodname". You must have this method defined on any objects you register with SOAPpy, and/or as a registered method. It should return 0 or 1 to indicate if authorization is allowed or not. Once the software is installed, you have obtained your certificate, and the SOAPpy module is installed, the following code shows how to run a GSI secured SOAP server (These snippets are directly from the echoServer.py and echoClient.py in the test directory). Server ------ def _authorize(self, *args, **kw): return 1 Config.authMethod = "_authorize" addr = ('localhost', 9900) from SOAPpy.GSIServer import GSISOAPServer server = GSISOAPServer(addr) server.registerFunction(_authorize) server.registerFunction(echo) Then you use the server like the SSL server or the standard server. Client ------ import pyGlobus # The httpg distinguishes this as a GSI TCP connection, so after # this you can use the SOAP proxy as you would any other SOAP Proxy. server = SOAPProxy("httpg://localhost:9900/") print server.echo("moo") Globus Toolkit http://www.globus.org ------------------------------------ The Globus Toolkit is an open source software toolkit used for building grids. It is being developed by the Globus Alliance and many others all over the world. A growing number of projects and companies are using the Globus Toolkit to unlock the potential of grids for their cause. PyGlobus http://www-itg.lbl.gov/gtg/projects/pyGlobus/ ------------------------------------------------------ The goal of this project is to allow the use of the entire Globus toolkit from Python, a high-level scripting language. SWIG is used to generate the necessary interface code. Currently a substantial subset of the 2.2.4 and 2.4 versions of the Globus toolkit has been wrapped. The Access Grid http://www.accessgrid.org/ ------------------------------------------ The Access GridT is an ensemble of resources including multimedia large-format displays, presentation and interactive environments, and interfaces to Grid middleware and to visualization environments. These resources are used to support group-to-group interactions across the Grid. For example, the Access Grid (AG) is used for large-scale distributed meetings, collaborative work sessions, seminars, lectures, tutorials, and training. The Access Grid thus differs from desktop-to-desktop tools that focus on individual communication. - Submitted 2004-01-08 by Ivan R. Judson $Id: GlobusSupport.txt,v 1.3 2005/02/21 20:09:32 warnes Exp $ SOAPpy-0.12.22/docs/MethodParameterNaming.txt000077500000000000000000000067631235077700100207160ustar00rootroot00000000000000 Experimental method for handing ordered vs named method parameters ------------------------------------------------------------------ There is an incompatibility with the way that Python and SOAP handle method arguments: SOAP requires that all arguments have names and that they are presented in the same order as the method signature. Python (like other scripting languages, notably the S language) has the concept of unnamed arguments. Further Python does not preserve the order of named arguments, since they are handled using the dictionary data type. It seems to me that this makes it impossible to fully meet the SOAP specification without significant modifications to the Python method of handling named arguments or to the Python dictionary class. Historically SOAPpy has attempted to work around this issue by handling all arguments as unnamed unless the method or function was explicitly flagged, in which case all arguments were considered named. This has resulted in a several problems, particularly for a SOAPpy client communicating with a SOAPpy server. First, when named arguments were used in call to a non-flagged function, the argument would silently be reordered by the sender (since they were stored using a Python dictionary), *and* the names would be ignored by the receiver, which assumed that the parameters were unnamed and only the order was significant. This results in incorrect argument matching. This problem also occurred with mixed named and unnamed arguments. For my primary SOAP application, it is not reasonable to flag all of the SOAPpy methods as requiring named arguments, for a variety of reasons. One reason is that the available methods are not known apriori by the client software, hence the names of the arguments are not known. Second, many of the methods provide a large number of optional arguments, making it impractical to specify them all. In an attempt to overcome this problem, I implemented an experimental and non-standard method of handling named and unnamed arguments. This mechanism is enabled in SOAPpy by setting SOAPpy.SOAP.Config.specialArgs=1, and disabled by setting SOAPpy.SOAP.Config.specialArgs=0. When enabled, parameters with names of the form v#### (i.e., matching the regexp "^v[0-9]+$") are assumed to be unnamed parameters and are passed to the method in numeric order. All other parameters are assumed to be named and are passed using the name. Outgoing SOAP method calls now always generate names in this way--whether or not specialArgs is enabled. I selected the form v#### because it is a valid XML name, but is unlikely to be used as a parameter name. [As it turns out, this choice was fortitous because Apache's SOAP tool uses the same system.] In my testing, this mechanism for handling method parameter names works fine between a SOAPpy client and a SOAPpy server, and resolves the parameter reordering problems I was experiencing. This system seems unlikely to have any negative side effects on other SOAP applications, except in the (hopefully) rare case when v#### might be used as an actual parameter name. **In version 0.9.9-pre1, this feature is enabled by default.** Please let me know if there are situations where this causes problems. Note that this mechanism is only a partial solution, since it is still impossible to return named parameters in a specified order using SOAPpy. SOAP applications or implementations which require this feature are simply not compatible with SOAPpy. -Greg Warnes 2003-03-07 (updated 2003-11-14) SOAPpy-0.12.22/docs/UsingHeaders.txt000077500000000000000000000054451235077700100170600ustar00rootroot00000000000000Using Headers ============= SOAPpy has a Header class to hold data for the header of a SOAP message. Each Header instance has methods to set/get the MustUnderstand attribute, and methods to set/get the Actor attribute. SOAPpy also has a SOAPContext class so that each server method can be implemented in such a way that it gets the context of the connecting client. This includes both common SOAP information and connection information (see below for an example). CLIENT EXAMPLES --------------- ## CODE import SOAPpy test = 42 server = SOAPpy.SOAPProxy("http://localhost:8888") server = server._sa ("urn:soapinterop") hd = SOAPpy.Header() hd.InteropTestHeader ='This should fault, as you don\'t understand the header.' hd._setMustUnderstand ('InteropTestHeader', 0) hd._setActor ('InteropTestHeader','http://schemas.xmlsoap.org/soap/actor/next') server = server._hd (hd) print server.echoInteger (test) ## /CODE This should succeed (provided the server has defined echoInteger), as it builds a valid header into this client with MustUnderstand set to 0 and then sends the SOAP with this header. ## CODE import SOAPpy test = 42 server = SOAPpy.SOAPProxy("http://localhost:8888") server = server._sa ("urn:soapinterop") #Header hd = SOAPpy.Header() hd.InteropTestHeader = 'This should fault,as you don\'t understand the header.' hd._setMustUnderstand ('InteropTestHeader', 1) hd._setActor ('InteropTestHeader','http://schemas.xmlsoap.org/soap/actor/next') server = server._hd (hd) print server.echoInteger (test) ## /CODE This should fail (even if the server has defined 'echoInteger'), as it builds a valid header into this client, but sets MustUnderstand to 1 for a message that the server presumably won't understand before sending. SERVER EXAMPLES --------------- ## CODE import SOAPpy def echoInteger (inputInteger): return inputInteger server = SOAPpy.SOAPServer ( ('localhost', 8080) ) server.registerFunction (echoInteger) server.serve_forever() ## /CODE This is a simple server designed to work with the first 2 clients above. ## CODE import SOAPpy def echoInteger (inputInteger, _SOAPContext): c = _SOAPContext print c.xmldata print c.header print c.body print c.connection.getpeername() print c.soapaction print c.httpheaders return inputInteger host = 'localhost' port = 8888 server = SOAPpy.SOAPServer ( (host, port) ) server.registerFunction (SOAPpy.MethodSig(echoInteger, keywords=0,context=1)) server.serve_forever() ## /CODE This is a server which shows off the SOAPContext feature. This server gets a context from the client that has connected to it, and prints some of the pertinent aspects of that client before returning. This server should also work with the code for the two clients written above. $Id: UsingHeaders.txt,v 1.1 2005/02/18 15:36:12 warnes Exp $ SOAPpy-0.12.22/docs/WSDL.txt000066400000000000000000000013621235077700100152370ustar00rootroot00000000000000 WSDL NOTES: Release 0.9.9 and later include logic for dealing with web service description language (WSDL) files. - SOAPpy.WSDL provides a SOAP Proxy object that parses a WSDL file and provides access to the listed services: url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' zip = '01072' proxy = SOAPpy.WSDL.Proxy(url) temp = proxy.getTemp(zip) print 'Temperature at', zip, 'is', temp - On the server, you can allow the client to download the WSDL for a service by sending a request of the form by adding a do_GET method to the SOAPRequestHandler. [Not yet working when debug=FALSE. Add example here when working] $Id: WSDL.txt,v 1.2 2005/02/21 20:09:34 warnes Exp $ SOAPpy-0.12.22/docs/attrs.txt000066400000000000000000000005601235077700100156220ustar00rootroot00000000000000 Using SOAPpy Attributes ======================= All SOAPpy data classes implement methods to access and mutate individual attributes. The _setAttr method has as parameters a 'tag', the attribute name, and the value to which the attribute should be set. The _getAttrs method simply has the 'tag' parameter. $Id: attrs.txt,v 1.2 2005/02/18 15:40:46 warnes Exp $ SOAPpy-0.12.22/docs/complexTypes.txt000066400000000000000000000012031235077700100171540ustar00rootroot00000000000000COMPLEX TYPES HOWTO =================== The easiest way (at the moment) to create complex SOAP typs is to use the SOAPpy.structType class, which allows you to create an object with named arguments of arbitraty types. For example: >>> in0 = SOAPpy.structType() >>> in0._addItem('outwardDate', dep) >>> in0._addItem('returnDate', ret) >>> in0._addItem('originAirport', 'den') >>> in0._addItem('destinationAirport', 'iad') SOAPpy has code for declaring structured object templates including the type for each component, but this broke sometime in the past and has not yet been corrected. (See tests/TCtypes.py to see how it should work.) SOAPpy-0.12.22/docs/simpleTypes.txt000066400000000000000000000200151235077700100170000ustar00rootroot00000000000000Simple Types HOWTO ================== The easiest way to understand use of data types is look at and run the examples already written (in tests/, validate/ and bid/) , and to write your own clients, looking at the xml as it is sent (by setting SOAP.Config.debug=1). As far as the built-in types are concerned, SOAP.py will preserve type as expected. That is: python integer will be of type integer, and equivalently for string and float. To access more than just these types, there are classes in SOAP.py. These allow invoking a certain type by making an instance of the corresponding class. The SOAPBuilder in SOAP.py will automatically convert python lists to Arrays and python dictionaries to Structs- these are two of the most frequently used data types. CLIENT EXAMPLES --------------- ## CODE import SOAP server = SOAP.SOAPProxy("http://localhost:8080/") print server.echo("Hello world") ## /CODE This example (taken from quickstart.txt) sends an ordered parameter of type string. ## CODE import SOAP import time #SOAP.Config.debug = 1 test = time.gmtime (time.time ()) server = SOAP.SOAPProxy("http://localhost:8080/") print server.echoDate (inputDate = SOAP.DateTime(test)) ## /CODE This test calls echoDate with the named parameter inputDate, which is a TimeInstant. It prints the the result. **Note: The reason that it is a TimeInstant and not a DateTime is that SOAP.py uses the 1999 schema intead of the 2001 schema. To make it a DateTime, one would just use SOAP.dateTimeType() in place of SOAP.DateTime(). ** ## CODE import SOAP server = SOAP.SOAPProxy("http://localhost:8080/") test = [0, 1, -1, 3853] print server.echoIntegerArray (inputIntegerArray = test) ## /CODE This calls echoIntegerArray with the named parameter inputIntegerArray, which is a four-member array of type int. It prints the result. ## CODE import SOAP test = {'varFloat': 2.256, 'varInt': 474, 'varString': 'Utah'} server = SOAP.SOAPProxy("http://localhost:8080/") print server.echoStruct (inputStruct = test) ## /CODE This code calls the method echoStruct with the named parameter inputStruct, which is of type Struct. It then prints the result. ## CODE import SOAP item1 = SOAP.Struct( data = {"name":"widget","quantity":200,"price":SOAP.decimalType(45.99), "_typename":"LineItem"}) items = SOAP.Array ( data = [item1] ) items._ns = "http://www.soapinterop.org/Bid" server = SOAP.SOAPProxy("http://localhost:8080") server = server._sa ("http://www.soapinterop.org/Buy") server = server._ns ("http://www.soapinterop.org/Bid") po = SOAP.Struct( data = {"poID":"Order 1234", "createDate": SOAP.dateTimeType(), "items": items} ) print server.Buy(PurchaseOrder = po) ## /CODE A few new things here. -First, we are creating an Array, 'items', with components of (made up) type 'LineItem'. (Notice the use of "_typename" to specify type). -This code associates a namespace with the Array, rather than use the default. -SOAP.dateTimeType() is called directly to get a dateTime instead of SOAP.py's default, 'timeInstant'. -Note that when creating a Struct or Array, the data must be passed in as a named 'data' param (as the first param, by order, is 'name'). -The proxy is instantiated and then the values for its namespace (_ns) and soapaction (_sa) are assigned. -This call will work for a server expecting a parameter with the same components as those in the variable 'po' above. It will work whether the server has a named param 'PurchaseOrder' or has an unnamed param, but will not work if the server expects a named param with a name of anything but 'PurchaseOrder'. SERVER EXAMPLES --------------- ## CODE import SOAP def echo(s): return s + s # repeats a string twice server = SOAP.SOAPServer(("localhost", 8080)) server.registerFunction(echo) server.serve_forever() ## /CODE This server example, from quickstart.txt, echoes (as type string) the string that is passed in, s. ## CODE import SOAP def echoDate (inputDate): return SOAP.DateTime(inputDate) server = SOAP.SOAPServer(("localhost", 8080)) server.registerKWFunction(echoDate ) server.serve_forever() ## /CODE This code accepts an inputDate and returns the same date, ensuring that it is of type TimeInstant by returning an instance of DateTime instead of simply returning the value. ## CODE import SOAP def echoIntegerArray (inputIntegerArray): if type(inputIntegerArray) != type([]) or len(inputIntegerArray) != 4: for elem in inputIntegerArray: if type(elem) != type(1): raise TypeError, "expected 4-member Array of ints" return inputIntegerArray server = SOAP.SOAPServer(("localhost", 8080)) server.registerKWFunction(echoIntegerArray ) server.serve_forever() ## /CODE This server supports the method echoIntegerArray, requiring the named parameter inputIntegerArray, which must be a four-member array of type int. ## CODE import SOAP def echoStruct (inputStruct): myfloat = inputStruct["varFloat"] mystr = inputStruct["varString"] myint = inputStruct["varInt"] return inputStruct server = SOAP.SOAPServer(("localhost", 8080)) server.registerKWFunction(echoStruct ) server.serve_forever() ## /CODE This code creates a server with a method echoStruct, which requires that the incoming Struct have elements named varFloat, varString, and varInt. That is, the server will fault if the incoming Struct does not have any of those elements. **Note, this server code does NOT require that these be the only elements in the struct- just that they be present**. This method simply returns the Struct passed in. ## CODE import sys import SOAP serverstring = "SOAP.py (actzero.com) running "+sys.platform def Buy(**kw): try: PurchaseOrder = kw["PurchaseOrder"] except: PurchaseOrder = kw["PO"] POkeys = PurchaseOrder['_keyord'] POkeys.sort() POkeys_expected = ["items","poID","createDate"] POkeys_expected.sort() if POkeys != POkeys_expected: raise ValueError, "struct 'PurchaseOrder' needs %s, %s, and %s" % tuple(POkeys_expected) items = PurchaseOrder["items"].__dict__ data = items["data"] retstring = "" for item in data: itemdict = item["_asdict"] q = itemdict["quantity"] p = itemdict["price"] name = itemdict["name"] if retstring != "": retstring += ", " else: retstring = "bought " retstring += "%d %s(s) for %.2f" % (q,name,p) retstring += " from "+serverstring return retstring server = SOAP.SOAPServer(("localhost", 8080)) namespace = "http://www.soapinterop.org/Bid" server.registerKWFunction(Buy, namespace ) server.serve_forever() ## /CODE This example creates a server to implement 'Buy', which takes a parameter named either PurchaseOrder or PO. (Notice the use of **kw as the input parameter to the method for this functionality). The server gets the names of the Struct's members by using the '_keyord' key of the Struct-as-dictionary. It checks these names against what it expects from the client, and raises a fault if the two are not the same. By using the __dict__ attribute, the server gets the 'items' (an elemnent of the PurchaseOrder Struct) as a dictionary. Then it checks that 'items' is formatted as expected. Finally, it returns a confirmation of what was bought. $Id: simpleTypes.txt,v 1.2 2005/02/21 20:09:39 warnes Exp $ SOAPpy-0.12.22/old.Changelog000066400000000000000000002641501235077700100153720ustar00rootroot000000000000002005-02-22 10:58 warnes * ChangeLog, README, RELEASE_INFO: Update for 0.12.0 release. 2005-02-21 23:30 tag SOAPpy_0_12_0 2005-02-21 23:30 warnes * tests/README: update README since TCtests.py now passes! 2005-02-21 23:29 warnes * SOAPpy/: Parser.py, Types.py: Fix handling of parse rules! TCtest.py now passes! 2005-02-21 23:25 warnes * tests/: Bug1001646.py, Bug916265.py, ComplexTypes.py, GoogleTest.py, Makefile, README, TCtest.py, echoClient.py, echoHeader.py, echoServer.py, largeDataTest.py, testleak.py: Enhance echoServer with a quit method. Provide a makefile for running all working tests. 2005-02-21 15:27 warnes * SOAPpy/Client.py: Fix loss of quotes at start of file description. 2005-02-21 15:24 warnes * SOAPpy/SOAPBuilder.py: Add spaces and newlines to soap environment declarations when writing SOAP enclosure so that the results are more human readable. 2005-02-21 15:21 warnes * SOAPpy/Client.py: Add code to handle the case when headers are empty or not present. 2005-02-21 15:16 warnes * SOAPpy/WSDL.py: Add 'show_methods' which will print the methods and associated parameters. 2005-02-21 15:09 warnes * docs/: GettingStarted.txt, GlobusSupport.txt, WSDL.txt, complexTypes.txt, simpleTypes.txt: Update documentation. 2005-02-18 14:29 warnes * SOAPpy/Client.py: If content_length is missing or empty, we need not check for a the OC4J bug... 2005-02-18 11:28 warnes * README: Add bug reporting and mailing list information. 2005-02-18 10:42 warnes * docs/GettingStarted.txt: Change 'SOAP.py' to 'SOAPpy' 2005-02-18 10:40 warnes * docs/attrs.txt: Remove the long copyright and usage notices. Clarify the (too brief) text. 2005-02-18 10:36 warnes * docs/: complexTypes.txt, UsingHeaders.txt: Most of the information in the 'complexTypes.txt' file was actually about the use of headers. Moved that text to a new file 'UsingHeaders.txt'. 2005-02-18 08:50 warnes * SOAPpy/wstools/XMLSchema.py: Apply patch submitted by Peter McA'Nulty of WebReply.com: "class SimpleContent, class Extension.fromDom() at line ~2313 doesn't handle extensions without contents -- unusual, but not illegal" 2005-02-17 01:44 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added the item trace to an exception thrown when an unexpected child is encountered in complexType.fromDom method so one can see where the problem is occuring. ---------------------------------------------------------------------- 2005-02-16 13:39 warnes * tests/echoServer.py: Added echo_jheader which returns its argument and the header, in order to support Bug1001646.py 2005-02-16 13:34 warnes * tests/Bug1001646.py: Test now properly checks to see that the header is preserved. 2005-02-16 09:45 tag v1_7 2005-02-16 09:45 warnes * SOAPpy/wstools/XMLname.py: Remember to paste prefix back onto the XMLname before returning. 2005-02-15 23:27 warnes * SOAPpy/SOAPBuilder.py: Bug fix for [ 1078051 ] "Arrays of complex types (doc/lit)" per the patch submited with the bug report by Nelson Minar. 2005-02-15 23:25 warnes * tests/echoClient.py: Print what we're trying to do so that errors are easier to track down. 2005-02-15 23:24 warnes * tests/storageTest.py: Updated 'registerUser' to match current documentation, but still get an error from the server. 2005-02-15 23:23 warnes * tests/echoServer.py: Add 'echo_simple' command that just returns its arguments as-is. 2005-02-15 23:22 warnes * tests/Bug1001646.py: Turn of some debugging information. 2005-02-15 23:21 warnes * tests/Bug916265.py: Regression test for [ 916265 ] "Arrays of unicode do not serialize correctly (patch included)" 2005-02-15 23:09 warnes * tests/Bug1001646.py: Regression test for bug [ 1001646 ] SOAPpy stomps headers when sending multirefs. 2005-02-15 16:51 warnes * SOAPpy/Client.py: Create workaround for a bug in OC4J reported in [ 1122991 ] "error from SOAPpy/Client.py for content_length evaluation?" by Merten Schumann. 2005-02-15 16:09 warnes * SOAPpy/SOAPBuilder.py: Fix [ 1106450 ] "Floats are truncated to 10 digits, causing precision loss" submitted by Kerry 'krdavis'. 2005-02-15 16:07 warnes * SOAPpy/Client.py: Fixed [ 1096971 ] "Parse error: missing HTTP header 'Content-length'" submitted by 'pure water'. 2005-02-15 15:59 warnes * SOAPpy/Types.py: Fix [ 1064248 ] "Bugs in _asdict() and _asarray() in Types.py" submitted by Peter Lamb. 2005-02-15 15:56 warnes * SOAPpy/SOAPBuilder.py: Fix handling of 0-length arrays. 2005-02-15 15:52 warnes * SOAPpy/SOAPBuilder.py: Apply [ 1064233 ] "Bug fixes for complex types" from Peter Lamb. 2005-02-15 15:41 warnes * SOAPpy/SOAPBuilder.py: Fix bug [ 1001646 ] SOAPpy stomps headers when sending multirefs using included patch provide by Nelson Minar 2005-02-15 15:15 warnes * SOAPpy/Client.py: Fix [ 925077 ] SOAPpy prints out SOAP fault /even when Config.debug is off/. 2005-02-15 15:12 warnes * SOAPpy/Parser.py, tests/Bug918216.py: Fix parsing bug & add regression test. SOAPpy was not allowing anything after the close of a faulttype block, but multirefs should be permitted there. Closes bug [ 918216 ] "Parsing faults in SOAPpy 0.11.3" 2005-02-15 14:30 warnes * tests/ZeroLengthArray.py: Test handling of zero-length typed lists. Currently fails. 2005-02-15 14:22 warnes * SOAPpy/SOAPBuilder.py: Revert broken header generation from last patch. 2005-02-15 11:41 warnes * SOAPpy/SOAPBuilder.py: Fix bug [ 916265 ] Arrays of unicode do not serialize correctly, submitted by Nelson Minar. 2005-02-15 11:37 warnes * README: Fix typo in README. 2005-02-15 11:32 warnes * LICENSE, README, setup.py, SOAPpy/Client.py, SOAPpy/Errors.py, SOAPpy/GSIServer.py, SOAPpy/NS.py, SOAPpy/Server.py, SOAPpy/wstools/XMLname.py, docs/MethodParameterNaming.txt: Update email address 2005-02-09 13:33 tag bogus-12_9_123RC93 2005-02-09 13:33 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- need to do isfile check before calling mod func "urlopen" for cross-platform compat. ---------------------------------------------------------------------- 2005-02-07 12:07 irjudson * SOAPpy/wstools/WSDLTools.py: Mod to flatten wsdl imports, schemas not dealt with yet. 2005-02-04 14:18 boverhof * SOAPpy/wstools/Namespaces.py: ---------------------------------------------------------------------- Committing in . Modified Files: Namespaces.py -- OASIS.PROPERTIES wasn't quite correct (suffix .wsdl --> .xsd) ---------------------------------------------------------------------- 2005-02-01 13:10 boverhof * SOAPpy/wstools/Namespaces.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py -- added OASIS BaseFaults. ---------------------------------------------------------------------- 2005-01-31 09:45 warnes * README: Update URL for fpconst. 2005-01-27 18:01 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added a couple convenience methods for grabbing various Schema Items. ---------------------------------------------------------------------- 2005-01-25 19:31 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- change to accomodate writing out XML instances w/o SOAP Envelopes, "known" prefixes aren't "known" when the Envelope isn't writen out. ---------------------------------------------------------------------- 2005-01-18 12:18 boverhof * SOAPpy/wstools/: Namespaces.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py -- added Oasis base notification ns. XMLSchema.py -- modified an exception message. ---------------------------------------------------------------------- 2004-12-20 15:36 boverhof * SOAPpy/wstools/: WSDLTools.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- removed a line that was screwing up imports/includes of when WSDL file was specified to "wsdl2py" via a relative path. XMLSchema.py -- stop requiring suffix "xsd" for schema files. ---------------------------------------------------------------------- 2004-12-17 16:41 boverhof * SOAPpy/wstools/c14n.py: ---------------------------------------------------------------------- Modified Files: c14n.py -- fixed a bug affecting those who don't have pyXML installed. ---------------------------------------------------------------------- 2004-12-08 15:04 boverhof * SOAPpy/wstools/c14n.py: ---------------------------------------------------------------------- Modified Files: c14n.py -- just removed import of ZSI so SOAPy can use w/o ZSI. ---------------------------------------------------------------------- 2004-12-07 10:54 blunck2 * SOAPpy/wstools/__init__.py: uncommented import of WSDLTools. josh commented this out during another commit and i think it was unintentional 2004-11-30 01:27 boverhof * SOAPpy/wstools/: Namespaces.py, WSDLTools.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py WSDLTools.py -- added WSA 2004/08 namespaces, and enabled "PortType" to discover it. ---------------------------------------------------------------------- 2004-11-16 15:59 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added a couple helper methods for discovering whether or not an element should be qualified. ---------------------------------------------------------------------- 2004-11-12 18:14 boverhof * SOAPpy/wstools/: Namespaces.py, WSDLTools.py, XMLSchema.py, logging.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py -- Added a SOAP-1.2 binding WSDLTools.py -- Added some methods from grabbing ElementDeclaration and TypeDefintion from Message instances. XMLSchema.py -- fixed a bug in SchemaReader. logging.py -- added a couple more functions, and a level to basic logger. ---------------------------------------------------------------------- 2004-11-08 14:46 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Committing in . Modified Files: Utility.py -- removed "sw" property in ElementProxy. ---------------------------------------------------------------------- 2004-11-05 02:32 boverhof * SOAPpy/wstools/c14n.py: ---------------------------------------------------------------------- Modified Files: c14n.py -- opps, want to call the implementation constructor when passed any NodeType, not just Element nodes. ---------------------------------------------------------------------- 2004-11-05 01:35 boverhof * SOAPpy/wstools/: Namespaces.py, Utility.py, WSDLTools.py, __init__.py, c14n.py: ---------------------------------------------------------------------- Modified Files: ** removed all "imports" of ZSI or ZSI.wstools, so wstools can be used independently by SOAPpy. Namespaces.py -- added a namespace Utility.py -- moved ZSI.utility here, and the "Base" class for logging. WSDLTools.py -- added a "toDom" and "GetWSDL" methods to several classes, so now you can construct a WSDL instance and then call WSDL.toDom() --> DOM --> and create a WSDL file. __init__.py -- removed "Base" class for logging. Added Files: c14n.py -- moved the c14n stuff from ZSI.compat here. ---------------------------------------------------------------------- 2004-11-04 18:06 mateo41 * SOAPpy/wstools/Namespaces.py: overloaded the DSIG.C14N (from PyXML Namespace with a newer canonicalization algorithm. Added GLOBUS.SIG, which is the namespace for SecureConversation 2004-10-26 20:09 boverhof * SOAPpy/wstools/Namespaces.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py -- added OASIS.LIFETIME ---------------------------------------------------------------------- 2004-10-22 16:11 boverhof * SOAPpy/wstools/: Utility.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- catch any exceptions thrown when a DOM is loaded up, throw a ParseError with old ex.args and inform which file caused the problem. XMLSchema.py -- For attributeGroup incorrectly adding global attribute declarations, but these are declared locally. ---------------------------------------------------------------------- 2004-10-21 02:40 mateo41 * SOAPpy/wstools/Namespaces.py: added another namespace to WSSE, and created a GLOBUS namespace class with 2 namespaces 2004-10-20 18:35 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- uncommented some "import" code that I didn't think was of any use. Now I need it. ---------------------------------------------------------------------- 2004-10-19 21:33 mateo41 * SOAPpy/wstools/Namespaces.py: added the BEA class, which is an organization which has created schema for the SecureConversation protocol 2004-10-19 18:52 boverhof * SOAPpy/wstools/: WSDLTools.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py XMLSchema.py --removed some print statements I left behind. ---------------------------------------------------------------------- 2004-10-18 22:51 boverhof * SOAPpy/wstools/Namespaces.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py -- added some URLs for Oasis specifications. ---------------------------------------------------------------------- 2004-10-15 21:15 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- forgot to look for 2004 WS-Actions. ---------------------------------------------------------------------- 2004-10-14 04:24 boverhof * SOAPpy/wstools/: WSDLTools.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- resolution of default WS-Action was incorrect when using imported portTypes. XMLSchema.py -- added a couple helper functions, and a few more Markers for introspecting modelGroups and simpleType derivations. ---------------------------------------------------------------------- 2004-10-01 00:27 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- SchemaReader wasn't resolving relative paths correctly. ---------------------------------------------------------------------- 2004-09-27 16:40 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- Shouldn't check attributes for WSDL definition since it's legal to specify attribute in ---------------------------------------------------------------------- 2004-09-27 15:55 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- required another condition in getItemTrace, need to check if at or , also added some info to SchemaError throw in checkAttributes. Now provides namespace/attribute and the Schema Item containing the offending attribute. ---------------------------------------------------------------------- ~ 2004-09-22 18:40 boverhof * SOAPpy/wstools/: XMLSchema.py, __init__.py, logging.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added a few convience methods, and 'disabled' a few methods to force a sane usage. __init__.py -- removed use of python logging module, and replaced it with the below. Added Files: logging.py -- simple interface to log message to, can write your own logger class. By default do no logging. ---------------------------------------------------------------------- 2004-09-21 18:19 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added a "getItemTrace" method to XMLSchemaComponent Base class to produce a node trace. Added a bunch of "tag" class variables for identifying what an instance represents, and removed a bunch of unused code. ---------------------------------------------------------------------- 2004-09-10 23:14 warnes * RELEASE_INFO: Update for release 0.11.6 2004-09-10 23:07 tag SOAPpy_0_11_6 2004-09-10 23:07 warnes * ChangeLog, SOAPpy/version.py: Update version number 2004-09-10 23:03 warnes * LICENSE, README, RELEASE_INFO, SOAPpy/Types.py: - Update URLs and email address. - Use 'dictType' instead of 'dict' in type check. 2004-09-09 19:32 boverhof * SOAPpy/wstools/__init__.py: ---------------------------------------------------------------------- Modified Files: __init__.py -- changed "Base", which contains a logger, to no-op logging if the logging configuration file is not found and avoid the overhead of using the logging module. ---------------------------------------------------------------------- 2004-09-09 00:37 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- Commented out the "imports" collection, which isn't of much use. Now URLs are resolved relative to the importing document. Support for this scenario: --- /Users/boverhof/Desktop/Wsdl/Service/whatever.wsdl ... --- /Users/boverhof/Desktop/Wsdl/hello/hello.wsdl ... --- /Users/boverhof/Desktop/Wsdl/hello/goodbye.wsdl ... ---------------------------------------------------------------------- 2004-09-01 22:18 tag SOAPpy_0_11_5 2004-09-01 22:18 warnes * ChangeLog, RELEASE_INFO, SOAPpy/version.py: Update for release 0.11.5 2004-08-18 19:12 boverhof * SOAPpy/wstools/__init__.py: ---------------------------------------------------------------------- Modified Files: __init__.py -- cleaned up the module, removed some old code. ---------------------------------------------------------------------- 2004-06-23 16:10 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added getAttributeContent method wherever appropriate. ---------------------------------------------------------------------- 2004-06-23 14:05 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- SoapBinding item soap:header message attribute needs to be stored as a (namespace,name) tuple to enable lookup. ---------------------------------------------------------------------- 2004-06-21 17:40 boverhof * SOAPpy/wstools/Namespaces.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py -- added 2004 ws-addressing namespaces. ---------------------------------------------------------------------- 2004-06-05 14:30 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- couple bug fixes for determining default wsa:Action values ---------------------------------------------------------------------- 2004-06-04 12:53 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- added a "getResourceProperties" method to class PortType. ---------------------------------------------------------------------- 2004-06-04 12:44 boverhof * SOAPpy/wstools/__init__.py: ---------------------------------------------------------------------- Enter Log. Lines beginning with `CVS:' are removed automatically Committing in . Modified Files: __init__.py -- added some code for doing logging ---------------------------------------------------------------------- 2004-06-03 09:03 warnes * MANIFEST.in: Add text files like LICENSE to the list included in distributed packages. 2004-05-14 00:37 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- Had to change how the default wsa:Action values are set up. Must wait until entire WSDL is loaded, otherwise can get into situations where the objects we need to access haven't been initialized yet because of the order of WSDL information items in the WSDL definition. ---------------------------------------------------------------------- 2004-05-13 13:15 tyger23 * SOAPpy/wstools/Namespaces.py: added XSD_LIST to SCHEMA because it's absence broke wsdl2python. 2004-05-11 04:07 boverhof * SOAPpy/wstools/: Namespaces.py, WSDLTools.py: ---------------------------------------------------------------------- Modified Files: Namespaces.py -- added a bunch of namespaces (encryption, ws-address, ws-resourcepolicy, etc) WSDLTools.py -- added functionality for getting WS-ResourceProperties and ws-Address information out of WSDL. Ran all unittests and passed. ---------------------------------------------------------------------- 2004-05-10 21:09 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added some code to generate user interpretable exceptions. BEFORE: File "/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages/ZSI/wstools/Utility.py", line 600, in __getitem__ return self.data[key] KeyError: u'xtvd' AFTER: File "/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages/ZSI/wstools/XMLSchema.py", line 465, in getQNameAttribute raise KeyError, "targetNamespace(%s) collection(%s) has no item(%s)"\ KeyError: u'targetNamespace(urn:TMSWebServices) collection(types) has no item(xtvd)' ---------------------------------------------------------------------- 2004-04-28 21:40 boverhof * SOAPpy/wstools/: Namespaces.py, Utility.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: Utility.py XMLSchema.py -- just moved SplitQName out of here and into Utility Added Files: Namespaces.py -- WSDL, SOAP, SCHEMA, XMLNS namespaces here. Doesn't require PyXml ---------------------------------------------------------------------- 2004-04-28 17:47 warnes * SOAPpy/Server.py: Fix string format error in fault handling 2004-04-27 11:47 warnes * CHANGELOG: Renamed to ChangeLog 2004-04-27 11:39 warnes * ChangeLog, SOAPpy/version.py: Update for 0.11.4. 2004-04-27 11:38 warnes * RELEASE_INFO: Updated for 0.11.4 release. 2004-04-27 11:23 warnes * SOAPpy/Server.py: Check if header information contains SOAPAction key before checking its value. 2004-04-27 11:22 warnes * tests/TCtest.py: Convert TCtest.py to unit test framework. 2004-04-13 23:42 irjudson * SOAPpy/Types.py: Added traceback info to exception for methodnotfound. 2004-04-13 23:41 irjudson * SOAPpy/Server.py: Added traceback back in, without optional config arg, seems resonable to do it this way. 2004-04-11 18:01 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- Fix to DOM singleton hasAttr method. _attr and _attrNS are instance variables of the minidom Element, and are implementation specific. Now hasAttr method will work when using FtNode.Element, which is what ZSI ParsedSoap defaults to (Ft.Doc). ---------------------------------------------------------------------- 2004-04-10 00:29 irjudson * SOAPpy/Types.py: Applied patch from antonio.beamud@linkend.com, for tagging complexType arrays. Looks entirely self-contained, and therefore safe to apply. Also includes new classes for the standard soap faults that can occur, so clients can catch them directly. 2004-04-10 00:28 irjudson * SOAPpy/SOAPBuilder.py: Applied patch from antonio.beamud@linkend.com, for tagging complexType arrays. Looks entirely self-contained, and therefore safe to apply. 2004-04-10 00:26 irjudson * SOAPpy/Server.py: Changed faultType construction to be more client side parsable, make faultstring a non-variable string (ie no nsmethod in it) so that it can be programmatically checked more easily. Modified faultdetail to be the nsmethod. Now the traceback doesn't get passed to the client side. 2004-04-10 00:22 irjudson * SOAPpy/Client.py: Put quotes back in around SOAP Action, for spec conformance. 2004-04-02 08:45 irjudson * SOAPpy/Client.py: Removed quotes from SOAPAction header, seems to be more correct. 2004-04-01 08:25 warnes * SOAPpy/SOAPBuilder.py, SOAPpy/Types.py, SOAPpy/version.py, tests/SOAPtest.py: - Fixed bug that caused typedArrayTypes to lose their type information when rendered to SOAP. - Added corresponding test case to SOAPtest.py - Updated version number. 2004-03-30 19:42 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- 'attrsNS' replaced with '_attrNS', the actual name ---------------------------------------------------------------------- 2004-03-30 18:19 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- isElement should return False if NOT an Element. ---------------------------------------------------------------------- 2004-03-25 15:46 irjudson * SOAPpy/Server.py: Modified unregsiterObject function to take optional namespace/path args to be consistent with registerObject. 2004-03-22 14:32 irjudson * SOAPpy/Client.py: Fixed indent block bug and removed extraneous print. 2004-03-18 19:21 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- qualified Names are now stored as tuples (namespace, localName). These tuples are used as keys into CollectionNS instances. ---------------------------------------------------------------------- 2004-03-18 09:19 irjudson * SOAPpy/Client.py: Introduced the notion of a fault handler, if a call fails a user specified fault handler can be invoked (if it's specified). This can be used in many situations, we're using is specifically to handle credential problems. 2004-03-11 18:07 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- fixed a few problem with the XML namespace, mainly affecting the use of 'xml:lang'. Fixed a bug identifying attributeGroup references vs. definitions. Also changed the inheritance of MarkerInterface, and moved the classes involved before all Schema classes. Now will parse "XML Schema Part 1: Structures", and "XML Schema Part 2: Datatypes" XML Schema definitions. ---------------------------------------------------------------------- 2004-03-11 14:14 boverhof * SOAPpy/wstools/: Utility.py, WSDLTools.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- added a CollectionNS class that keys items via (targetNamespace, name). WSDLTools.py -- Made WSDL Collections into CollectionNS instances, this fixes problem with collisions, caused by wsdl:imports, between items with same name but defined in different targetNamespaces. So now all items can be accessed via (namespace,name), but ONLY those items defined in WSDL.targetNamepsace (not an import.targetNamespace) can be accessed using just 'name'. Also changed how portType is "loaded". Now instead of dropping all the operation nodes in "load", I drop the portType node into "load". This makes sense because portType really should know about itself, and the XML Schema definition of "portType" includes an "anyAttribute" and I need to make this stuff available. I may change the other WSDL information items to do this to be consistent. ---------------------------------------------------------------------- 2004-03-09 17:53 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py - small fix for the creation of the output parameters, to enable return messages to be properly typecoded. ---------------------------------------------------------------------- 2004-03-04 14:50 irjudson * SOAPpy/SOAPBuilder.py: Added calls in dumpers to ensure tags are built using toXMLname. 2004-03-01 20:34 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- fixed bug in _clone_node patch. This method was being called with qualifiedName for namespaced attributes, and bombing. It is supposed to be called like so: getAttributeNodeNS(self, namespaceURI, localName) Really could remove the if/else clause here but I decided to leave it there just to keep the 3 distinctions in the code. ---------------------------------------------------------------------- 2004-03-01 18:27 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- fixed bugs concerning Model Group References (missing minOccurs/maxOccurs), and simpleType annotations. ---------------------------------------------------------------------- 2004-02-19 10:37 irjudson * SOAPpy/Server.py: Added an unregisterObject function, which unfortunately looks through the entire self.objmap dictionary to find the object to remove, but it does remove it. 2004-02-18 16:48 warnes * SOAPpy/: SOAPBuilder.py, Types.py: Changes to allow SOAPBuilder to allow it to be passed a 'raw' Python object. 2004-02-18 16:27 warnes * tests/: esj_test_client.py, esj_test_server.py: Add quit() method to server and appropriate call to client. 2004-02-18 16:22 warnes * tests/: cardClient.py, cardServer.py: Add quit() method to cardServer, and have cardClient call it when done. 2004-02-17 23:53 warnes * CHANGELOG, RELEASE_INFO: Update CHANGELOG and RELEASE_INFO for 0.11.3 release. 2004-02-17 23:36 warnes * tests/SOAPtest.py: Fix a change to how SOAPpy returns namespace URI's that are non-string. They used to be converted to strings and now are not. I'm not entirely sure what the correct behavior is... 2004-02-17 23:28 warnes * SOAPpy/Types.py: Accept provosed revision by Ivan Judson to the handling of faultType objects in simplify(). 2004-02-17 23:25 warnes * SOAPpy/version.py: Update version number for 0.11.1 release. 2004-02-17 23:17 warnes * docs/GettingStarted.txt: Add \n to end of file. 2004-02-17 23:16 warnes * tests/testClient1.py: Add test of echo with named parameter in call to catch bugs related to providing names. 2004-02-17 23:15 warnes * SOAPpy/SOAPBuilder.py: Fix bug #875977: no escaping of bad tagnames for NoneTypes. Both bug and fix suggested by Robert Zimmermann. 2004-02-17 23:10 warnes * SOAPpy/SOAPBuilder.py: Apply patch to fix bug #888345: Python 2.3 boolean type serialized as int, both provided by Nelson Minar. 2004-02-17 23:05 warnes * SOAPpy/Client.py: Nelson Minar reported bug 888352 and provided a patch: If the server does not send a content-length header for the response, SOAPpy's Client fails to read the response. The Google Web APIs at api.google.com are one such service, as of around 2004-01-20. A patch is included below to just read the whole socket's contents if there is no content-length. This should work fine for HTTP/1.0, but will cause troubles with HTTP/1.1 and chunked encoding. SOAPpy's Client.py uses an old HTTP compatibility class from httplib which sends 1.0 requests, so this seems safe. 2004-02-13 14:04 irjudson * SOAPpy/Types.py: I've added a SOAPException(Exception) class. The simplify_objects option now raises a SOAPException instead of a faultType. This seems to make more sense to me, but I could be wrong. 2004-02-13 14:02 irjudson * tests/echoClient.py: Added another missing call. 2004-02-03 22:21 irjudson * SOAPpy/GSIServer.py: Modified GSIServer to have a GSIConfig that handles the pyGlobus specific configuartion details. Hides this from users. 2004-02-03 01:39 irjudson * docs/GlobusSupport.txt: Updated for simpler client usage. 2004-02-03 01:38 irjudson * SOAPpy/Server.py: Added a fix for exception handling that cleans up exception data structures. This plugs a memory leak when exceptions are raised. 2004-02-03 01:21 irjudson * tests/echoServer.py: Added Context Test, cleaned up output to honor Config.debug flag more. 2004-02-03 01:20 irjudson * tests/echoClient.py: Cleaned up client usage of globus, added in simplest test. 2004-02-03 01:11 irjudson * SOAPpy/Client.py: Changed the use of SOAPAction, it used to default to setting it to "", now it defaults to setting it to the method (not the nsmethod). There is a clause in Server.py that catches 'old style' SOAPActions (aka "") and sets them to the method. When this is confirmed to be what everyone wants and we decide it's alright to (possibly) break client/server interop, we can take the clause out of Server.py and just handle SOAPActions of "" as a possible error/warning. 2004-02-03 01:08 irjudson * SOAPpy/GSIServer.py: Turned off default logging. 2004-02-03 01:08 irjudson * SOAPpy/Server.py: Added context handling. Each call builds a SOAP context and puts it in the global dict _contexts (indexed by thread id). There is also a new function: GetSOAPContext() that returns the context for the current thread. Removed previously added method keyword args,. Turned off default log = 1 in RequestHandler Classes. 2004-01-30 23:20 warnes * SOAPpy/: Client.py, Config.py, Errors.py, GSIServer.py, NS.py, Parser.py, SOAP.py, SOAPBuilder.py, Server.py, Types.py, URLopener.py, Utilities.py, WSDL.py, __init__.py, version.py: Add ident and __version string to all files. 2004-01-30 23:19 warnes * SOAPpy/Server.py: Fix bug reported by Dan Nathan that occurs using named arguments. 2004-01-26 01:39 dwrobertson * SOAPpy/wstools/test/test_WSDLReader.py: Removed duplicate test. 2004-01-26 01:38 dwrobertson * SOAPpy/wstools/test/: README, __init__.py, test_wsdl.py, test_wstools.py, test_wstools_net.py: Brought README up to date, made changes having to do with moving of ZSI-specific material to zsi/test/wsdlpy, removed dependencies on utils.py. 2004-01-26 01:35 dwrobertson * SOAPpy/wstools/test/: config.py, config.txt: config.py renamed to config.txt 2004-01-26 01:34 dwrobertson * SOAPpy/wstools/test/: test_wsdl2python.py, utils.py: Code moved to zsi/test/wsdl2py 2004-01-21 16:54 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added substutionGroup to the list of attributes that can be specified in an ElementDeclaration. ---------------------------------------------------------------------- 2004-01-15 01:09 warnes * docs/GlobusSupport.txt: Added GlobusSupport.txt documentation submitted by Ivan R. Judson . 2004-01-15 00:39 warnes * tests/testClient1.py: Add test for dataTimeType objects. 2004-01-15 00:34 warnes * SOAPpy/Server.py, tests/echoServer.py: Integrate patch from Ivan R. Judson [mailto:judson@mcs.anl.gov]: "There's a namespace collision in the Server.py module for deciding what namespace should be used, ie, r._ns or the path. I've resolved it with a big comment that basically says, r._ns is the preferred specification, but that if it is missing and self.path exists, use that. "This patch also includes the previous patch to include "method" : nsmethod in the keywords for invocations so that authorization gets the methodname." 2004-01-05 13:03 warnes * SOAPpy/Types.py: - Code assumes nested scopes, so I added the proper import so this will work under python 2.2.x - _setAttr was assuming that all attributes are strings. Fixed. 2004-01-01 23:17 rsalz * SOAPpy/.cvsignore: added 2003-12-23 05:19 tag SOAPpy_0_11_1 2003-12-23 05:19 warnes * CHANGELOG, RELEASE_INFO, TODO: - Updated documentation for 0.11.1 release. 2003-12-23 05:05 warnes * SOAPpy/version.py: - Update version number for new release. 2003-12-23 05:04 warnes * SOAPpy/Server.py: - Changes suggested by Richard Au (richardau) to fix ssl support. See bug report [ 752882 ] "SSL SOAP Server no longer working." 2003-12-23 04:33 warnes * SOAPpy/SOAPBuilder.py: - Fixed bug [ 792258 ] "SOAPBuilder.SOAPBuilder.dump can catch wrong exceptions" in SOAPBuilder.dump() submitted by Greg Chapman (glchapman). - Fixed a bug in SOAPBuilder.dump_instance() that had been masked by bug #792258. 2003-12-23 04:24 warnes * tests/SOAPtest.py: - Add call to structType.__init__ for user classes that inherit from structType. This fixes a bug in the tests that was masked by incorrectly catching & ignoring exceptions in SOAPBuilder.dump(). 2003-12-23 04:10 warnes * tests/testClient1.py: - testClient1.py now works. The problem was failing to set 'quit' back to zero after the SOAP server exited. 2003-12-23 03:22 warnes * SOAPpy/SOAPBuilder.py: - Remove call to gentag from 'dump' and add to 'dump_float', per bug report [ 792600 ] "SOAPBuilder.SOAPBuilder.dump possibly should not call gentag" by Greg Chapman (glchapman). 2003-12-23 03:21 warnes * tests/SOAPtest.py: - Add a tests for handling of nil="true" and nil="false". 2003-12-23 03:17 warnes * SOAPpy/Parser.py: - Correctly handle testing for nil="true" and for nil=1. 2003-12-23 02:56 warnes * SOAPpy/wstools/WSDLTools.py: - Fix syntax error from last change. 2003-12-23 02:42 warnes * SOAPpy/wstools/WSDLTools.py: - Added 'strict' option to the WSDL class. If strict is true, a RuntimeException will be raised if an unrecogned message is recieved. If strict is false, a warning will be printed to the console, the message type will be added to the WSDL schema, and processing will continue. This is in response to the second half of bug report [ 817331 ] "Some WSDL.py changes", submitted by Rudolf Ruland. 2003-12-23 02:21 warnes * SOAPpy/wstools/WSDLTools.py: - rename loadFromStream's 'file' argument to 'stream' to make it clear that the stream need not be a file. 2003-12-23 02:11 warnes * SOAPpy/Parser.py: - Fix bug [ 858168 ] 'xsi:nil="true" causes exception', reported by Robert Zimmermann (robertzett@user.sf.net). 2003-12-19 22:21 warnes * RELEASE_INFO: - Mistyped 'unwrap_results' instead of 'simplify_objects' 2003-12-19 22:03 tag SOAPpy_0_11_0 2003-12-19 22:03 warnes * SOAPpy/version.py: - Update version number for release. 2003-12-19 17:23 warnes * TODO: - Clarify what documentation needs to be done. 2003-12-19 17:20 warnes * docs/quickstart.txt: Renamed quickstart.txt to GettingStarted.txt. 2003-12-19 17:19 warnes * CHANGELOG, LICENSE, README, RELEASE_INFO, docs/GettingStarted.txt, docs/WSDL.txt: Updated README to be shorter and clearer: - Moved most example to docs/GettingStarted.txt - Moved WSDL example to docs/WSDL.txt - Moved license text to LICENSE Updated RELEASE_INFO Updated CHANGELOG 2003-12-19 15:19 warnes * SOAPpy/Client.py, SOAPpy/Parser.py, SOAPpy/SOAPBuilder.py, tests/SOAPtest.py, tests/simpleWSDL.py: - Updated calls to fpconst - SOAPpy now checks for nonstandard infinity encoding produced by some older SOAP tools like SOAP4J and Apache SOAP (both now superceeded by Axis SOAP). - Added the offending XML string to the exception thrown when a float/double underflow or overflow occurs. - Minor twiddles in the examples. 2003-12-19 13:22 warnes * SOAPpy/: Client.py, Config.py, Types.py: - Modified SOAPProxy code to correctly pull value of unwrap_results and simplify_objects from Config unless specifically provided in the instantiation call. - Modified Config to better handle configuration variables that are only valid when pyGlobus is available. - Added more documentation to Config variables. - Better documentation for simplify() and simplify_contents() functions. 2003-12-19 13:16 warnes * tests/: README, SOAPtest.py, echoClient.py, echoHeader.py, echoServer.py, esj_test_client.py, simpleWSDL.py: - Add more documentation - Modify echoClient to work properly when pyGlobus is not available. - Misc cleanup. 2003-12-19 12:04 warnes * SOAPpy/Client.py, SOAPpy/Config.py, SOAPpy/Parser.py, SOAPpy/Server.py, tests/SOAPtest.py, tests/echoClient.py, tests/echoServer.py, tests/esj_test_client.py, tests/esj_test_server.py: - Restored Config.unwrap_results to its previous meaning. - Added Config.simplify_objects to control whether SOAPpy objects are simplified into basic python types. - Moved simplification code out of ParseSOAPRPC into SOAPRequestHandler.do_POST and SOAPProxy.__call. - Modified test code appropriately. 2003-12-19 10:58 warnes * tests/simpleWSDL.py: - Add WSDL example from the README as simpleWSDL.py 2003-12-18 17:46 warnes * tests/README: - More information 2003-12-18 17:42 warnes * tests/: README, esj_test_client.py, esj_test_server.py, largeDataTest.py, testClient1.py: - Update test/README with more information - Remove/comment out verbose debugging from tests. 2003-12-18 17:40 warnes * SOAPpy/: Client.py, Config.py, GSIServer.py, Parser.py, SOAPBuilder.py, Server.py, Types.py, WSDL.py, version.py: - More changes to enable proper return of simple python objects when Config.unwrap_results=1. - Addition of support for Globus, contributed by Ivan R. Judson - Resolution of merge conflicts due to unsynchronized copies at home and work. 2003-12-18 13:28 warnes * tests/: echoHeader.py, esj_test_client.py, esj_test_server.py, largeDataTest.py, testClient1.py, testleak.py: - Added more test scripts. 2003-12-18 13:26 warnes * tests/: echoClient.py, echoServer.py: - Add testing of Globus Support code - Turn off verbose debugging messages 2003-12-18 13:25 warnes * tests/SOAPtest.py: - Missed a call to parseSOAPRPC when config.uwrap_results=0. 2003-12-18 02:08 warnes * RELEASE_INFO, TODO: - Update documentation. 2003-12-18 01:55 warnes * SOAPpy/version.py: - Update version string. 2003-12-18 01:54 warnes * SOAPpy/: Config.py, Parser.py, SOAPBuilder.py, Server.py, Types.py: - Config.unwrap_results now works properly. - New Config.dict_encoding option to control the encoding of dictionary keys. By default this is 'ascii' so that dictionaries have ordinary string keys even if they were encoded into UTF for transport (the default is UTF-8). Any other encoding known to string.encode is valid. - New Config.strict_range option to force Parsing to enforce range checking on double and float variables. This is off by default. 2003-12-18 01:31 warnes * tests/: SOAPtest.py, TCtest.py, echoClient.py, echoServer.py, quoteTest.py, storageTest.py, xmethods.py: - Modified SOAPtest.py to work when Config.unwrap_results=1. - Modified SOAPtest.py to set Config.strict_range to enforce checking of the range of float and double objects. [This is a new Config variable and is off by default.] - Fixed wrongly named arguments in TCtest.py - Turned off excess debugging information in echoClient.py, echoServer.py, storageTest.py - Removed unneeded import from quoteTest.py that was generating a warning. - Removed unnecessary explict mapping to dictionary in xmethods.py 2003-12-18 01:23 warnes * tests/README: - A little documentation can go a long way, ;^) 2003-12-17 17:18 warnes * SOAPpy/wstools/WSDLTools.py: - Fix problem when WSDL.Proxy was passed WSDL in a string or other object that does not have a 'name' attribute. 2003-12-08 03:04 boverhof * SOAPpy/wstools/WSDLTools.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- partial bug fix for [ 850905 ] wsdl2py crash on a more sophisticated WSDL. We do expect a list, but nmtokens is a list separated by a single space. So if "parts" is a string, the just split it to create a list. ---------------------------------------------------------------------- 2003-12-05 20:49 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- If a schema needs to 'create' a schema instance itself it adds this schema to its import dictionary. ---------------------------------------------------------------------- 2003-12-05 19:17 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- error in Import class for accessing a schemaLocation. This bug would only show up if a schema had to 'construct' a schema instance of a different namespace itself. Basically the last option. ---------------------------------------------------------------------- 2003-12-05 10:34 warnes * SOAPpy/: WSDL.py, wstools/WSDLTools.py: - Fixes submitted by Kirk Strauser for WSDL use in SOAPpy 2003-12-04 14:05 warnes * zope/: README, zope-2.5.0-soappy.diff, zope-2.6.2-soappy.diff, zope-soap-client.py: - Added contributed patches from Antonio Beamud Montero that extend Zope with SOAP support. 2003-12-04 13:57 warnes * README, README.MethodParameterNaming, SOAPpy/Config.py, SOAPpy/Parser.py, SOAPpy/SOAPBuilder.py, SOAPpy/Types.py, SOAPpy/version.py: - Mostly changes to allow returned SOAP objects to be 'unwrapped' into plain python objects when Config.unwrap_results=1. 2003-11-21 18:12 warnes * tests/SOAPtest.py: - Fix some errors - Updated to mactch change back to "v#" unnamed variable naming strategy. - Added config.unwrap=0 to prevent unwrapping since this test code expects the old behavior. - Only 1 failure now! 2003-11-14 14:09 warnes * docs/MethodParameterNaming.txt: Moved /README.MethodParameterNaming to /docs/MethodParameterNaming.txt 2003-11-14 13:48 warnes * SOAPpy/Types.py: - Modify compoundType to remove internal _asdict and _aslist objects which were different views of (some of) the object attributes. It was possible for these views to get out of sync causing (at least) confusion. Instead, I provide _aslist() and _asdict() functions to render the existing data in the desired format. - Modify simplify() function to work recursively on compound types. 2003-11-14 13:44 warnes * SOAPpy/Server.py: - if Config.unwrap_results is True, convert SOAPpy arrayType and structType to python list and dictionary. - Modify special argument handling to use "v[0-9]" for unnamed ordered arguments. 2003-11-14 13:36 warnes * SOAPpy/SOAPBuilder.py: - Modifid to use "v[0-9]+" as pattern for ordered but unnamed parameters instead of "_[0-9]". - Modified dump_instance to simplify writing out object components. 2003-11-14 13:32 warnes * SOAPpy/Parser.py: - Parser.py now converts arrayType and structType SOAPpy objects to standard python lists and dictionaries when Config.unwrap_results is True. 2003-11-14 13:29 warnes * SOAPpy/Config.py: - Changed config.specialArgs back to a simple flag. 2003-10-31 21:49 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- fixed an unknown bug caused by overlooking the potential namespace contents of a "types" node. ---------------------------------------------------------------------- 2003-10-27 17:42 boverhof * SOAPpy/wstools/: Utility.py, WSDLTools.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: Utility.py WSDLTools.py XMLSchema.py -- Fixed [ 810251 ] default method broken in wstools.Utility.Collection -- Also fixed problem with includes Collection key, and changed Types(Collection) class to declare a different default key instead of redefining several methods. ---------------------------------------------------------------------- 2003-10-27 16:26 boverhof * SOAPpy/wstools/: WSDLTools.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py XMLSchema.py -- Fixed [ 808505 ] ZSI fails with Now schema include statements should be handled correctly. -- Also fixed a problem with relative uri handling for XMLSchema and SchemaReader. ---------------------------------------------------------------------- 2003-10-25 22:54 dwrobertson * SOAPpy/wstools/test/utils.py: Fixed bug, where if multiple tests using one diff file, and one test failed, subsequent tests failed on assertion errors. 2003-10-23 15:09 uid27080 * README: Updated for 0.10.4 2003-10-23 15:00 uid27080 * RELEASE_INFO: Updated for 0.10.4 2003-10-23 14:58 uid27080 * CHANGELOG: - Updated for 0.10.4. 2003-10-22 12:46 tag SOAPpy_0_10_4 2003-10-22 12:46 warnes * SOAPpy/version.py: Release with improved performace thanks to a patch by Erik Westra. 2003-10-22 12:45 warnes * SOAPpy/Parser.py: Patch improving parser performance submitted by Erik Westra: On Tuesday, October 21, 2003, at 09:44 PM, Erik Westra wrote: > Hi Greg, > > I've been using your SOAPpy library (version 0.10.3) in an application > I've been developing, and have had complaints about the amount of time > it takes to receive large packets of data. In this application, the > server was sending through PDF documents as base64-encoded strings, > which were transmitted using a perl SOAP library, and processed on my > end using SOAPpy. As soon as the PDF files got reasonably large, > SOAPpy was taking a long time to decode the data -- up to five minutes > in some cases. > > I started digging into the SOAPpy source code, and quickly found the > cause of the problem: the Parser.py module was using a Python string > to store the character data, and as new character data was being > received, it was "appending" the new data like this [from Parser.py, > line 404]: > > self._data += c > > The problem with this is that Python strings are immutable, so the > above statement is actually recreating the entire string buffer from > scratch every time a new line of character data is received -- which > is extremely inefficient. A much better way to do this is to use a > (mutable) Python list object, and to append the new character data to > the end of this list, like this: > > self._data = [] > > ... > > self._data.append(c) > > and then use: > > string.join(self._data, "") > > to obtain the complete copy of the list once all the lines of data > have been processed. I've attached a unified diff file listing the > changes I've made to Parser.py to implement this -- they're pretty > minimal, and won't affect anything other than the performance of > character data processing. > > The results of this patch are quite impressive: I tried processing a > SOAP response with a single string containing around 675K of data. > Using the unpatched Parser.py file, it took 111 seconds to process -- > with this patch, it took just 2.4 seconds. > > I hope you find this useful... > > Cheers, > > - Erik. > > PS: Thanks for the work you (and the others) are doing on SOAPpy. > It's a great library! 2003-10-21 17:19 dwrobertson * SOAPpy/wstools/test/config.py: Latest xmethods. 2003-10-14 12:08 mbucc * SOAPpy/wstools/Utility.py: Use m2crypto for SSL if it's installed 2003-10-08 13:07 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- now we get reasonable error message back when import or include is incorrectly defined. File "/usr/local/lib/python2.3/site-packages/ZSI/wstools/XMLSchema.py", line 478, in __checkAttributes raise SchemaError, '%s, unknown attribute' %a ZSI.wstools.XMLSchema.SchemaError: location, unknown attribute ---------------------------------------------------------------------- 2003-10-03 13:49 rsalz * SOAPpy/wstools/Utility.py: Let lower layers (http lib) raise exception if trying to use SSL on a non-SSL-enabled system. 2003-10-03 10:01 mbucc * SOAPpy/wstools/XMLSchema.py: Removed pyXml dependency. 2003-10-01 18:08 dwrobertson * SOAPpy/wstools/test/__init__.py: For importing utils 2003-10-01 17:47 dwrobertson * SOAPpy/wstools/test/test_wsdl2python.py: High level client code generator tests moved elsewhere. 2003-09-30 04:25 dwrobertson * SOAPpy/wstools/test/utils.py: Fixed premature close of string buffer. 2003-09-25 14:12 tag SOAPpy_0_10_3 2003-09-25 14:12 warnes * SOAPpy/version.py: - Updated to 0.10.3 (we missed a cvs tag point) 2003-09-25 14:09 tag SOAPpy_0_10_2 2003-09-25 14:09 warnes * SOAPpy/SOAPBuilder.py: Updated version number for release 0.10.2. 2003-09-16 20:08 dwrobertson * SOAPpy/wstools/test/config.py: Updated with latest xmethods, removed URL's no longer in xmethods. 2003-09-16 15:25 rsalz * SOAPpy/WSDL.py: Bug 792247: Unnecessarily slow code in WSDL.Proxy.__getattr__ Use has_key instead of creating temporary names() list 2003-09-13 20:38 dwrobertson * SOAPpy/wstools/test/utils.py: Added ability to read values from multiple config file sections, added setUpWsdl utility function, cleaned up loadTestsFromNames, updated comments. 2003-09-13 20:36 dwrobertson * SOAPpy/wstools/test/test_WSDLReader.py: Now using separate MatchTestLoader in makeSuite. Improved way config file sections are selected. 2003-09-13 20:35 dwrobertson * SOAPpy/wstools/test/test_wsdl2python.py: Combined two tests generating services and services_types files into one method. Moved setUpWsdl to utils. Added easier choosing of config file sections. Used separate MatchTestLoader in makeTestSuite. 2003-09-13 20:32 dwrobertson * SOAPpy/wstools/test/: test_t1.py, test_wsdl.py, test_wstools.py, test_wstools_net.py: Converted to more automated way of generating test cases from configuration file. 2003-09-12 02:11 dwrobertson * SOAPpy/wstools/test/config.py: Cleaned up names. 2003-09-11 21:22 dwrobertson * SOAPpy/wstools/test/config.py: services_by_http section divided into services where there is no schema, those with only simple types, those with complex types, those with WSDLReader errors, and those with wsdl2python errors. The last contain mostly those that are raised by that module. 2003-09-11 18:53 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- fixed two places where 'readFromURL' was supposed to be loadFromURL. ---------------------------------------------------------------------- 2003-09-10 02:01 dwrobertson * SOAPpy/wstools/test/test_wsdl2python.py: Got rid of pyGridWare import. 2003-09-10 02:01 dwrobertson * SOAPpy/wstools/test/test_WSDLReader.py: Got rid of pyGridWare import 2003-09-10 00:17 dwrobertson * SOAPpy/wstools/test/utils.py: Utilities to aid unit tests. 2003-09-10 00:16 dwrobertson * SOAPpy/wstools/test/test_wsdl2python.py: Unit tests for code generation in wsdl2python 2003-09-10 00:15 dwrobertson * SOAPpy/wstools/test/test_WSDLReader.py: Unit tests for WSDLReader from WSTools 2003-09-10 00:14 dwrobertson * SOAPpy/wstools/test/config.py: Added many URL's from xmethods to services_by_http section. 2003-09-05 15:59 warnes * README: Changed dependency list. SOAPpy does depend on fpconst, but no longer depends on pyXML. 2003-09-05 15:53 warnes * README: - Added dependencies list 2003-09-05 14:57 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added a try clause to catch xml.dom.ext ImportError, and added a SplitQName function that matches xml.dom.ext.SplitQName output. ---------------------------------------------------------------------- 2003-08-28 15:03 boverhof * SOAPpy/wstools/test/: README, config.py, test_t1.py, test_wsdl.py, xmethods.tar.gz: ---------------------------------------------------------------------- Modified Files: README config.py test_t1.py test_wsdl.py xmethods.tar.gz Added a couple tests and an explanation of how to add new tests. ---------------------------------------------------------------------- 2003-08-28 13:26 warnes * SOAPpy/Client.py: - Fixed missing import needed for basic authentication. 2003-08-27 18:27 boverhof * SOAPpy/wstools/test/: README, config.py, schema.tar.gz, test_t1.py, test_wsdl.py, test_wstools.py, test_wstools_net.py, xmethods.tar.gz: ---------------------------------------------------------------------- Added Files: README config.py schema.tar.gz test_t1.py test_wsdl.py test_wstools.py test_wstools_net.py xmethods.tar.gz -- basic unittesting framework for WSDLTools/XMLSchema, test_t1 just checks that everything goes where it's supposed to. ---------------------------------------------------------------------- 2003-08-27 18:25 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- attribute declarations were going into wrong collection. ---------------------------------------------------------------------- 2003-08-26 18:43 boverhof * SOAPpy/wstools/: WSDLTools.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: WSDLTools.py -- added a line in Reader to to set WSDL.location for files so that imports with relative paths will work for file paths as well as urls. XMLSchema.py -- a couple Attribute fixes, and the WSDLAdapter wasn't passing it's parent into the XMLSchemaComponent constructor which was messing up import lookups. ---------------------------------------------------------------------- 2003-08-25 18:35 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- fixed XMLSchemaComponent.setAttributes, added the needed getNamespace method to all DOMAdapters. All changes are related to XML attribute handling. ---------------------------------------------------------------------- 2003-08-25 08:16 warnes * README: - Applied patch submitted by Humberto Diógenes (virtualspirit): Corrected examples inside "readme Just eliminated some warnings ("import SOAPProxy" instead of "import SOAP") 2003-08-07 00:49 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- Modified/Extended some of the element classes. For LocalElementDeclaration inheritance was duplicitous, and for ElementReference it was wrong. ---------------------------------------------------------------------- 2003-08-05 19:42 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- Fixed a few bugs, a few classes mistakenly thought they contained global attribute declarations and I fixed this to local attribute declarations. Couple spots where AttributeGroup declarations and references were incorreclty used in place of eachother. Completed a few classes but a few remain incomplete. ---------------------------------------------------------------------- 2003-07-31 02:37 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- Namespaced a couple attributes in attribute dictionary that I missed. ---------------------------------------------------------------------- 2003-07-30 15:45 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- there was a indexing logic error in Restriction/Extention classes fromDom method. Also changed the attribute dictionary of all classes that inherit XMLSchemaComponent, now all attributes are organized by namespace. ---------------------------------------------------------------------- 2003-07-25 17:46 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- Wasn't resolving schema imports in every scenario. Now look in parent schema imported_schemas first, second look in the parent wsdl, lastly try to resolve schemaLocation. Removed 'what' parameter from marker interface methods, I don't know what it was doing there. Check self. ---------------------------------------------------------------------- 2003-07-23 20:34 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- changed getQNameAttribute to return None if it can't find QName obj in it's own tns or in any of its imported namespaces. Used to throw an exception. ---------------------------------------------------------------------- 2003-07-23 18:16 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- fixed some default attribute handling, added a few get methods in XMLSchema for elementFormDefault, attributeFormDefault, blockDefault, finalDefault. Also added a global method GetSchema. Now default attributes are set correctly in all schema components. ---------------------------------------------------------------------- 2003-07-23 16:33 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- checking for wrong class in two methods. ---------------------------------------------------------------------- 2003-07-23 14:25 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- removed bogus method setType in SimpleType class. ---------------------------------------------------------------------- 2003-07-22 13:39 boverhof * SOAPpy/wstools/Utility.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- commited a mistake. fixed. ---------------------------------------------------------------------- 2003-07-22 13:34 boverhof * SOAPpy/wstools/: Utility.py, XMLSchema.py: ---------------------------------------------------------------------- Modified Files: Utility.py -- Added a parameter to Collection class constructor, 'name' is the default attribute used for keys but one can specify whatever key they want. XMLSchema.py -- Used the above parameter to make Collection instances use the appropriate 'attribute' as key. ---------------------------------------------------------------------- 2003-07-22 10:57 warnes * SOAPpy/: Parser.py, SOAPBuilder.py: - More fixes to use fpconst instead of ieee754. 2003-07-22 10:54 warnes * SOAPpy/: Parser.py, SOAPBuilder.py, wstools/__init__.py, wstools/ieee754.py: - Remove obsolete ieee754.py. PEP 754 provides a (proposed) fpconst module which is a newer version of this code. fpconst, will of course, need to be installed separately. 2003-07-21 18:13 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- still a couple mistakes in constructors, changed XSDNS to SCHEMA.XSD_LIST which was a mistake. 2003-07-21 17:56 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- missing parent parameter to a few constructors that expect to see it. fixed. 2003-07-21 15:14 boverhof * SOAPpy/wstools/: XMLSchema.py, license.txt: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- added LBNL copyright header. Added Files: license.txt -- LBNL copyright. 2003-07-21 10:18 warnes * SOAPpy/: version.py, wstools/UserTuple.py, wstools/XMLSchema.py: - Modified XMLSchema to extend UserTuple instead of tuple for python < 2.2. - Added UserTuple class, taken from from Stefan Schwarzer's ftputil library, which is available at . 2003-07-21 09:15 warnes * SOAPpy/Utilities.py: - Unecesssary import was creating a circular import loop. 2003-07-18 13:36 tyger23 * SOAPpy/wstools/XMLSchema.py: fixed a naming issue 2003-07-18 11:58 warnes * SOAPpy/URLopener.py, SOAPpy/WSDL.py, tests/BabelfishWSDLTest.py: - Modifed WSDL.Proxy to pass along all arguments to SOAPProxy. This should ensure that all features of SOAPProxy are accessible to users of WSDL.Proxy - Created URLopener.py, which contains a class extending urllib.FancyURLopener. This class allows reading from URLs that are protected by basic authenticatoin, have been relocated, etc. - Modified WSDL.Proxy to use URLopener. It should now permit access to WSDL files protected by basic authentication. 2003-07-18 10:13 warnes * SOAPpy/Client.py: - Trivial formatting change 2003-07-17 18:23 boverhof * SOAPpy/wstools/XMLSchema.py: ---------------------------------------------------------------------- Modified Files: XMLSchema.py -- fixed a couple bad variable references. 2003-07-17 17:48 boverhof * SOAPpy/wstools/: WSDLTools.py, XMLSchema.py: Modified Files: WSDLTools.py -- just a few minor changes so the new schema class will be used instead of the schema tns placeholder. Might want to add an argument to WSDL.load method so that programmer can specify the placeholder or actual implementation. XMLSchema.py -- mostly new, unused original code is commented out at the bottom. 2003-07-02 14:58 warnes * SOAPpy/: Client.py, version.py: - Client.py failed to import faultType from Types.py, and was getting the python default instead. This caused problems in properly detecting errors on the server reported via SOAP. 2003-05-29 17:01 warnes * SOAPpy/WSDL.py: - Add additional arguments to __init__ which will be passed to Proxy.__init__. This allows specification of proxy server and other options. 2003-05-22 22:31 feanor420 * SOAPpy/wstools/Utility.py: Running pychecker over ZSI, and I noticed some problems in wstools. I fixed that fact that Notation and Entity were not be found. I changed them to use the qualified name like the rest of the symbols from xml.dom.minidom. I also discovered that a RecursionError was being thrown, but RecursionError didn't exist. I created simple sub-class of Exception to rectify this. 2003-05-21 13:39 warnes * SOAPpy/Client.py: - Modified getNS pattern to prevent grabbing to much text. 2003-05-21 12:06 blunck2 * SOAPpy/Client.py: changed namespace regular expression so that it matches what is returned from a stateful (*shiver*) soap server. for example, the namespace returned from a stateful soap server looks like: urn:echo@rO0ABXNyACJ3ZWJsb2.... where urn:echo was the original namespace. 2003-05-21 11:33 tag SOAPpy_0_10_1 2003-05-21 11:33 warnes * CHANGELOG, RELEASE_INFO: - Updated CHANGELOG and RELEASE_INFO for 0.10.1 release. 2003-05-21 10:52 warnes * tests/: SOAPtest.py, TCtest.py, alanbushTest.py, echoClient.py, echoServer.py, excelTest.py, newsTest.py, quoteTest.py, speedTest.py, storageTest.py, translateTest.py, weatherTest.py, whoisTest.py, xmethods.py: - Add ".." to python module path so that the local SOAPpy code will be used instead of the globally installed code when running tests. 2003-05-21 10:51 warnes * setup.py: - Update setup.py to get version string from SOAPpy/version.__version__. 2003-05-21 10:37 warnes * SOAPpy/version.py: - I forgot to update the version number associated with the addition of the file version.py. 2003-05-21 10:34 warnes * SOAPpy/: Client.py, Errors.py, Server.py, version.py: - Added file 'version.py' whose sole purpose is to hold the definition of __version__ in a single place. - Modified Server.py and Client.py to 'from version import __version__'. - Removed __version__ definition from Error.py, which never used it. 2003-05-20 17:25 tag SOAPpy_0_10_0 2003-05-20 17:25 warnes * RELEASE_INFO: Updated for release 0.10.0. 2003-05-20 17:10 warnes * SOAPpy/wstools/: TimeoutSocket.py, Utility.py, WSDLTools.py, XMLSchema.py, XMLname.py, __init__.py: - Added ident string containing CVS version to all files that were lacking this. 2003-05-20 17:04 warnes * CHANGELOG, TODO, setup.py, SOAPpy/SOAP.py, SOAPpy/Types.py, SOAPpy/WSDL.py, SOAPpy/__init__.py: - Added ident string containing CVS version to all files that were lacking this. 2003-05-20 16:08 warnes * SOAPpy/Client.py: - Fix bug in getNS that caused loss of namespace by using better pattern matching to find the namespace in the SOAP message. 2003-05-20 08:47 warnes * setup.py: - Removed or changed dashes to underscores in version numbers to make RPM happy. 2003-05-19 13:45 warnes * SOAPpy/Server.py: - Added ThreadingSOAPServer which inherits from ThreadingTCPServer server so that muliple clients will be automatically multiplexed. 2003-05-15 20:31 boverhof * SOAPpy/wstools/XMLSchema.py: Modified Files: XMLSchema.py ---------------------------------------------------------------------- fixed an obvious bug, added a SchemaError class so it can actually be thrown. ---------------------------------------------------------------------- 2003-05-13 20:22 blunck2 * SOAPpy/wstools/WSDLTools.py: changed references to classes that exist within this module. 2003-05-09 08:46 warnes * README, TODO, setup.py, SOAPpy/Client.py, SOAPpy/Config.py, SOAPpy/Errors.py, SOAPpy/NS.py, SOAPpy/Parser.py, SOAPpy/SOAP.py, SOAPpy/SOAPBuilder.py, SOAPpy/Server.py, SOAPpy/Types.py, SOAPpy/Utilities.py, SOAPpy/WSDL.py, SOAPpy/__init__.py, tests/SOAPtest.py, tests/TCtest.py, tests/alanbushTest.py, tests/cardClient.py, tests/cardServer.py, tests/echoClient.py, tests/echoServer.py, tests/excelTest.py, tests/fortuneTest.py, tests/guidTest.py, tests/itimeTest.py, tests/newsTest.py, tests/quoteTest.py, tests/quoteTest1.py, tests/quoteTest2.py, tests/speedTest.py, tests/storageTest.py, tests/testWSDL.py, tests/translateTest.py, tests/weatherTest.py, tests/whoisTest.py, tests/wordFindTest.py, tests/xmethods.py: - Merge changes splitting SOAP.py file into 10 separate files. This should make the source much easier to navigate. 2003-05-09 03:17 warnes * setup.py, SOAPpy/Client.py, SOAPpy/Parser.py, SOAPpy/SOAP.py, SOAPpy/Server.py, SOAPpy/Utilities.py, SOAPpy/WSDL.py, SOAPpy/__init__.py, tests/SOAPtest.py, tests/TCtest.py, tests/alanbushTest.py, tests/cardClient.py, tests/cardServer.py, tests/echoClient.py, tests/echoServer.py, tests/excelTest.py, tests/newsTest.py, tests/quoteTest.py, tests/speedTest.py, tests/storageTest.py, tests/testWSDL.py, tests/translateTest.py, tests/weatherTest.py: - Many changes associated with splitting SOAP.py into separate files. - Added Mark Bucciarelli's patch to provide wsdl code on properly structured .GET requests 2003-05-09 02:41 warnes * tests/translateTest.py: - Added code to check for http_proxy environment variable and 'do the right thing' (tm). 2003-05-09 02:39 warnes * tests/whoisTest.py: - Updated to use whois SOAP service provided by www.SoapClient.com 2003-05-09 02:23 warnes * tests/wordFindTest.py: - Service no longer exists. 2003-05-09 02:16 warnes * tests/: quoteTest1.py, quoteTest2.py: - Service no longer exists. 2003-05-09 02:13 warnes * tests/xmethods.py: - Added test out to xmethods.net, which looks like a stable site with lots of useful SOAP/WSDL/... stuff. 2003-05-09 02:13 warnes * tests/itimeTest.py: - Service no longer exists. 2003-05-08 23:44 warnes * tests/guidTest.py: - The target SOAP server no longer exists. 2003-05-08 23:14 warnes * tests/fortuneTest.py: - The target server no longer exists. Delete test. 2003-05-08 17:32 warnes * TODO: - Add TODO file. 2003-05-08 17:29 warnes * README, setup.py, SOAPpy/Client.py, SOAPpy/Config.py, SOAPpy/Errors.py, SOAPpy/NS.py, SOAPpy/Parser.py, SOAPpy/SOAP.py, SOAPpy/SOAPBuilder.py, SOAPpy/Server.py, SOAPpy/Types.py, SOAPpy/Utilities.py, SOAPpy/__init__.py, tests/cardClient.py, tests/excelTest.py, tests/testWSDL.py: - Split up the monolithic SOAPpy/SOAP.py into separate files. This should make SOAPpy easier to maintain. - Other incidental changes.. 2003-05-08 13:26 rsalz * SOAPpy/: WSDL.py, wstools/ServiceProxy.py, wstools/__init__.py: Finish up what Mark Bucciarelli kicked off and I started with commit a little while ago. :) That is, wstools is now independant of SOAPpy and ZSI. This commit does the following: wstools/ServiceProxy.py is now ZSI/ServiceProxy.py, so some imports and ZSI docs had to change. ZSI needs some changing, in case I didn't patch up all the imports right. 2003-05-08 12:58 rsalz * SOAPpy/wstools/: ServiceProxy.py, WSDLTools.py: Move some stuff from ServiceProxy (which imports ZSI) to WSDLTools (which doesn't), so that SOAPpy can use wstools without needing ZSI around... which is kinda the point of generic common-code. :) class SOAPCallInfo: class ParameterInfo: class HeaderInfo(ParameterInfo): def callInfoFromWSDL(port, name): Next step is to move what's left of wstools/ServiceProxy.py into the ZSI module (and fix up the imports), so that wstools has *no* soap-stack-specific code in it. 2003-05-07 17:07 warnes * SOAPpy/SOAP.py: - Fixed XML parse error memory leak fix to still raise the error... 2003-05-07 12:50 warnes * SOAPpy/SOAP.py: - Applied patch by bstpierre, which he suggested to fix memory leaks in bug report 544572 (see http://sourceforge.net/tracker/index.php?func=detail&aid=544572&group_id=26590&atid=387667). The leaks seem to have been corrected by other patches, but the suggested code is cleaner, so I've applied it anyway. 2003-05-07 11:34 warnes * SOAPpy/SOAP.py: - Applied patch by Mark Bucciarelli to fix memory leak when the SAX parser throws an exception. 2003-05-07 10:39 warnes * SOAPpy/SOAP.py: - Commit memory leak fix patch submitted by Jeremy Fincher (jemfinch). 2003-04-30 15:38 warnes * SOAPpy/SOAP.py: - Fixed display of exception when an internal error happens. 2003-04-29 10:53 rsalz * SOAPpy/wstools/: ServiceProxy.py, Utility.py: Remove DOS line-ending ^M chars 2003-04-28 10:59 rsalz * SOAPpy/wstools/.cvsignore: Move .cvsignore from ZSI/wsdl to wstools 2003-04-28 09:57 tag SOAPpy_0_9_9_pre5 2003-04-28 09:57 warnes * SOAPpy/SOAP.py: - Updated version number 2003-04-28 09:56 warnes * CHANGELOG, MANIFEST.in, README, SOAPpy/WSDL.py, SOAPpy/__init__.py, tests/TemperatureService.wsdl, tests/testWSDL.py: - Added client support for WSDL, ported from ZSI by Mark Bucciarelli 2003-04-24 22:50 warnes * setup.py, SOAPpy/SOAP.py, SOAPpy/__init__.py: - More changes associated with moving ZSI/SOAPpy common code into wstools CVS package. 2003-04-24 19:08 warnes * setup.py, SOAPpy/SOAP.py, SOAPpy/XMLname.py, SOAPpy/__init__.py, SOAPpy/ieee754.py: - Moved XMLname.py and ieee754 to the wstools CVS package. - Modified SOAPpy to include these files from thier new location. 2003-04-24 13:45 warnes * SOAPpy/wstools/: XMLname.py, __init__.py, ieee754.py: - Moved XMLname.py and ieee754.py into the wstools CVS package from SOAPpy/SOAPpy. 2003-04-24 13:03 rsalz * SOAPpy/wstools/: ServiceProxy.py, TimeoutSocket.py, Utility.py, WSDLTools.py, XMLSchema.py, ZPL, __init__.py: Import files from (now outdated) ZSI/wsdl directory 2003-03-27 11:36 warnes * CHANGELOG, SOAPpy/SOAP.py: Updated version to 0.9.9-pre3 and added reason to changelog. 2003-03-27 11:22 warnes * SOAPpy/SOAP.py: - Only define SOAPUnixSocketServer if the Unix domain sockets are supported 2003-03-27 08:10 tag REL_0_9_9_pre2 2003-03-27 08:10 warnes * CHANGELOG: - Added named scope change. 2003-03-27 08:07 warnes * SOAPpy/SOAP.py: - New argument handling codes needs nested scopes. 2003-03-27 07:32 warnes * CHANGELOG, README, RELEASE_INFO: - Updated text files for 0.9.9-pre2 release. 2003-03-26 16:12 warnes * SOAPpy/SOAP.py: - Update version number to 0.9.9-pre2 2003-03-26 12:55 warnes * SOAPpy/__init__.py: - Added import of ieee754. 2003-03-26 12:54 warnes * SOAPpy/ieee754.py: - Fixed type in __doc__ text. 2003-03-26 11:29 warnes * SOAPpy/SOAP.py: - Split class SOAPServer into SOAPServerBase and two sublcasses, SOAPServer and SOAPUnixSocketServer. SOAPServer has the same functionality as before, while SOAPUnixSocketServer connects over a Unix domain socket instead of to a (public) TCP/IP port. 2003-03-26 00:02 tag REL_0_9_9_pre1 2003-03-26 00:02 warnes * CHANGELOG: - Updated to note addition of ieee754 module and changes enablein MS-Windows support 2003-03-25 23:51 warnes * SOAPpy/: SOAP.py, ieee754.py: - Added ieee754.py, which handles checking for IEEE 754 special values: Inf, -Inf, NaN, ... - Updated SOAP.py to use the new ieee754 module instead of the old (broken) windows hack. 2003-03-25 15:53 warnes * SOAPpy/SOAP.py: - Reversed version string to 0.9.9-pre1. 2003-03-25 15:45 warnes * CHANGELOG, README.MethodParameterNaming, SOAPpy/SOAP.py: - specialArgs handling is now enabled by default. 2003-03-25 15:26 warnes * setup.py: - Modified setup.py to get version number directly from SOAPpy/SOAP.py's __version__ variable. 2003-03-25 12:53 warnes * SOAPpy/SOAP.py: - Changed all references from actzero.com to pywebsvcs.sf.net. 2003-03-25 12:02 warnes * SOAPpy/SOAP.py: - Unnamed arguments which were lists were being incorrectly given the name 'Result'. 2003-03-12 03:14 tag REL_0_9_8 2003-03-12 03:14 warnes * MANIFEST.in: - Added MANIFEST.in: needed by setup.py to create source distribution. 2003-03-12 02:53 warnes * tests/: SOAPtest.py, TCtest.py, echoClient.py, echoServer.py, excelTest.py, speedTest.py: - Updates related to change in structure to allow installation using python distutils (i.e. setup.py) 2003-03-12 02:47 warnes * setup.py: - Updated version number to 0.9.8 2003-03-12 02:38 warnes * CHANGELOG: - Noted directory restructuring in CHANGELOG. 2003-03-08 00:10 warnes * CHANGELOG, README, setup.py, SOAPpy/__init__.py, bid/inventoryClient.py, bid/inventoryServer.py, bid/monitorClient.py, contrib/soap_cli.py, contrib/soap_handler.py, tests/alanbushTest.py, tests/cardClient.py, tests/cardServer.py, tests/fortuneTest.py, tests/guidTest.py, tests/itimeTest.py, tests/newsTest.py, tests/quoteTest.py, tests/quoteTest1.py, tests/quoteTest2.py, tests/storageTest.py, tests/translateTest.py, tests/weatherTest.py, tests/whoisTest.py, tests/wordFindTest.py, validate/silabclient.py, validate/silabserver.py, validate/soapware.py: - Updates related to change in structure to allow installation using python distutils (i.e. setup.py) 2003-03-08 00:07 warnes * SOAPpy/SOAP.py: - implemented an experimental method of handling method argument names. 2003-03-08 00:00 warnes * README.MethodParameterNaming: - Fixed typos, improved wording and formatting. 2003-03-05 16:43 warnes * setup.py: - Initial version of setup.py. Not yet tested! 2003-02-10 12:06 rsalz * SOAPpy.spec: Add RPM spec file from Antonio Beamud Montero (http://www.agoratechnologies.com). Temporary fix until a setup.py file is written. 2002-08-06 14:26 tag Release_1_0_0_beta3 2002-08-06 14:26 blunck2 * SOAPpy/SOAP.py: - Changed invoke method in SOAPProxy class to return the value from the __call invocation (there was previously no way to extract the return values from the call) 2002-07-30 22:28 blunck2 * SOAPpy/SOAP.py: HTTPTransport.call(..) returns the response message from the HTTP request regardless of the value of config.dumpSOAPIn. I removed the conditional logic around the fetching of the response message so that prior to the call to getNS, the data is guaranteed to be there. 2002-07-30 20:30 warnes * CHANGELOG, README, SOAPpy/SOAP.py: - Added 'no namespace' check to namespace-rewriting code to avoid problems when no namespace is specified. - Updated CHANGELOG and README - Added noroot parameter to the SOAPBuilder and SOAPProxy objects in order to provide compatibility with an older version of EasySOAP (v0.2) that balked if the SOAP-ENC:root parameter was included.(Brad Knotwell) 2002-07-25 17:38 blunck2 * SOAPpy/SOAP.py: - Added support for namespace-rewriting (used by Apache v2.x SOAP server for error conditions as well as stateful communication) - Added string <-> str conversion for array types (Python 2.2+) - Added convenience method (invoke) to SOAPProxy that calls __call (not sure if it is necessary - feel free to remove if you want) 2002-07-25 15:43 warnes * SOAPpy/SOAP.py: - Python 'float' are equivalent to SOAP 'double'. Modified dump_float and dump_list to use SOAP type string 'double' appropriately. 2002-06-27 15:44 tag Release_0_1_b2 2002-06-27 15:44 tag Release_0_1b2 2002-06-27 15:44 warnes * SOAPpy/SOAP.py: - Patch from Brad Knotwell [b.knotwell@f5.com] to add basic authentication: Hi Gregory-- This is untested (except for running some of the example programs to ensure it didn't break anything). However, it's trivial enough (and copied almost verbatim from ZSI. . .I helped Rich with Authorization there as well) that I would be pretty confident about committing it. My primary assumption in saying this is that the Authorization header can show up *anywhere* in the header stream and that I've inserted the putheader in the right method call. --Brad 2002-05-24 17:38 warnes * SOAPpy/SOAP.py: Fixes to enble proper handling of SOAP faults by the client. - Fixed test of whether message content is text/xml when recieving a fault. - Added __call__ method to exception classes to match the current API. - The faultType.__repr__() method now print details if present 2002-05-10 10:56 warnes * SOAPpy/: SOAP.py, XMLname.py, __init__.py: - Added XMLnam.py which provides toXMLname() and fromXMLname() for properly encoding xml tag names per the SOAP 2.1 (draft) specification. - Added calls to toXMLname() and fromXMLname() so that tags names are properly encoded. This resolves bug [ 548785 ] 'Error passing dict keys containing space.' - Added code to cgi encode contents of tags when they are not a recognized type. Fixes bug [ 549551 ] 'Error when passing non-standard types'. - Added __init__.py, so that SOAPpy can be used like a standard python module. 2002-02-26 22:19 gliptak * SOAPpy/SOAP.py, tests/SOAPtest.py: Use array for string concat when building messages 2002-02-26 21:33 gliptak * SOAPpy/SOAP.py, tests/SOAPtest.py: Correcting arrayType struct typo 2002-02-26 20:14 gliptak * tests/quoteTest2.py: Another quote test using mybubble.com 2002-02-26 20:13 gliptak * tests/SOAPtest.py: Added test for parameter ordering 2002-02-26 20:11 gliptak * SOAPpy/SOAP.py: Support for explicit parameter ordering 2002-02-25 22:34 gliptak * tests/translateTest.py: Correcting URL and URN 2002-02-25 22:25 gliptak * tests/guidTest.py: Correcting URL 2002-02-25 22:17 gliptak * tests/alanbushTest.py: Correct URI and list categories 2002-02-25 22:06 gliptak * tests/SOAPtest.py: Modified to use PyUnit 2002-02-25 16:47 gliptak * tests/SOAPtest.py: Do not fail for large double parsing for Python 2.2 2002-02-25 10:57 gliptak * SOAPpy/SOAP.py: Fixing abs(None) traceback 2002-02-24 21:50 gliptak * tests/quoteTest1.py: Another quote service test 2002-02-24 21:48 gliptak * tests/wordFindTest.py: Corrected import path 2002-02-24 21:46 gliptak * SOAPpy/SOAP.py: Aliases for Python 2.2 (lib\types.py definitions changed) 2001-11-05 14:19 tag REL_0_9_9_pre5 2001-11-05 14:19 tag v1_2RC4 2001-11-05 14:19 tag v1_2RC5 2001-11-05 14:19 tag v1_2RC6 2001-11-05 14:19 rsalz * .cvsignore, bid/.cvsignore, contrib/.cvsignore, tests/.cvsignore, tools/.cvsignore, validate/.cvsignore: add .cvsignore 2001-07-06 14:03 tag v1_2RC1 2001-07-06 14:03 tag v1_2RC2 2001-07-06 14:03 tag v1_2RC3 2001-07-06 14:03 cullman * SOAPpy/SOAP.py: Fixed the memory leak. 2001-06-28 16:13 cullman * SOAPpy/SOAP.py: Fixed the 500 return code is always a SOAP response "issue". 2001-06-27 18:33 tag REL_0_9_6 2001-06-27 18:33 cullman * CHANGELOG: More changelog changes. 2001-06-27 18:30 cullman * contrib/soap_handler.py: Adding the contributed soap_handler. 2001-06-27 18:29 cullman * contrib/soap_cli.py: Added the medusa example files contributed by Ng. 2001-06-27 18:13 cullman * CHANGELOG: Added a description of the latest release. 2001-06-27 17:36 tag start 2001-06-27 17:36 cullman * CHANGELOG, README, SOAPpy/SOAP.py, bid/inventory.servers, bid/inventoryClient.py, bid/inventoryServer.py, bid/monitorClient.py, docs/quickstart.txt, docs/simpleTypes.txt, tests/SOAPtest.py, tests/TCtest.py, tests/echoClient.py, tests/echoServer.py, tests/excelTest.py, tests/speedTest.py, docs/attrs.txt, docs/complexTypes.txt, tests/alanbushTest.py, tests/cardClient.py, tests/cardServer.py, tests/fortuneTest.py, tests/guidTest.py, tests/itimeTest.py, tests/newsTest.py, tests/quoteTest.py, tests/storageTest.py, tests/translateTest.py, tests/weatherTest.py, tests/whoisTest.py, tests/wordFindTest.py, tools/interop2html.py, validate/server.pem, validate/silab.servers, validate/silabclient.py, validate/silabserver.py, validate/soapware.py: Initial SOAP.py check in. 2001-06-27 17:36 cullman * CHANGELOG, README, SOAPpy/SOAP.py, bid/inventory.servers, bid/inventoryClient.py, bid/inventoryServer.py, bid/monitorClient.py, docs/quickstart.txt, docs/simpleTypes.txt, tests/SOAPtest.py, tests/TCtest.py, tests/echoClient.py, tests/echoServer.py, tests/excelTest.py, tests/speedTest.py, docs/attrs.txt, docs/complexTypes.txt, tests/alanbushTest.py, tests/cardClient.py, tests/cardServer.py, tests/fortuneTest.py, tests/guidTest.py, tests/itimeTest.py, tests/newsTest.py, tests/quoteTest.py, tests/storageTest.py, tests/translateTest.py, tests/weatherTest.py, tests/whoisTest.py, tests/wordFindTest.py, tools/interop2html.py, validate/server.pem, validate/silab.servers, validate/silabclient.py, validate/silabserver.py, validate/soapware.py: Initial revision SOAPpy-0.12.22/setup.py000066400000000000000000000015631235077700100145120ustar00rootroot00000000000000#!/usr/bin/env python # # $Id: setup.py,v 1.11 2005/02/15 16:32:22 warnes Exp $ CVS=0 from setuptools import setup, find_packages import os def read(*rnames): return "\n"+ open( os.path.join('.', *rnames) ).read() url="https://github.com/kiorky/SOAPpy.git" long_description="SOAPpy provides tools for building SOAP clients and servers. For more information see " + url\ +'\n'+read('README.txt')\ +'\n'+read('CHANGES.txt') setup( name="SOAPpy", version='0.12.22', description="SOAP Services for Python", maintainer="Gregory Warnes, kiorky", maintainer_email="Gregory.R.Warnes@Pfizer.com, kiorky@cryptelium.net", url = url, long_description=long_description, packages=find_packages('src'), package_dir = {'': 'src'}, include_package_data=True, install_requires=[ 'wstools', 'defusedxml', ] ) SOAPpy-0.12.22/src/000077500000000000000000000000001235077700100135625ustar00rootroot00000000000000SOAPpy-0.12.22/src/SOAPpy/000077500000000000000000000000001235077700100146755ustar00rootroot00000000000000SOAPpy-0.12.22/src/SOAPpy/Client.py000066400000000000000000000467011235077700100164750ustar00rootroot00000000000000""" ################################################################################ # # SOAPpy - Cayce Ullman (cayce@actzero.com) # Brian Matthews (blm@actzero.com) # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) # Christopher Blunck (blunck@gst.com) # ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ from __future__ import nested_scopes ident = '$Id: Client.py 1496 2010-03-04 23:46:17Z pooryorick $' from version import __version__ #import xml.sax import urllib from types import * import re import base64 import socket, httplib from httplib import HTTPConnection, HTTP import Cookie # SOAPpy modules from Errors import * from Config import Config from Parser import parseSOAPRPC from SOAPBuilder import buildSOAP from Utilities import * from Types import faultType, simplify ################################################################################ # Client ################################################################################ def SOAPUserAgent(): return "SOAPpy " + __version__ + " (pywebsvcs.sf.net)" class SOAPAddress: def __init__(self, url, config = Config): proto, uri = urllib.splittype(url) # apply some defaults if uri[0:2] != '//': if proto != None: uri = proto + ':' + uri uri = '//' + uri proto = 'http' host, path = urllib.splithost(uri) try: int(host) host = 'localhost:' + host except: pass if not path: path = '/' if proto not in ('http', 'https', 'httpg'): raise IOError, "unsupported SOAP protocol" if proto == 'httpg' and not config.GSIclient: raise AttributeError, \ "GSI client not supported by this Python installation" if proto == 'https' and not config.SSLclient: raise AttributeError, \ "SSL client not supported by this Python installation" self.user,host = urllib.splituser(host) self.proto = proto self.host = host self.path = path def __str__(self): return "%(proto)s://%(host)s%(path)s" % self.__dict__ __repr__ = __str__ class SOAPTimeoutError(socket.timeout): '''This exception is raised when a timeout occurs in SOAP operations''' pass class HTTPConnectionWithTimeout(HTTPConnection): '''Extend HTTPConnection for timeout support''' def __init__(self, host, port=None, strict=None, timeout=None): HTTPConnection.__init__(self, host, port, strict) self._timeout = timeout def connect(self): HTTPConnection.connect(self) if self.sock and self._timeout: self.sock.settimeout(self._timeout) class HTTPWithTimeout(HTTP): _connection_class = HTTPConnectionWithTimeout def __init__(self, host='', port=None, strict=None, timeout=None): """Slight modification of superclass (httplib.HTTP) constructor. The only change is that arg ``timeout`` is also passed in the initialization of :attr:`_connection_class`. :param timeout: for the socket connection (seconds); None to disable :type timeout: float or None """ if port == 0: port = None self._setup(self._connection_class(host, port, strict, timeout)) class HTTPTransport: def __init__(self): self.cookies = Cookie.SimpleCookie(); def getNS(self, original_namespace, data): """Extract the (possibly extended) namespace from the returned SOAP message.""" if type(original_namespace) == StringType: pattern="xmlns:\w+=['\"](" + original_namespace + "[^'\"]*)['\"]" match = re.search(pattern, data) if match: return match.group(1) else: return original_namespace else: return original_namespace def __addcookies(self, r): '''Add cookies from self.cookies to request r ''' for cname, morsel in self.cookies.items(): attrs = [] value = morsel.get('version', '') if value != '' and value != '0': attrs.append('$Version=%s' % value) attrs.append('%s=%s' % (cname, morsel.coded_value)) value = morsel.get('path') if value: attrs.append('$Path=%s' % value) value = morsel.get('domain') if value: attrs.append('$Domain=%s' % value) r.putheader('Cookie', "; ".join(attrs)) def call(self, addr, data, namespace, soapaction = None, encoding = None, http_proxy = None, config = Config, timeout=None): if not isinstance(addr, SOAPAddress): addr = SOAPAddress(addr, config) # Build a request if http_proxy: real_addr = http_proxy real_path = addr.proto + "://" + addr.host + addr.path else: real_addr = addr.host real_path = addr.path if addr.proto == 'httpg': from pyGlobus.io import GSIHTTP r = GSIHTTP(real_addr, tcpAttr = config.tcpAttr) elif addr.proto == 'https': r = httplib.HTTPS(real_addr, key_file=config.SSL.key_file, cert_file=config.SSL.cert_file) else: r = HTTPWithTimeout(real_addr, timeout=timeout) r.putrequest("POST", real_path) r.putheader("Host", addr.host) r.putheader("User-agent", SOAPUserAgent()) t = 'text/xml'; if encoding != None: t += '; charset=%s' % encoding r.putheader("Content-type", t) r.putheader("Content-length", str(len(data))) self.__addcookies(r); # if user is not a user:passwd format # we'll receive a failure from the server. . .I guess (??) if addr.user != None: val = base64.encodestring(urllib.unquote_plus(addr.user)) r.putheader('Authorization','Basic ' + val.replace('\012','')) # This fixes sending either "" or "None" if soapaction == None or len(soapaction) == 0: r.putheader("SOAPAction", "") else: r.putheader("SOAPAction", '"%s"' % soapaction) if config.dumpHeadersOut: s = 'Outgoing HTTP headers' debugHeader(s) print "POST %s %s" % (real_path, r._http_vsn_str) print "Host:", addr.host print "User-agent: SOAPpy " + __version__ + " (http://pywebsvcs.sf.net)" print "Content-type:", t print "Content-length:", len(data) print 'SOAPAction: "%s"' % soapaction debugFooter(s) r.endheaders() if config.dumpSOAPOut: s = 'Outgoing SOAP' debugHeader(s) print data, if data[-1] != '\n': print debugFooter(s) # send the payload r.send(data) # read response line code, msg, headers = r.getreply() self.cookies = Cookie.SimpleCookie(); if headers: content_type = headers.get("content-type","text/xml") content_length = headers.get("Content-length") for cookie in headers.getallmatchingheaders("Set-Cookie"): self.cookies.load(cookie); else: content_type=None content_length=None # work around OC4J bug which does ', ' for some reaason if content_length: comma=content_length.find(',') if comma>0: content_length = content_length[:comma] # attempt to extract integer message size try: message_len = int(content_length) except: message_len = -1 f = r.getfile() if f is None: raise HTTPError(code, "Empty response from server\nCode: %s\nHeaders: %s" % (msg, headers)) if message_len < 0: # Content-Length missing or invalid; just read the whole socket # This won't work with HTTP/1.1 chunked encoding data = f.read() message_len = len(data) else: data = f.read(message_len) if(config.debug): print "code=",code print "msg=", msg print "headers=", headers print "content-type=", content_type print "data=", data if config.dumpHeadersIn: s = 'Incoming HTTP headers' debugHeader(s) if headers.headers: print "HTTP/1.? %d %s" % (code, msg) print "\n".join(map (lambda x: x.strip(), headers.headers)) else: print "HTTP/0.9 %d %s" % (code, msg) debugFooter(s) def startswith(string, val): return string[0:len(val)] == val if code == 500 and not \ ( startswith(content_type, "text/xml") and message_len > 0 ): raise HTTPError(code, msg) if config.dumpSOAPIn: s = 'Incoming SOAP' debugHeader(s) print data, if (len(data)>0) and (data[-1] != '\n'): print debugFooter(s) if code not in (200, 500): raise HTTPError(code, msg) # get the new namespace if namespace is None: new_ns = None else: new_ns = self.getNS(namespace, data) # return response payload return data, new_ns ################################################################################ # SOAP Proxy ################################################################################ class SOAPProxy: def __init__(self, proxy, namespace = None, soapaction = None, header = None, methodattrs = None, transport = HTTPTransport, encoding = 'UTF-8', throw_faults = 1, unwrap_results = None, http_proxy=None, config = Config, noroot = 0, simplify_objects=None, timeout=None): # Test the encoding, raising an exception if it's not known if encoding != None: ''.encode(encoding) # get default values for unwrap_results and simplify_objects # from config if unwrap_results is None: self.unwrap_results=config.unwrap_results else: self.unwrap_results=unwrap_results if simplify_objects is None: self.simplify_objects=config.simplify_objects else: self.simplify_objects=simplify_objects self.proxy = SOAPAddress(proxy, config) self.namespace = namespace self.soapaction = soapaction self.header = header self.methodattrs = methodattrs self.transport = transport() self.encoding = encoding self.throw_faults = throw_faults self.http_proxy = http_proxy self.config = config self.noroot = noroot self.timeout = timeout # GSI Additions if hasattr(config, "channel_mode") and \ hasattr(config, "delegation_mode"): self.channel_mode = config.channel_mode self.delegation_mode = config.delegation_mode #end GSI Additions def invoke(self, method, args): return self.__call(method, args, {}) def __call(self, name, args, kw, ns = None, sa = None, hd = None, ma = None): ns = ns or self.namespace ma = ma or self.methodattrs if sa: # Get soapaction if type(sa) == TupleType: sa = sa[0] else: if self.soapaction: sa = self.soapaction else: sa = name if hd: # Get header if type(hd) == TupleType: hd = hd[0] else: hd = self.header hd = hd or self.header if ma: # Get methodattrs if type(ma) == TupleType: ma = ma[0] else: ma = self.methodattrs ma = ma or self.methodattrs m = buildSOAP(args = args, kw = kw, method = name, namespace = ns, header = hd, methodattrs = ma, encoding = self.encoding, config = self.config, noroot = self.noroot) call_retry = 0 try: r, self.namespace = self.transport.call(self.proxy, m, ns, sa, encoding = self.encoding, http_proxy = self.http_proxy, config = self.config, timeout = self.timeout) except socket.timeout: raise SOAPTimeoutError except Exception, ex: # # Call failed. # # See if we have a fault handling vector installed in our # config. If we do, invoke it. If it returns a true value, # retry the call. # # In any circumstance other than the fault handler returning # true, reraise the exception. This keeps the semantics of this # code the same as without the faultHandler code. # if hasattr(self.config, "faultHandler"): if callable(self.config.faultHandler): call_retry = self.config.faultHandler(self.proxy, ex) if not call_retry: raise else: raise else: raise if call_retry: try: r, self.namespace = self.transport.call(self.proxy, m, ns, sa, encoding = self.encoding, http_proxy = self.http_proxy, config = self.config, timeout = self.timeout) except socket.timeout: raise SOAPTimeoutError p, attrs = parseSOAPRPC(r, attrs = 1) try: throw_struct = self.throw_faults and \ isinstance (p, faultType) except: throw_struct = 0 if throw_struct: if self.config.debug: print p raise p # If unwrap_results=1 and there is only element in the struct, # SOAPProxy will assume that this element is the result # and return it rather than the struct containing it. # Otherwise SOAPproxy will return the struct with all the # elements as attributes. if self.unwrap_results: try: count = 0 for i in p.__dict__.keys(): if i[0] != "_": # don't count the private stuff count += 1 t = getattr(p, i) if count == 1: # Only one piece of data, bubble it up p = t except: pass # Automatically simplfy SOAP complex types into the # corresponding python types. (structType --> dict, # arrayType --> array, etc.) if self.simplify_objects: p = simplify(p) if self.config.returnAllAttrs: return p, attrs return p def _callWithBody(self, body): return self.__call(None, body, {}) def __getattr__(self, name): # hook to catch method calls if name in ( '__del__', '__getinitargs__', '__getnewargs__', '__getstate__', '__setstate__', '__reduce__', '__reduce_ex__'): raise AttributeError, name return self.__Method(self.__call, name, config = self.config) # To handle attribute weirdness class __Method: # Some magic to bind a SOAP method to an RPC server. # Supports "nested" methods (e.g. examples.getStateName) -- concept # borrowed from xmlrpc/soaplib -- www.pythonware.com # Altered (improved?) to let you inline namespaces on a per call # basis ala SOAP::LITE -- www.soaplite.com def __init__(self, call, name, ns = None, sa = None, hd = None, ma = None, config = Config): self.__call = call self.__name = name self.__ns = ns self.__sa = sa self.__hd = hd self.__ma = ma self.__config = config return def __call__(self, *args, **kw): if self.__name[0] == "_": if self.__name in ["__repr__","__str__"]: return self.__repr__() else: return self.__f_call(*args, **kw) else: return self.__r_call(*args, **kw) def __getattr__(self, name): if name == '__del__': raise AttributeError, name if self.__name[0] == "_": # Don't nest method if it is a directive return self.__class__(self.__call, name, self.__ns, self.__sa, self.__hd, self.__ma) return self.__class__(self.__call, "%s.%s" % (self.__name, name), self.__ns, self.__sa, self.__hd, self.__ma) def __f_call(self, *args, **kw): if self.__name == "_ns": self.__ns = args elif self.__name == "_sa": self.__sa = args elif self.__name == "_hd": self.__hd = args elif self.__name == "_ma": self.__ma = args return self def __r_call(self, *args, **kw): return self.__call(self.__name, args, kw, self.__ns, self.__sa, self.__hd, self.__ma) def __repr__(self): return "<%s at %d>" % (self.__class__, id(self)) SOAPpy-0.12.22/src/SOAPpy/Config.py000066400000000000000000000201771235077700100164630ustar00rootroot00000000000000""" ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ ident = '$Id: Config.py 1298 2006-11-07 00:54:15Z sanxiyn $' from version import __version__ import socket from types import * from NS import NS ################################################################################ # Configuration class ################################################################################ class SOAPConfig: __readonly = ('SSLserver', 'SSLclient', 'GSIserver', 'GSIclient') class SSLconfig: __slots__ = ('key_file', 'cert_file') key_file = None cert_file = None def __init__(self, config = None, **kw): d = self.__dict__ if config: if not isinstance(config, SOAPConfig): raise AttributeError, \ "initializer must be SOAPConfig instance" s = config.__dict__ for k, v in s.items(): if k[0] != '_': d[k] = v else: # Setting debug also sets returnFaultInfo, # dumpHeadersIn, dumpHeadersOut, dumpSOAPIn, and dumpSOAPOut self.debug = 0 self.dumpFaultInfo = 1 # Setting namespaceStyle sets typesNamespace, typesNamespaceURI, # schemaNamespace, and schemaNamespaceURI self.namespaceStyle = '1999' self.strictNamespaces = 0 self.typed = 1 self.buildWithNamespacePrefix = 1 self.buildWithGlobalNamespacePrefix = False self.returnAllAttrs = 0 # Strict checking of range for floats and doubles self.strict_range = 0 # Default encoding for dictionary keys self.dict_encoding = 'ascii' # New argument name handling mechanism. See # README.MethodParameterNaming for details self.specialArgs = 1 # If unwrap_results=1 and there is only element in the struct, # SOAPProxy will assume that this element is the result # and return it rather than the struct containing it. # Otherwise SOAPproxy will return the struct with all the # elements as attributes. self.unwrap_results = 1 # Automatically convert SOAP complex types, and # (recursively) public contents into the corresponding # python types. (Private subobjects have names that start # with '_'.) # # Conversions: # - faultType --> raise python exception # - arrayType --> array # - compoundType --> dictionary # self.simplify_objects = 0 # Per-class authorization method. If this is set, before # calling a any class method, the specified authorization # method will be called. If it returns 1, the method call # will proceed, otherwise the call will throw with an # authorization error. self.authMethod = None # The tuple of type and dump handler function pairs for # SOAPBuilder dump dispatch. Used for handling additional types # and overriding built-in types. Functions are expected to have # the same parameters as SOAPBuilder dump_ methods # (including self; possibility to call any SOAPBuilder dump method) self.dumpmap = tuple() # Globus Support if pyGlobus.io available try: from pyGlobus import io; d['GSIserver'] = 1 d['GSIclient'] = 1 except: d['GSIserver'] = 0 d['GSIclient'] = 0 # Server SSL support if M2Crypto.SSL available try: from M2Crypto import SSL d['SSLserver'] = 1 except: d['SSLserver'] = 0 # Client SSL support if socket.ssl available try: from socket import ssl d['SSLclient'] = 1 except: d['SSLclient'] = 0 # Cert support if d['SSLclient'] or d['SSLserver']: d['SSL'] = self.SSLconfig() dumpmap = kw.pop("dumpmap", None) if dumpmap: if not isinstance(dumpmap, tuple): raise TypeError("Config dumpmap parameter must be a tuple") self.dumpmap = dumpmap + self.dumpmap for k, v in kw.items(): if k[0] != '_': setattr(self, k, v) def __setattr__(self, name, value): if name in self.__readonly: raise AttributeError, "readonly configuration setting" d = self.__dict__ if name in ('typesNamespace', 'typesNamespaceURI', 'schemaNamespace', 'schemaNamespaceURI'): if name[-3:] == 'URI': base, uri = name[:-3], 1 else: base, uri = name, 0 if type(value) == StringType: if NS.NSMAP.has_key(value): n = (value, NS.NSMAP[value]) elif NS.NSMAP_R.has_key(value): n = (NS.NSMAP_R[value], value) else: raise AttributeError, "unknown namespace" elif type(value) in (ListType, TupleType): if uri: n = (value[1], value[0]) else: n = (value[0], value[1]) else: raise AttributeError, "unknown namespace type" d[base], d[base + 'URI'] = n try: d['namespaceStyle'] = \ NS.STMAP_R[(d['typesNamespace'], d['schemaNamespace'])] except: d['namespaceStyle'] = '' elif name == 'namespaceStyle': value = str(value) if not NS.STMAP.has_key(value): raise AttributeError, "unknown namespace style" d[name] = value n = d['typesNamespace'] = NS.STMAP[value][0] d['typesNamespaceURI'] = NS.NSMAP[n] n = d['schemaNamespace'] = NS.STMAP[value][1] d['schemaNamespaceURI'] = NS.NSMAP[n] elif name == 'debug': d[name] = \ d['returnFaultInfo'] = \ d['dumpHeadersIn'] = \ d['dumpHeadersOut'] = \ d['dumpSOAPIn'] = \ d['dumpSOAPOut'] = value else: d[name] = value Config = SOAPConfig() SOAPpy-0.12.22/src/SOAPpy/Errors.py000066400000000000000000000056721235077700100165350ustar00rootroot00000000000000""" ################################################################################ # # SOAPpy - Cayce Ullman (cayce@actzero.com) # Brian Matthews (blm@actzero.com) # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) # Christopher Blunck (blunck@gst.com) # ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ ident = '$Id: Errors.py 921 2005-02-15 16:32:23Z warnes $' from version import __version__ import exceptions ################################################################################ # Exceptions ################################################################################ class Error(exceptions.Exception): def __init__(self, msg): self.msg = msg def __str__(self): return "" % self.msg __repr__ = __str__ def __call__(self): return (msg,) class RecursionError(Error): pass class UnknownTypeError(Error): pass class HTTPError(Error): # indicates an HTTP protocol error def __init__(self, code, msg): self.code = code self.msg = msg def __str__(self): return "" % (self.code, self.msg) __repr__ = __str__ def __call___(self): return (self.code, self.msg, ) class UnderflowError(exceptions.ArithmeticError): pass SOAPpy-0.12.22/src/SOAPpy/GSIServer.py000066400000000000000000000121661235077700100170660ustar00rootroot00000000000000""" GSIServer - Contributed by Ivan R. Judson ################################################################################ # # SOAPpy - Cayce Ullman (cayce@actzero.com) # Brian Matthews (blm@actzero.com) # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) # Christopher Blunck (blunck@gst.com) # ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ from __future__ import nested_scopes ident = '$Id: GSIServer.py 1468 2008-05-24 01:55:33Z warnes $' from version import __version__ #import xml.sax import re import socket import sys import SocketServer from types import * import BaseHTTPServer # SOAPpy modules from Parser import parseSOAPRPC from Config import SOAPConfig from Types import faultType, voidType, simplify from NS import NS from SOAPBuilder import buildSOAP from Utilities import debugHeader, debugFooter try: from M2Crypto import SSL except: pass ##### from Server import * from pyGlobus.io import GSITCPSocketServer, ThreadingGSITCPSocketServer from pyGlobus import ioc def GSIConfig(): config = SOAPConfig() config.channel_mode = ioc.GLOBUS_IO_SECURE_CHANNEL_MODE_GSI_WRAP config.delegation_mode = ioc.GLOBUS_IO_SECURE_DELEGATION_MODE_FULL_PROXY config.tcpAttr = None config.authMethod = "_authorize" return config Config = GSIConfig() class GSISOAPServer(GSITCPSocketServer, SOAPServerBase): def __init__(self, addr = ('localhost', 8000), RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', config = Config, namespace = None): # Test the encoding, raising an exception if it's not known if encoding != None: ''.encode(encoding) self.namespace = namespace self.objmap = {} self.funcmap = {} self.encoding = encoding self.config = config self.log = log self.allow_reuse_address= 1 GSITCPSocketServer.__init__(self, addr, RequestHandler, self.config.channel_mode, self.config.delegation_mode, tcpAttr = self.config.tcpAttr) def get_request(self): sock, addr = GSITCPSocketServer.get_request(self) return sock, addr class ThreadingGSISOAPServer(ThreadingGSITCPSocketServer, SOAPServerBase): def __init__(self, addr = ('localhost', 8000), RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', config = Config, namespace = None): # Test the encoding, raising an exception if it's not known if encoding != None: ''.encode(encoding) self.namespace = namespace self.objmap = {} self.funcmap = {} self.encoding = encoding self.config = config self.log = log self.allow_reuse_address= 1 ThreadingGSITCPSocketServer.__init__(self, addr, RequestHandler, self.config.channel_mode, self.config.delegation_mode, tcpAttr = self.config.tcpAttr) def get_request(self): sock, addr = ThreadingGSITCPSocketServer.get_request(self) return sock, addr SOAPpy-0.12.22/src/SOAPpy/NS.py000066400000000000000000000072141235077700100155730ustar00rootroot00000000000000""" ################################################################################ # # SOAPpy - Cayce Ullman (cayce@actzero.com) # Brian Matthews (blm@actzero.com) # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) # Christopher Blunck (blunck@gst.com) # ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ from __future__ import nested_scopes ident = '$Id: NS.py 1468 2008-05-24 01:55:33Z warnes $' from version import __version__ ############################################################################## # Namespace Class ################################################################################ def invertDict(dict): d = {} for k, v in dict.items(): d[v] = k return d class NS: XML = "http://www.w3.org/XML/1998/namespace" ENV = "http://schemas.xmlsoap.org/soap/envelope/" ENC = "http://schemas.xmlsoap.org/soap/encoding/" XSD = "http://www.w3.org/1999/XMLSchema" XSD2 = "http://www.w3.org/2000/10/XMLSchema" XSD3 = "http://www.w3.org/2001/XMLSchema" XSD_L = [XSD, XSD2, XSD3] EXSD_L= [ENC, XSD, XSD2, XSD3] XSI = "http://www.w3.org/1999/XMLSchema-instance" XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance" XSI3 = "http://www.w3.org/2001/XMLSchema-instance" XSI_L = [XSI, XSI2, XSI3] URN = "http://soapinterop.org/xsd" # For generated messages XML_T = "xml" ENV_T = "SOAP-ENV" ENC_T = "SOAP-ENC" XSD_T = "xsd" XSD2_T= "xsd2" XSD3_T= "xsd3" XSI_T = "xsi" XSI2_T= "xsi2" XSI3_T= "xsi3" URN_T = "urn" NSMAP = {ENV_T: ENV, ENC_T: ENC, XSD_T: XSD, XSD2_T: XSD2, XSD3_T: XSD3, XSI_T: XSI, XSI2_T: XSI2, XSI3_T: XSI3, URN_T: URN} NSMAP_R = invertDict(NSMAP) STMAP = {'1999': (XSD_T, XSI_T), '2000': (XSD2_T, XSI2_T), '2001': (XSD3_T, XSI3_T)} STMAP_R = invertDict(STMAP) def __init__(self): raise Error, "Don't instantiate this" SOAPpy-0.12.22/src/SOAPpy/Parser.py000066400000000000000000001102261235077700100165050ustar00rootroot00000000000000# SOAPpy modules import traceback from Config import Config from Types import * from NS import NS from Utilities import * import string import xml.sax from wstools.XMLname import fromXMLname try: from cStringIO import StringIO except ImportError: from StringIO import StringIO try: from M2Crypto import SSL except: pass from defusedxml import expatreader from defusedxml.common import DefusedXmlException ident = '$Id: Parser.py 1497 2010-03-08 06:06:52Z pooryorick $' from version import __version__ ################################################################################ # SOAP Parser ################################################################################ def make_parser(parser_list=[]): return expatreader.create_parser() class RefHolder: def __init__(self, name, frame): self.name = name self.parent = frame self.pos = len(frame) self.subpos = frame.namecounts.get(name, 0) def __repr__(self): return "<%s %s at %d>" % (self.__class__, self.name, id(self)) def __str__(self): return "<%s %s at %d>" % (self.__class__, self.name, id(self)) class SOAPParser(xml.sax.handler.ContentHandler): class Frame: def __init__(self, name, kind = None, attrs = {}, rules = {}): self.name = name self.kind = kind self.attrs = attrs self.rules = rules self.contents = [] self.names = [] self.namecounts = {} self.subattrs = [] def append(self, name, data, attrs): self.names.append(name) self.contents.append(data) self.subattrs.append(attrs) if self.namecounts.has_key(name): self.namecounts[name] += 1 else: self.namecounts[name] = 1 def _placeItem(self, name, value, pos, subpos = 0, attrs = None): self.contents[pos] = value if attrs: self.attrs.update(attrs) def __len__(self): return len(self.contents) def __repr__(self): return "<%s %s at %d>" % (self.__class__, self.name, id(self)) def __init__(self, rules = None): xml.sax.handler.ContentHandler.__init__(self) self.body = None self.header = None self.attrs = {} self._data = None self._next = "E" # Keeping state for message validity self._stack = [self.Frame('SOAP')] # Make two dictionaries to store the prefix <-> URI mappings, and # initialize them with the default self._prem = {NS.XML_T: NS.XML} self._prem_r = {NS.XML: NS.XML_T} self._ids = {} self._refs = {} self._rules = rules def startElementNS(self, name, qname, attrs): def toStr( name ): prefix = name[0] tag = name[1] if self._prem_r.has_key(prefix): tag = self._prem_r[name[0]] + ':' + name[1] elif prefix: tag = prefix + ":" + tag return tag # Workaround two sax bugs if name[0] == None and name[1][0] == ' ': name = (None, name[1][1:]) else: name = tuple(name) # First some checking of the layout of the message if self._next == "E": if name[1] != 'Envelope': raise Error, "expected `SOAP-ENV:Envelope', " \ "got `%s'" % toStr( name ) if name[0] != NS.ENV: raise faultType, ("%s:VersionMismatch" % NS.ENV_T, "Don't understand version `%s' Envelope" % name[0]) else: self._next = "HorB" elif self._next == "HorB": if name[0] == NS.ENV and name[1] in ("Header", "Body"): self._next = None else: raise Error, \ "expected `SOAP-ENV:Header' or `SOAP-ENV:Body', " \ "got `%s'" % toStr( name ) elif self._next == "B": if name == (NS.ENV, "Body"): self._next = None else: raise Error, "expected `SOAP-ENV:Body', " \ "got `%s'" % toStr( name ) elif self._next == "": raise Error, "expected nothing, " \ "got `%s'" % toStr( name ) if len(self._stack) == 2: rules = self._rules else: try: rules = self._stack[-1].rules[name[1]] except: rules = None if type(rules) not in (NoneType, DictType): kind = rules else: kind = attrs.get((NS.ENC, 'arrayType')) if kind != None: del attrs._attrs[(NS.ENC, 'arrayType')] i = kind.find(':') if i >= 0: try: kind = (self._prem[kind[:i]], kind[i + 1:]) except: kind = None else: kind = None self.pushFrame(self.Frame(name[1], kind, attrs._attrs, rules)) self._data = [] # Start accumulating def pushFrame(self, frame): self._stack.append(frame) def popFrame(self): return self._stack.pop() def endElementNS(self, name, qname): # Workaround two sax bugs if name[0] == None and name[1][0] == ' ': ns, name = None, name[1][1:] else: ns, name = tuple(name) name = fromXMLname(name) # convert to SOAP 1.2 XML name encoding if self._next == "E": raise Error, "didn't get SOAP-ENV:Envelope" if self._next in ("HorB", "B"): raise Error, "didn't get SOAP-ENV:Body" cur = self.popFrame() attrs = cur.attrs idval = None if attrs.has_key((None, 'id')): idval = attrs[(None, 'id')] if self._ids.has_key(idval): raise Error, "duplicate id `%s'" % idval del attrs[(None, 'id')] root = 1 if len(self._stack) == 3: if attrs.has_key((NS.ENC, 'root')): root = int(attrs[(NS.ENC, 'root')]) # Do some preliminary checks. First, if root="0" is present, # the element must have an id. Next, if root="n" is present, # n something other than 0 or 1, raise an exception. if root == 0: if idval == None: raise Error, "non-root element must have an id" elif root != 1: raise Error, "SOAP-ENC:root must be `0' or `1'" del attrs[(NS.ENC, 'root')] while 1: href = attrs.get((None, 'href')) if href: if href[0] != '#': raise Error, "Non-local hrefs are not yet suppported." if self._data != None and \ string.join(self._data, "").strip() != '': raise Error, "hrefs can't have data" href = href[1:] if self._ids.has_key(href): data = self._ids[href] else: data = RefHolder(name, self._stack[-1]) if self._refs.has_key(href): self._refs[href].append(data) else: self._refs[href] = [data] del attrs[(None, 'href')] break kind = None if attrs: for i in NS.XSI_L: if attrs.has_key((i, 'type')): kind = attrs[(i, 'type')] del attrs[(i, 'type')] if kind != None: i = kind.find(':') if i >= 0: try: kind = (self._prem[kind[:i]], kind[i + 1:]) except: kind = (None, kind) else: # XXX What to do here? (None, kind) is just going to fail in convertType #print "Kind with no NS:", kind kind = (None, kind) null = 0 if attrs: for i in (NS.XSI, NS.XSI2): if attrs.has_key((i, 'null')): null = attrs[(i, 'null')] del attrs[(i, 'null')] if attrs.has_key((NS.XSI3, 'nil')): null = attrs[(NS.XSI3, 'nil')] del attrs[(NS.XSI3, 'nil')] ## Check for nil # check for nil='true' if type(null) in (StringType, UnicodeType): if null.lower() == 'true': null = 1 # check for nil=1, but watch out for string values try: null = int(null) except ValueError, e: if not e[0].startswith("invalid literal for int()"): raise e null = 0 if null: if len(cur) or \ (self._data != None and string.join(self._data, "").strip() != ''): raise Error, "nils can't have data" data = None break if len(self._stack) == 2: if (ns, name) == (NS.ENV, "Header"): self.header = data = headerType(attrs = attrs) self._next = "B" break elif (ns, name) == (NS.ENV, "Body"): self.body = data = bodyType(attrs = attrs) self._next = "" break elif len(self._stack) == 3 and self._next == None: if (ns, name) == (NS.ENV, "Fault"): data = faultType() self._next = None # allow followons break #print "\n" #print "data=", self._data #print "kind=", kind #print "cur.kind=", cur.kind #print "cur.rules=", cur.rules #print "\n" if cur.rules != None: rule = cur.rules if type(rule) in (StringType, UnicodeType): rule = (None, rule) # none flags special handling elif type(rule) == ListType: rule = tuple(rule) #print "kind=",kind #print "rule=",rule # XXX What if rule != kind? if callable(rule): data = rule(string.join(self._data, "")) elif type(rule) == DictType: data = structType(name = (ns, name), attrs = attrs) elif rule[1][:9] == 'arrayType': data = self.convertType(cur.contents, rule, attrs) else: data = self.convertType(string.join(self._data, ""), rule, attrs) break #print "No rules, using kind or cur.kind..." if (kind == None and cur.kind != None) or \ (kind == (NS.ENC, 'Array')): kind = cur.kind if kind == None: kind = 'ur-type[%d]' % len(cur) else: kind = kind[1] if len(cur.namecounts) == 1: elemsname = cur.names[0] else: elemsname = None data = self.startArray((ns, name), kind, attrs, elemsname) break if len(self._stack) == 3 and kind == None and \ len(cur) == 0 and \ (self._data == None or string.join(self._data, "").strip() == ''): data = structType(name = (ns, name), attrs = attrs) break if len(cur) == 0 and ns != NS.URN: # Nothing's been added to the current frame so it must be a # simple type. # print "cur:", cur # print "ns:", ns # print "attrs:", attrs # print "kind:", kind if kind == None: # If the current item's container is an array, it will # have a kind. If so, get the bit before the first [, # which is the type of the array, therefore the type of # the current item. kind = self._stack[-1].kind if kind != None: i = kind[1].find('[') if i >= 0: kind = (kind[0], kind[1][:i]) elif ns != None: kind = (ns, name) if kind != None: try: data = self.convertType(string.join(self._data, ""), kind, attrs) except UnknownTypeError: data = None else: data = None if data == None: if self._data == None: data = '' else: data = string.join(self._data, "") if len(attrs) == 0: try: data = str(data) except: pass break data = structType(name = (ns, name), attrs = attrs) break if isinstance(data, compoundType): for i in range(len(cur)): v = cur.contents[i] data._addItem(cur.names[i], v, cur.subattrs[i]) if isinstance(v, RefHolder): v.parent = data if root: self._stack[-1].append(name, data, attrs) if idval != None: self._ids[idval] = data if self._refs.has_key(idval): for i in self._refs[idval]: i.parent._placeItem(i.name, data, i.pos, i.subpos, attrs) del self._refs[idval] self.attrs[id(data)] = attrs if isinstance(data, anyType): data._setAttrs(attrs) self._data = None # Stop accumulating def endDocument(self): if len(self._refs) == 1: raise Error, \ "unresolved reference " + self._refs.keys()[0] elif len(self._refs) > 1: raise Error, \ "unresolved references " + ', '.join(self._refs.keys()) def startPrefixMapping(self, prefix, uri): self._prem[prefix] = uri self._prem_r[uri] = prefix def endPrefixMapping(self, prefix): try: del self._prem_r[self._prem[prefix]] del self._prem[prefix] except: pass def characters(self, c): if self._data != None: self._data.append(c) arrayre = '^(?:(?P[^:]*):)?' \ '(?P[^[]+)' \ '(?:\[(?P,*)\])?' \ '(?:\[(?P\d+(?:,\d+)*)?\])$' def startArray(self, name, kind, attrs, elemsname): if type(self.arrayre) == StringType: self.arrayre = re.compile (self.arrayre) offset = attrs.get((NS.ENC, "offset")) if offset != None: del attrs[(NS.ENC, "offset")] try: if offset[0] == '[' and offset[-1] == ']': offset = int(offset[1:-1]) if offset < 0: raise Exception else: raise Exception except: raise AttributeError, "invalid Array offset" else: offset = 0 try: m = self.arrayre.search(kind) if m == None: raise Exception t = m.group('type') if t == 'ur-type': return arrayType(None, name, attrs, offset, m.group('rank'), m.group('asize'), elemsname) elif m.group('ns') != None: return typedArrayType(None, name, (self._prem[m.group('ns')], t), attrs, offset, m.group('rank'), m.group('asize'), elemsname) else: return typedArrayType(None, name, (None, t), attrs, offset, m.group('rank'), m.group('asize'), elemsname) except: raise AttributeError, "invalid Array type `%s'" % kind # Conversion class DATETIMECONSTS: SIGNre = '(?P-?)' CENTURYre = '(?P\d{2,})' YEARre = '(?P\d{2})' MONTHre = '(?P\d{2})' DAYre = '(?P\d{2})' HOURre = '(?P\d{2})' MINUTEre = '(?P\d{2})' SECONDre = '(?P\d{2}(?:\.\d*)?)' TIMEZONEre = '(?PZ)|(?P[-+])(?P\d{2}):' \ '(?P\d{2})' BOSre = '^\s*' EOSre = '\s*$' __allres = {'sign': SIGNre, 'century': CENTURYre, 'year': YEARre, 'month': MONTHre, 'day': DAYre, 'hour': HOURre, 'minute': MINUTEre, 'second': SECONDre, 'timezone': TIMEZONEre, 'b': BOSre, 'e': EOSre} dateTime = '%(b)s%(sign)s%(century)s%(year)s-%(month)s-%(day)sT' \ '%(hour)s:%(minute)s:%(second)s(%(timezone)s)?%(e)s' % __allres timeInstant = dateTime timePeriod = dateTime time = '%(b)s%(hour)s:%(minute)s:%(second)s(%(timezone)s)?%(e)s' % \ __allres date = '%(b)s%(sign)s%(century)s%(year)s-%(month)s-%(day)s' \ '(%(timezone)s)?%(e)s' % __allres century = '%(b)s%(sign)s%(century)s(%(timezone)s)?%(e)s' % __allres gYearMonth = '%(b)s%(sign)s%(century)s%(year)s-%(month)s' \ '(%(timezone)s)?%(e)s' % __allres gYear = '%(b)s%(sign)s%(century)s%(year)s(%(timezone)s)?%(e)s' % \ __allres year = gYear gMonthDay = '%(b)s--%(month)s-%(day)s(%(timezone)s)?%(e)s' % __allres recurringDate = gMonthDay gDay = '%(b)s---%(day)s(%(timezone)s)?%(e)s' % __allres recurringDay = gDay gMonth = '%(b)s--%(month)s--(%(timezone)s)?%(e)s' % __allres month = gMonth recurringInstant = '%(b)s%(sign)s(%(century)s|-)(%(year)s|-)-' \ '(%(month)s|-)-(%(day)s|-)T' \ '(%(hour)s|-):(%(minute)s|-):(%(second)s|-)' \ '(%(timezone)s)?%(e)s' % __allres duration = '%(b)s%(sign)sP' \ '((?P\d+)Y)?' \ '((?P\d+)M)?' \ '((?P\d+)D)?' \ '((?PT)' \ '((?P\d+)H)?' \ '((?P\d+)M)?' \ '((?P\d*(?:\.\d*)?)S)?)?%(e)s' % \ __allres timeDuration = duration # The extra 31 on the front is: # - so the tuple is 1-based # - so months[month-1] is December's days if month is 1 months = (31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) def convertDateTime(self, value, kind): def getZoneOffset(d): zoffs = 0 try: if d['zulu'] == None: zoffs = 60 * int(d['tzhour']) + int(d['tzminute']) if d['tzsign'] != '-': zoffs = -zoffs except TypeError: pass return zoffs def applyZoneOffset(months, zoffs, date, minfield, posday = 1): if zoffs == 0 and (minfield > 4 or 0 <= date[5] < 60): return date if minfield > 5: date[5] = 0 if minfield > 4: date[4] = 0 if date[5] < 0: date[4] += int(date[5]) / 60 date[5] %= 60 date[4] += zoffs if minfield > 3 or 0 <= date[4] < 60: return date date[3] += date[4] / 60 date[4] %= 60 if minfield > 2 or 0 <= date[3] < 24: return date date[2] += date[3] / 24 date[3] %= 24 if minfield > 1: if posday and date[2] <= 0: date[2] += 31 # zoffs is at most 99:59, so the # day will never be less than -3 return date while 1: # The date[1] == 3 (instead of == 2) is because we're # going back a month, so we need to know if the previous # month is February, so we test if this month is March. leap = minfield == 0 and date[1] == 3 and \ date[0] % 4 == 0 and \ (date[0] % 100 != 0 or date[0] % 400 == 0) if 0 < date[2] <= months[date[1]] + leap: break date[2] += months[date[1] - 1] + leap date[1] -= 1 if date[1] > 0: break date[1] = 12 if minfield > 0: break date[0] -= 1 return date try: exp = getattr(self.DATETIMECONSTS, kind) except AttributeError: return None if type(exp) == StringType: exp = re.compile(exp) setattr (self.DATETIMECONSTS, kind, exp) m = exp.search(value) try: if m == None: raise Exception d = m.groupdict() f = ('century', 'year', 'month', 'day', 'hour', 'minute', 'second') fn = len(f) # Index of first non-None value r = [] if kind in ('duration', 'timeDuration'): if d['sep'] != None and d['hour'] == None and \ d['minute'] == None and d['second'] == None: raise Exception f = f[1:] for i in range(len(f)): s = d[f[i]] if s != None: if f[i] == 'second': s = float(s) else: try: s = int(s) except ValueError: s = long(s) if i < fn: fn = i r.append(s) if fn > len(r): # Any non-Nones? raise Exception if d['sign'] == '-': r[fn] = -r[fn] return tuple(r) if kind == 'recurringInstant': for i in range(len(f)): s = d[f[i]] if s == None or s == '-': if i > fn: raise Exception s = None else: if i < fn: fn = i if f[i] == 'second': s = float(s) else: try: s = int(s) except ValueError: s = long(s) r.append(s) s = r.pop(0) if fn == 0: r[0] += s * 100 else: fn -= 1 if fn < len(r) and d['sign'] == '-': r[fn] = -r[fn] cleanDate(r, fn) return tuple(applyZoneOffset(self.DATETIMECONSTS.months, getZoneOffset(d), r, fn, 0)) r = [0, 0, 1, 1, 0, 0, 0] for i in range(len(f)): field = f[i] s = d.get(field) if s != None: if field == 'second': s = float(s) else: try: s = int(s) except ValueError: s = long(s) if i < fn: fn = i r[i] = s if fn > len(r): # Any non-Nones? raise Exception s = r.pop(0) if fn == 0: r[0] += s * 100 else: fn -= 1 if d.get('sign') == '-': r[fn] = -r[fn] cleanDate(r, fn) zoffs = getZoneOffset(d) if zoffs: r = applyZoneOffset(self.DATETIMECONSTS.months, zoffs, r, fn) if kind == 'century': return r[0] / 100 s = [] for i in range(1, len(f)): if d.has_key(f[i]): s.append(r[i - 1]) if len(s) == 1: return s[0] return tuple(s) except Exception, e: raise Error, "invalid %s value `%s' - %s" % (kind, value, e) intlimits = \ { 'nonPositiveInteger': (0, None, 0), 'non-positive-integer': (0, None, 0), 'negativeInteger': (0, None, -1), 'negative-integer': (0, None, -1), 'long': (1, -9223372036854775808L, 9223372036854775807L), 'int': (0, -2147483648L, 2147483647L), 'short': (0, -32768, 32767), 'byte': (0, -128, 127), 'nonNegativeInteger': (0, 0, None), 'non-negative-integer': (0, 0, None), 'positiveInteger': (0, 1, None), 'positive-integer': (0, 1, None), 'unsignedLong': (1, 0, 18446744073709551615L), 'unsignedInt': (0, 0, 4294967295L), 'unsignedShort': (0, 0, 65535), 'unsignedByte': (0, 0, 255), } floatlimits = \ { 'float': (7.0064923216240861E-46, -3.4028234663852886E+38, 3.4028234663852886E+38), 'double': (2.4703282292062327E-324, -1.7976931348623158E+308, 1.7976931348623157E+308), } zerofloatre = '[1-9]' def convertType(self, d, t, attrs, config=Config): if t[0] is None and t[1] is not None: type = t[1].strip() if type[:9] == 'arrayType': index_eq = type.find('=') index_obr = type.find('[') index_cbr = type.find(']') elemtype = type[index_eq+1:index_obr] elemnum = type[index_obr+1:index_cbr] if elemtype=="ur-type": return(d) else: newarr = map( lambda(di): self.convertToBasicTypes(d=di, t = ( NS.XSD, elemtype), attrs=attrs, config=config), d) return newarr else: t = (NS.XSD, t[1]) return self.convertToBasicTypes(d, t, attrs, config) def convertToSOAPpyTypes(self, d, t, attrs, config=Config): pass def convertToBasicTypes(self, d, t, attrs, config=Config): dnn = d or '' #if Config.debug: #print "convertToBasicTypes:" #print " requested_type=", t #print " data=", d # print "convertToBasicTypes:" # print " requested_type=", t # print " data=", d # print " attrs=", attrs # print " t[0]=", t[0] # print " t[1]=", t[1] # print " in?", t[0] in NS.EXSD_L if t[0] in NS.EXSD_L: if t[1]=="integer": # unbounded integer type try: d = int(d) if len(attrs): d = long(d) except: d = long(d) return d if self.intlimits.has_key (t[1]): # range-bounded integer types l = self.intlimits[t[1]] try: d = int(d) except: d = long(d) if l[1] != None and d < l[1]: raise UnderflowError, "%s too small" % d if l[2] != None and d > l[2]: raise OverflowError, "%s too large" % d if l[0] or len(attrs): return long(d) return d if t[1] == "string": if len(attrs): return unicode(dnn) try: return str(dnn) except: return dnn if t[1] in ("bool", "boolean"): d = d.strip().lower() if d in ('0', 'false'): return False if d in ('1', 'true'): return True raise AttributeError, "invalid boolean value" if t[1] in ('double','float'): l = self.floatlimits[t[1]] s = d.strip().lower() # Explicitly check for NaN and Infinities if s == "nan": d = NaN elif s[0:2]=="inf" or s[0:3]=="+inf": d = PosInf elif s[0:3] == "-inf": d = NegInf else : d = float(s) if config.strict_range: if NaN == d: if s[0:2] != 'nan': raise ValueError, "invalid %s: %s" % (t[1], s) elif NegInf == d: if s[0:3] != '-inf': raise UnderflowError, "%s too small: %s" % (t[1], s) elif PosInf == d: if s[0:2] != 'inf' and s[0:3] != '+inf': raise OverflowError, "%s too large: %s" % (t[1], s) elif d < 0 and d < l[1]: raise UnderflowError, "%s too small: %s" % (t[1], s) elif d > 0 and ( d < l[0] or d > l[2] ): raise OverflowError, "%s too large: %s" % (t[1], s) elif d == 0: if type(self.zerofloatre) == StringType: self.zerofloatre = re.compile(self.zerofloatre) if self.zerofloatre.search(s): raise UnderflowError, "invalid %s: %s" % (t[1], s) return d if t[1] in ("dateTime", "date", "timeInstant", "time"): return self.convertDateTime(d, t[1]) if t[1] == "decimal": return float(d) if t[1] in ("language", "QName", "NOTATION", "NMTOKEN", "Name", "NCName", "ID", "IDREF", "ENTITY"): return collapseWhiteSpace(d) if t[1] in ("IDREFS", "ENTITIES", "NMTOKENS"): d = collapseWhiteSpace(d) return d.split() if t[0] in NS.XSD_L: if t[1] in ("base64", "base64Binary"): if d: return base64.decodestring(d) else: return '' if t[1] == "hexBinary": if d: return decodeHexString(d) else: return if t[1] == "anyURI": return urllib.unquote(collapseWhiteSpace(d)) if t[1] in ("normalizedString", "token"): return collapseWhiteSpace(d) if t[0] == NS.ENC: if t[1] == "base64": if d: return base64.decodestring(d) else: return '' if t[0] == NS.XSD: if t[1] == "binary": try: e = attrs[(None, 'encoding')] if d: if e == 'hex': return decodeHexString(d) elif e == 'base64': return base64.decodestring(d) else: return '' except: pass raise Error, "unknown or missing binary encoding" if t[1] == "uri": return urllib.unquote(collapseWhiteSpace(d)) if t[1] == "recurringInstant": return self.convertDateTime(d, t[1]) if t[0] in (NS.XSD2, NS.ENC): if t[1] == "uriReference": return urllib.unquote(collapseWhiteSpace(d)) if t[1] == "timePeriod": return self.convertDateTime(d, t[1]) if t[1] in ("century", "year"): return self.convertDateTime(d, t[1]) if t[0] in (NS.XSD, NS.XSD2, NS.ENC): if t[1] == "timeDuration": return self.convertDateTime(d, t[1]) if t[0] == NS.XSD3: if t[1] == "anyURI": return urllib.unquote(collapseWhiteSpace(d)) if t[1] in ("gYearMonth", "gMonthDay"): return self.convertDateTime(d, t[1]) if t[1] == "gYear": return self.convertDateTime(d, t[1]) if t[1] == "gMonth": return self.convertDateTime(d, t[1]) if t[1] == "gDay": return self.convertDateTime(d, t[1]) if t[1] == "duration": return self.convertDateTime(d, t[1]) if t[0] in (NS.XSD2, NS.XSD3): if t[1] == "token": return collapseWhiteSpace(d) if t[1] == "recurringDate": return self.convertDateTime(d, t[1]) if t[1] == "month": return self.convertDateTime(d, t[1]) if t[1] == "recurringDay": return self.convertDateTime(d, t[1]) if t[0] == NS.XSD2: if t[1] == "CDATA": return collapseWhiteSpace(d) raise UnknownTypeError, "unknown type `%s'" % (str(t[0]) + ':' + t[1]) ################################################################################ # call to SOAPParser that keeps all of the info ################################################################################ class EmptyEntityResolver(xml.sax.handler.EntityResolver): def resolveEntity(self, publicId, systemId): return StringIO("") def _parseSOAP(xml_str, rules = None, ignore_ext=None, forbid_entities=False, forbid_external=True, forbid_dtd=False): inpsrc = xml.sax.xmlreader.InputSource() inpsrc.setByteStream(StringIO(xml_str)) if ignore_ext is None: ignore_ext = False parser = make_parser() t = SOAPParser(rules=rules) parser.setContentHandler(t) errorHandler = xml.sax.handler.ErrorHandler() parser.setErrorHandler(errorHandler) if ignore_ext: # disable by default entity loading on posted content forbid_dtd = True forbid_entities = True forbid_external = True parser.forbid_dtd = forbid_dtd parser.forbid_entities = forbid_entities parser.forbid_external = forbid_external parser.setEntityResolver(EmptyEntityResolver()) # turn on namespace mangeling parser.setFeature(xml.sax.handler.feature_namespaces, 1) try: parser.parse(inpsrc) except DefusedXmlException, e: parser._parser = None print traceback.format_exc() raise e except xml.sax.SAXParseException, e: parser._parser = None print traceback.format_exc() raise e return t ################################################################################ # SOAPParser's more public interface ################################################################################ def parseSOAP(xml_str, attrs = 0): t = _parseSOAP(xml_str) if attrs: return t.body, t.attrs return t.body def parseSOAPRPC(xml_str, header = 0, body = 0, attrs = 0, rules = None, ignore_ext=None): t = _parseSOAP(xml_str, rules = rules, ignore_ext=ignore_ext) p = t.body[0] # Empty string, for RPC this translates into a void if type(p) in (type(''), type(u'')) and p in ('', u''): name = "Response" for k in t.body.__dict__.keys(): if k[0] != "_": name = k p = structType(name) if header or body or attrs: ret = (p,) if header : ret += (t.header,) if body: ret += (t.body,) if attrs: ret += (t.attrs,) return ret else: return p SOAPpy-0.12.22/src/SOAPpy/SOAP.py000066400000000000000000000015051235077700100160120ustar00rootroot00000000000000"""This file is here for backward compatibility with versions <= 0.9.9 Delete when 1.0.0 is released! """ ident = '$Id: SOAP.py 541 2004-01-31 04:20:06Z warnes $' from version import __version__ from Client import * from Config import * from Errors import * from NS import * from Parser import * from SOAPBuilder import * from Server import * from Types import * from Utilities import * import wstools import WSDL from warnings import warn warn(""" The sub-module SOAPpy.SOAP is deprecated and is only provided for short-term backward compatibility. Objects are now available directly within the SOAPpy module. Thus, instead of from SOAPpy import SOAP ... SOAP.SOAPProxy(...) use from SOAPpy import SOAPProxy ... SOAPProxy(...) instead. """, DeprecationWarning) SOAPpy-0.12.22/src/SOAPpy/SOAPBuilder.py000066400000000000000000000605321235077700100173260ustar00rootroot00000000000000""" ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ ident = '$Id: SOAPBuilder.py 1498 2010-03-12 02:13:19Z pooryorick $' from version import __version__ import cgi from wstools.XMLname import toXMLname, fromXMLname # SOAPpy modules from Config import Config from NS import NS from Types import * # Test whether this Python version has Types.BooleanType # If it doesn't have it, then False and True are serialized as integers try: BooleanType pythonHasBooleanType = 1 except NameError: pythonHasBooleanType = 0 ################################################################################ # SOAP Builder ################################################################################ class SOAPBuilder: _xml_top = '\n' _xml_enc_top = '\n' _env_top = ( '%(ENV_T)s:Envelope\n' + \ ' %(ENV_T)s:encodingStyle="%(ENC)s"\n' ) % \ NS.__dict__ _env_bot = '\n' % NS.__dict__ # Namespaces potentially defined in the Envelope tag. _env_ns = {NS.ENC: NS.ENC_T, NS.ENV: NS.ENV_T, NS.XSD: NS.XSD_T, NS.XSD2: NS.XSD2_T, NS.XSD3: NS.XSD3_T, NS.XSI: NS.XSI_T, NS.XSI2: NS.XSI2_T, NS.XSI3: NS.XSI3_T} def __init__(self, args = (), kw = {}, method = None, namespace = None, header = None, methodattrs = None, envelope = 1, encoding = 'UTF-8', use_refs = 0, config = Config, noroot = 0): # Test the encoding, raising an exception if it's not known if encoding != None: ''.encode(encoding) self.args = args self.kw = kw self.envelope = envelope self.encoding = encoding self.method = method self.namespace = namespace self.header = header self.methodattrs= methodattrs self.use_refs = use_refs self.config = config self.out = [] self.tcounter = 0 self.ncounter = 1 self.icounter = 1 self.envns = {} self.ids = {} self.depth = 0 self.multirefs = [] self.multis = 0 self.body = not isinstance(args, bodyType) self.noroot = noroot def build(self): if self.config.debug: print "In build." ns_map = {} # Cache whether typing is on or not typed = self.config.typed if self.header: # Create a header. self.dump(self.header, "Header", typed = typed) #self.header = None # Wipe it out so no one is using it. if self.body: # Call genns to record that we've used SOAP-ENV. self.depth += 1 body_ns = self.genns(ns_map, NS.ENV)[0] self.out.append("<%sBody>\n" % body_ns) if self.method: # Save the NS map so that it can be restored when we # fall out of the scope of the method definition save_ns_map = ns_map.copy() self.depth += 1 a = '' if self.methodattrs: for (k, v) in self.methodattrs.items(): a += ' %s="%s"' % (k, v) if self.namespace: # Use the namespace info handed to us methodns, n = self.genns(ns_map, self.namespace) else: methodns, n = '', '' self.out.append('<%s%s%s%s%s>\n' % ( methodns, self.method, n, a, self.genroot(ns_map))) try: if type(self.args) != TupleType: args = (self.args,) else: args = self.args for i in args: self.dump(i, typed = typed, ns_map = ns_map) if hasattr(self.config, "argsOrdering") and self.config.argsOrdering.has_key(self.method): for k in self.config.argsOrdering.get(self.method): self.dump(self.kw.get(k), k, typed = typed, ns_map = ns_map) else: for (k, v) in self.kw.items(): self.dump(v, k, typed = typed, ns_map = ns_map) except RecursionError: if self.use_refs == 0: # restart b = SOAPBuilder(args = self.args, kw = self.kw, method = self.method, namespace = self.namespace, header = self.header, methodattrs = self.methodattrs, envelope = self.envelope, encoding = self.encoding, use_refs = 1, config = self.config) return b.build() raise if self.method: self.out.append("\n" % (methodns, self.method)) # End of the method definition; drop any local namespaces ns_map = save_ns_map self.depth -= 1 if self.body: # dump may add to self.multirefs, but the for loop will keep # going until it has used all of self.multirefs, even those # entries added while in the loop. self.multis = 1 for obj, tag in self.multirefs: self.dump(obj, tag, typed = typed, ns_map = ns_map) self.out.append("\n" % body_ns) self.depth -= 1 if self.envelope: e = map (lambda ns: ' xmlns:%s="%s"\n' % (ns[1], ns[0]), self.envns.items()) self.out = ['<', self._env_top] + e + ['>\n'] + \ self.out + \ [self._env_bot] if self.encoding != None: self.out.insert(0, self._xml_enc_top % self.encoding) return ''.join(self.out).encode(self.encoding) self.out.insert(0, self._xml_top) return ''.join(self.out) def gentag(self): if self.config.debug: print "In gentag." self.tcounter += 1 return "v%d" % self.tcounter def genns(self, ns_map, nsURI): if nsURI == None: return ('', '') if type(nsURI) == TupleType: # already a tuple if len(nsURI) == 2: ns, nsURI = nsURI else: ns, nsURI = None, nsURI[0] else: ns = None if ns_map.has_key(nsURI): return (ns_map[nsURI] + ':', '') if self._env_ns.has_key(nsURI): ns = self.envns[nsURI] = ns_map[nsURI] = self._env_ns[nsURI] return (ns + ':', '') if not ns: ns = "ns%d" % self.ncounter self.ncounter += 1 ns_map[nsURI] = ns if self.config.buildWithNamespacePrefix: return (ns + ':', ' xmlns:%s="%s"' % (ns, nsURI)) elif self.config.buildWithGlobalNamespacePrefix: self.envns[nsURI] = ns return (ns + ':', '') else: return ('', ' xmlns="%s"' % (nsURI)) def genroot(self, ns_map): if self.noroot: return '' if self.depth != 2: return '' ns, n = self.genns(ns_map, NS.ENC) return ' %sroot="%d"%s' % (ns, not self.multis, n) # checkref checks an element to see if it needs to be encoded as a # multi-reference element or not. If it returns None, the element has # been handled and the caller can continue with subsequent elements. # If it returns a string, the string should be included in the opening # tag of the marshaled element. def checkref(self, obj, tag, ns_map): if self.depth < 2: return '' if not self.ids.has_key(id(obj)): n = self.ids[id(obj)] = self.icounter self.icounter = n + 1 if self.use_refs == 0: return '' if self.depth == 2: return ' id="i%d"' % n self.multirefs.append((obj, tag)) else: if self.use_refs == 0: raise RecursionError, "Cannot serialize recursive object" n = self.ids[id(obj)] if self.multis and self.depth == 2: return ' id="i%d"' % n self.out.append('<%s href="#i%d"%s/>\n' % (tag, n, self.genroot(ns_map))) return None # dumpers def dump(self, obj, tag = None, typed = 1, ns_map = {}): if self.config.debug: print "In dump.", "obj=", obj ns_map = ns_map.copy() self.depth += 1 if type(tag) not in (NoneType, StringType, UnicodeType): raise KeyError, "tag must be a string or None" self.dump_dispatch(obj, tag, typed, ns_map) self.depth -= 1 # generic dumper def dumper(self, nsURI, obj_type, obj, tag, typed = 1, ns_map = {}, rootattr = '', id = '', xml = '<%(tag)s%(type)s%(id)s%(attrs)s%(root)s>%(data)s\n'): if self.config.debug: print "In dumper." if nsURI == None: nsURI = self.config.typesNamespaceURI tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding a = n = t = '' if typed and obj_type: ns, n = self.genns(ns_map, nsURI) ins = self.genns(ns_map, self.config.schemaNamespaceURI)[0] t = ' %stype="%s%s"%s' % (ins, ns, obj_type, n) try: a = obj._marshalAttrs(ns_map, self) except: pass try: data = obj._marshalData() except: if (obj_type != "string"): # strings are already encoded data = cgi.escape(str(obj)) else: data = obj return xml % {"tag": tag, "type": t, "data": data, "root": rootattr, "id": id, "attrs": a} def dump_float(self, obj, tag, typed = 1, ns_map = {}): if self.config.debug: print "In dump_float." tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding if self.config.strict_range: doubleType(obj) if PosInf == obj: obj = "INF" elif NegInf == obj: obj = "-INF" elif NaN == obj: obj = "NaN" else: obj = repr(obj) # Note: python 'float' is actually a SOAP 'double'. self.out.append(self.dumper( None, "double", obj, tag, typed, ns_map, self.genroot(ns_map))) def dump_int(self, obj, tag, typed = 1, ns_map = {}): if self.config.debug: print "In dump_int." # fix error "Bad types (class java.math.BigInteger -> class java.lang.Integer)" if isinstance(obj, LongType): obj_type = "integer" else: obj_type = "int" self.out.append(self.dumper(None, obj_type, obj, tag, typed, ns_map, self.genroot(ns_map))) def dump_bool(self, obj, tag, typed = 1, ns_map = {}): if self.config.debug: print "In dump_bool." self.out.append(self.dumper(None, 'boolean', obj, tag, typed, ns_map, self.genroot(ns_map))) def dump_string(self, obj, tag, typed = 0, ns_map = {}): if self.config.debug: print "In dump_string." tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding id = self.checkref(obj, tag, ns_map) if id == None: return try: data = obj._marshalData() except: data = obj self.out.append(self.dumper(None, "string", cgi.escape(data), tag, typed, ns_map, self.genroot(ns_map), id)) dump_str = dump_string # For Python 2.2+ dump_unicode = dump_string def dump_None(self, obj, tag, typed = 0, ns_map = {}): if self.config.debug: print "In dump_None." tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding ns = self.genns(ns_map, self.config.schemaNamespaceURI)[0] self.out.append('<%s %snull="1"%s/>\n' % (tag, ns, self.genroot(ns_map))) dump_NoneType = dump_None # For Python 2.2+ def dump_list(self, obj, tag, typed = 1, ns_map = {}): if self.config.debug: print "In dump_list.", "obj=", obj tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding if type(obj) == InstanceType: data = obj.data else: data = obj if typed: id = self.checkref(obj, tag, ns_map) if id == None: return try: sample = data[0] empty = 0 except: # preserve type if present if getattr(obj,"_typed",None) and getattr(obj,"_type",None): if getattr(obj, "_complexType", None): sample = typedArrayType(typed=obj._type, complexType = obj._complexType) sample._typename = obj._type if not getattr(obj,"_ns",None): obj._ns = NS.URN else: sample = typedArrayType(typed=obj._type) else: sample = structType() empty = 1 # First scan list to see if all are the same type same_type = 1 if not empty: for i in data[1:]: if type(sample) != type(i) or \ (type(sample) == InstanceType and \ sample.__class__ != i.__class__): same_type = 0 break ndecl = '' if same_type: if (isinstance(sample, structType)) or \ type(sample) == DictType or \ (isinstance(sample, anyType) and \ (getattr(sample, "_complexType", None) and \ sample._complexType)): # force to urn struct try: tns = obj._ns or NS.URN except: tns = NS.URN ns, ndecl = self.genns(ns_map, tns) try: typename = sample._typename except: typename = "SOAPStruct" t = ns + typename elif isinstance(sample, anyType): ns = sample._validNamespaceURI(self.config.typesNamespaceURI, self.config.strictNamespaces) if ns: ns, ndecl = self.genns(ns_map, ns) t = ns + str(sample._type) else: t = 'ur-type' else: typename = type(sample).__name__ # For Python 2.2+ if type(sample) == StringType: typename = 'string' # HACK: unicode is a SOAP string if type(sample) == UnicodeType: typename = 'string' # HACK: python 'float' is actually a SOAP 'double'. if typename=="float": typename="double" t = self.genns( ns_map, self.config.typesNamespaceURI)[0] + typename else: t = self.genns(ns_map, self.config.typesNamespaceURI)[0] + \ "ur-type" try: a = obj._marshalAttrs(ns_map, self) except: a = '' ens, edecl = self.genns(ns_map, NS.ENC) ins, idecl = self.genns(ns_map, self.config.schemaNamespaceURI) if typed: self.out.append( '<%s %sarrayType="%s[%d]" %stype="%sArray"%s%s%s%s%s%s>\n' % (tag, ens, t, len(data), ins, ens, ndecl, edecl, idecl, self.genroot(ns_map), id, a)) if typed: try: elemsname = obj._elemsname except: elemsname = "item" else: elemsname = tag if isinstance(data, (list, tuple, arrayType)): should_drill = True else: should_drill = not same_type for i in data: self.dump(i, elemsname, should_drill, ns_map) if typed: self.out.append('\n' % tag) dump_tuple = dump_list def dump_map(self, obj, tag, typed = 1, ns_map = {}): if self.config.debug: print "In dump_map.", "obj=", obj tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding if type(obj) == InstanceType: data = obj.data else: data = obj if typed: id = self.checkref(obj, tag, ns_map) if id == None: return try: a = obj._marshalAttrs(ns_map, self) except: a = '' ndecl = '' ens, edecl = self.genns(ns_map, 'http://xml.apache.org/xml-soap') ins, idecl = self.genns(ns_map, self.config.schemaNamespaceURI) if typed: self.out.append( '<%s %stype="%sMap"%s%s%s%s%s%s>\n' % (tag, ins, ens, ndecl, edecl, idecl, self.genroot(ns_map), id, a)) try: elemsname = obj._elemsname except: elemsname = "item" else: elemsname = tag if isinstance(data, (list, tuple, arrayType)): should_drill = True else: should_drill = not same_type for i in data: self.dump(i, elemsname, should_drill, ns_map) if typed: self.out.append('\n' % tag) def dump_exception(self, obj, tag, typed = 0, ns_map = {}): if isinstance(obj, faultType): # Fault cns, cdecl = self.genns(ns_map, NS.ENC) vns, vdecl = self.genns(ns_map, NS.ENV) self.out.append('<%sFault %sroot="1"%s%s>' % (vns, cns, vdecl, cdecl)) self.dump(obj.faultcode, "faultcode", typed, ns_map) self.dump(obj.faultstring, "faultstring", typed, ns_map) if hasattr(obj, "detail"): self.dump(obj.detail, "detail", typed, ns_map) self.out.append("\n" % vns) def dump_dictionary(self, obj, tag, typed = 1, ns_map = {}): if self.config.debug: print "In dump_dictionary." tag = tag or self.gentag() tag = toXMLname(tag) # convert from SOAP 1.2 XML name encoding id = self.checkref(obj, tag, ns_map) if id == None: return try: a = obj._marshalAttrs(ns_map, self) except: a = '' self.out.append('<%s%s%s%s>\n' % (tag, id, a, self.genroot(ns_map))) for (k, v) in obj.items(): if k[0] != "_": self.dump(v, k, 1, ns_map) self.out.append('\n' % tag) dump_dict = dump_dictionary # For Python 2.2+ def dump_dispatch(self, obj, tag, typed = 1, ns_map = {}): if not tag: # If it has a name use it. if isinstance(obj, anyType) and obj._name: tag = obj._name else: tag = self.gentag() # Apply additional types, override built-in types for dtype, func in self.config.dumpmap: if isinstance(obj, dtype): func(self, obj, tag, typed, ns_map) return # watch out for order! dumpmap = ( (Exception, self.dump_exception), (mapType, self.dump_map), (arrayType, self.dump_list), (basestring, self.dump_string), (NoneType, self.dump_None), (bool, self.dump_bool), (int, self.dump_int), (long, self.dump_int), (list, self.dump_list), (tuple, self.dump_list), (dict, self.dump_dictionary), (float, self.dump_float), ) for dtype, func in dumpmap: if isinstance(obj, dtype): func(obj, tag, typed, ns_map) return r = self.genroot(ns_map) try: a = obj._marshalAttrs(ns_map, self) except: a = '' if isinstance(obj, voidType): # void self.out.append("<%s%s%s>\n" % (tag, a, r, tag)) else: id = self.checkref(obj, tag, ns_map) if id == None: return if isinstance(obj, structType): # Check for namespace ndecl = '' ns = obj._validNamespaceURI(self.config.typesNamespaceURI, self.config.strictNamespaces) if ns: ns, ndecl = self.genns(ns_map, ns) tag = ns + tag self.out.append("<%s%s%s%s%s>\n" % (tag, ndecl, id, a, r)) keylist = obj.__dict__.keys() # first write out items with order information if hasattr(obj, '_keyord'): for i in range(len(obj._keyord)): self.dump(obj._aslist(i), obj._keyord[i], 1, ns_map) keylist.remove(obj._keyord[i]) # now write out the rest for k in keylist: if (k[0] != "_"): self.dump(getattr(obj,k), k, 1, ns_map) if isinstance(obj, bodyType): self.multis = 1 for v, k in self.multirefs: self.dump(v, k, typed = typed, ns_map = ns_map) self.out.append('\n' % tag) elif isinstance(obj, anyType): t = '' if typed: ns = obj._validNamespaceURI(self.config.typesNamespaceURI, self.config.strictNamespaces) if ns: ons, ondecl = self.genns(ns_map, ns) ins, indecl = self.genns(ns_map, self.config.schemaNamespaceURI) t = ' %stype="%s%s"%s%s' % \ (ins, ons, obj._type, ondecl, indecl) self.out.append('<%s%s%s%s%s>%s\n' % (tag, t, id, a, r, obj._marshalData(), tag)) else: # Some Class self.out.append('<%s%s%s>\n' % (tag, id, r)) d1 = getattr(obj, '__dict__', None) if d1 is None and hasattr(obj, "__slots__"): d1 = dict(((k, getattr(obj, k)) for k in obj.__slots__)) if d1 is not None: for (k, v) in d1.items(): if k[0] != "_": self.dump(v, k, 1, ns_map) self.out.append('\n' % tag) ################################################################################ # SOAPBuilder's more public interface ################################################################################ def buildSOAP(args=(), kw={}, method=None, namespace=None, header=None, methodattrs=None, envelope=1, encoding='UTF-8', config=Config, noroot = 0): t = SOAPBuilder(args=args, kw=kw, method=method, namespace=namespace, header=header, methodattrs=methodattrs,envelope=envelope, encoding=encoding, config=config,noroot=noroot) return t.build() SOAPpy-0.12.22/src/SOAPpy/Server.py000066400000000000000000000646441235077700100165330ustar00rootroot00000000000000""" ################################################################################ # # SOAPpy - Cayce Ullman (cayce@actzero.com) # Brian Matthews (blm@actzero.com) # Gregory Warnes (Gregory.R.Warnes@Pfizer.com) # Christopher Blunck (blunck@gst.com) # ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ from __future__ import nested_scopes ident = '$Id: Server.py 1468 2008-05-24 01:55:33Z warnes $' from version import __version__ #import xml.sax import socket import sys import SocketServer from types import * import BaseHTTPServer import thread # SOAPpy modules from Parser import parseSOAPRPC from Config import Config from Types import faultType, voidType, simplify from NS import NS from SOAPBuilder import buildSOAP from Utilities import debugHeader, debugFooter try: from M2Crypto import SSL except: pass ident = '$Id: Server.py 1468 2008-05-24 01:55:33Z warnes $' from version import __version__ ################################################################################ # Call context dictionary ################################################################################ _contexts = dict() def GetSOAPContext(): global _contexts return _contexts[thread.get_ident()] ################################################################################ # Server ################################################################################ # Method Signature class for adding extra info to registered funcs, right now # used just to indicate it should be called with keywords, instead of ordered # params. class MethodSig: def __init__(self, func, keywords=0, context=0): self.func = func self.keywords = keywords self.context = context self.__name__ = func.__name__ def __call__(self, *args, **kw): return apply(self.func,args,kw) class SOAPContext: def __init__(self, header, body, attrs, xmldata, connection, httpheaders, soapaction): self.header = header self.body = body self.attrs = attrs self.xmldata = xmldata self.connection = connection self.httpheaders= httpheaders self.soapaction = soapaction # A class to describe how header messages are handled class HeaderHandler: # Initially fail out if there are any problems. def __init__(self, header, attrs): for i in header.__dict__.keys(): if i[0] == "_": continue d = getattr(header, i) try: fault = int(attrs[id(d)][(NS.ENV, 'mustUnderstand')]) except: fault = 0 if fault: raise faultType, ("%s:MustUnderstand" % NS.ENV_T, "Required Header Misunderstood", "%s" % i) ################################################################################ # SOAP Server ################################################################################ class SOAPServerBase: def get_request(self): sock, addr = SocketServer.TCPServer.get_request(self) if self.ssl_context: sock = SSL.Connection(self.ssl_context, sock) sock._setup_ssl(addr) if sock.accept_ssl() != 1: raise socket.error, "Couldn't accept SSL connection" return sock, addr def registerObject(self, object, namespace = '', path = ''): if namespace == '' and path == '': namespace = self.namespace if namespace == '' and path != '': namespace = path.replace("/", ":") if namespace[0] == ":": namespace = namespace[1:] self.objmap[namespace] = object def registerFunction(self, function, namespace = '', funcName = None, path = ''): if not funcName : funcName = function.__name__ if namespace == '' and path == '': namespace = self.namespace if namespace == '' and path != '': namespace = path.replace("/", ":") if namespace[0] == ":": namespace = namespace[1:] if self.funcmap.has_key(namespace): self.funcmap[namespace][funcName] = function else: self.funcmap[namespace] = {funcName : function} def registerKWObject(self, object, namespace = '', path = ''): if namespace == '' and path == '': namespace = self.namespace if namespace == '' and path != '': namespace = path.replace("/", ":") if namespace[0] == ":": namespace = namespace[1:] for i in dir(object.__class__): if i[0] != "_" and callable(getattr(object, i)): self.registerKWFunction(getattr(object,i), namespace) # convenience - wraps your func for you. def registerKWFunction(self, function, namespace = '', funcName = None, path = ''): if namespace == '' and path == '': namespace = self.namespace if namespace == '' and path != '': namespace = path.replace("/", ":") if namespace[0] == ":": namespace = namespace[1:] self.registerFunction(MethodSig(function,keywords=1), namespace, funcName) def unregisterObject(self, object, namespace = '', path = ''): if namespace == '' and path == '': namespace = self.namespace if namespace == '' and path != '': namespace = path.replace("/", ":") if namespace[0] == ":": namespace = namespace[1:] del self.objmap[namespace] class SOAPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): ignore_ext = True def version_string(self): return '' + \ 'SOAPpy ' + __version__ + ' (Python ' + \ sys.version.split()[0] + ')' def date_time_string(self): self.__last_date_time_string = \ BaseHTTPServer.BaseHTTPRequestHandler.\ date_time_string(self) return self.__last_date_time_string def do_POST(self): global _contexts status = 500 try: if self.server.config.dumpHeadersIn: s = 'Incoming HTTP headers' debugHeader(s) print self.raw_requestline.strip() print "\n".join(map (lambda x: x.strip(), self.headers.headers)) debugFooter(s) data = self.rfile.read(int(self.headers["Content-length"])) if self.server.config.dumpSOAPIn: s = 'Incoming SOAP' debugHeader(s) print data, if data[-1] != '\n': print debugFooter(s) (r, header, body, attrs) = \ parseSOAPRPC(data, header = 1, body = 1, attrs = 1, ignore_ext=self.ignore_ext) method = r._name args = r._aslist() kw = r._asdict() if self.server.config.simplify_objects: args = simplify(args) kw = simplify(kw) # Handle mixed named and unnamed arguments by assuming # that all arguments with names of the form "v[0-9]+" # are unnamed and should be passed in numeric order, # other arguments are named and should be passed using # this name. # This is a non-standard exension to the SOAP protocol, # but is supported by Apache AXIS. # It is enabled by default. To disable, set # Config.specialArgs to False. ordered_args = {} named_args = {} if self.server.config.specialArgs: for (k,v) in kw.items(): if k[0]=="v": try: i = int(k[1:]) ordered_args[i] = v except ValueError: named_args[str(k)] = v else: named_args[str(k)] = v # We have to decide namespace precedence # I'm happy with the following scenario # if r._ns is specified use it, if not check for # a path, if it's specified convert it and use it as the # namespace. If both are specified, use r._ns. ns = r._ns if len(self.path) > 1 and not ns: ns = self.path.replace("/", ":") if ns[0] == ":": ns = ns[1:] # authorization method a = None keylist = ordered_args.keys() keylist.sort() # create list in proper order w/o names tmp = map( lambda x: ordered_args[x], keylist) ordered_args = tmp #print '<-> Argument Matching Yielded:' #print '<-> Ordered Arguments:' + str(ordered_args) #print '<-> Named Arguments :' + str(named_args) resp = "" # For fault messages if ns: nsmethod = "%s:%s" % (ns, method) else: nsmethod = method try: # First look for registered functions if self.server.funcmap.has_key(ns) and \ self.server.funcmap[ns].has_key(method): f = self.server.funcmap[ns][method] # look for the authorization method if self.server.config.authMethod != None: authmethod = self.server.config.authMethod if self.server.funcmap.has_key(ns) and \ self.server.funcmap[ns].has_key(authmethod): a = self.server.funcmap[ns][authmethod] else: # Now look at registered objects # Check for nested attributes. This works even if # there are none, because the split will return # [method] f = self.server.objmap[ns] # Look for the authorization method if self.server.config.authMethod != None: authmethod = self.server.config.authMethod if hasattr(f, authmethod): a = getattr(f, authmethod) # then continue looking for the method l = method.split(".") for i in l: f = getattr(f, i) except: info = sys.exc_info() try: resp = buildSOAP(faultType("%s:Client" % NS.ENV_T, "Method Not Found", "%s : %s %s %s" % (nsmethod, info[0], info[1], info[2])), encoding = self.server.encoding, config = self.server.config) finally: del info status = 500 else: try: if header: x = HeaderHandler(header, attrs) fr = 1 # call context book keeping # We're stuffing the method into the soapaction if there # isn't one, someday, we'll set that on the client # and it won't be necessary here # for now we're doing both if "SOAPAction".lower() not in self.headers.keys() or \ self.headers["SOAPAction"] == "\"\"": self.headers["SOAPAction"] = method thread_id = thread.get_ident() _contexts[thread_id] = SOAPContext(header, body, attrs, data, self.connection, self.headers, self.headers["SOAPAction"]) # Do an authorization check if a != None: if not apply(a, (), {"_SOAPContext" : _contexts[thread_id] }): raise faultType("%s:Server" % NS.ENV_T, "Authorization failed.", "%s" % nsmethod) # If it's wrapped, some special action may be needed if isinstance(f, MethodSig): c = None if f.context: # retrieve context object c = _contexts[thread_id] if self.server.config.specialArgs: if c: named_args["_SOAPContext"] = c fr = apply(f, ordered_args, named_args) elif f.keywords: # This is lame, but have to de-unicode # keywords strkw = {} for (k, v) in kw.items(): strkw[str(k)] = v if c: strkw["_SOAPContext"] = c fr = apply(f, (), strkw) elif c: fr = apply(f, args, {'_SOAPContext':c}) else: fr = apply(f, args, {}) else: if self.server.config.specialArgs: fr = apply(f, ordered_args, named_args) else: fr = apply(f, args, {}) if type(fr) == type(self) and \ isinstance(fr, voidType): resp = buildSOAP(kw = {'%sResponse' % method: fr}, encoding = self.server.encoding, config = self.server.config) else: resp = buildSOAP(kw = {'%sResponse' % method: {'Result': fr}}, encoding = self.server.encoding, config = self.server.config) # Clean up _contexts if _contexts.has_key(thread_id): del _contexts[thread_id] except Exception, e: import traceback info = sys.exc_info() try: if self.server.config.dumpFaultInfo: s = 'Method %s exception' % nsmethod debugHeader(s) traceback.print_exception(info[0], info[1], info[2]) debugFooter(s) if isinstance(e, faultType): f = e else: f = faultType("%s:Server" % NS.ENV_T, "Method Failed", "%s" % nsmethod) if self.server.config.returnFaultInfo: f._setDetail("".join(traceback.format_exception( info[0], info[1], info[2]))) elif not hasattr(f, 'detail'): f._setDetail("%s %s" % (info[0], info[1])) finally: del info resp = buildSOAP(f, encoding = self.server.encoding, config = self.server.config) status = 500 else: status = 200 except faultType, e: import traceback info = sys.exc_info() try: if self.server.config.dumpFaultInfo: s = 'Received fault exception' debugHeader(s) traceback.print_exception(info[0], info[1], info[2]) debugFooter(s) if self.server.config.returnFaultInfo: e._setDetail("".join(traceback.format_exception( info[0], info[1], info[2]))) elif not hasattr(e, 'detail'): e._setDetail("%s %s" % (info[0], info[1])) finally: del info resp = buildSOAP(e, encoding = self.server.encoding, config = self.server.config) status = 500 except Exception, e: # internal error, report as HTTP server error if self.server.config.dumpFaultInfo: s = 'Internal exception %s' % e import traceback debugHeader(s) info = sys.exc_info() try: traceback.print_exception(info[0], info[1], info[2]) finally: del info debugFooter(s) self.send_response(500) self.end_headers() if self.server.config.dumpHeadersOut and \ self.request_version != 'HTTP/0.9': s = 'Outgoing HTTP headers' debugHeader(s) if self.responses.has_key(status): s = ' ' + self.responses[status][0] else: s = '' print "%s %d%s" % (self.protocol_version, 500, s) print "Server:", self.version_string() print "Date:", self.__last_date_time_string debugFooter(s) else: # got a valid SOAP response self.send_response(status) t = 'text/xml'; if self.server.encoding != None: t += '; charset=%s' % self.server.encoding self.send_header("Content-type", t) self.send_header("Content-length", str(len(resp))) self.end_headers() if self.server.config.dumpHeadersOut and \ self.request_version != 'HTTP/0.9': s = 'Outgoing HTTP headers' debugHeader(s) if self.responses.has_key(status): s = ' ' + self.responses[status][0] else: s = '' print "%s %d%s" % (self.protocol_version, status, s) print "Server:", self.version_string() print "Date:", self.__last_date_time_string print "Content-type:", t print "Content-length:", len(resp) debugFooter(s) if self.server.config.dumpSOAPOut: s = 'Outgoing SOAP' debugHeader(s) print resp, if resp[-1] != '\n': print debugFooter(s) self.wfile.write(resp) self.wfile.flush() # We should be able to shut down both a regular and an SSL # connection, but under Python 2.1, calling shutdown on an # SSL connections drops the output, so this work-around. # This should be investigated more someday. if self.server.config.SSLserver and \ isinstance(self.connection, SSL.Connection): self.connection.set_shutdown(SSL.SSL_SENT_SHUTDOWN | SSL.SSL_RECEIVED_SHUTDOWN) else: self.connection.shutdown(1) def do_GET(self): #print 'command ', self.command #print 'path ', self.path #print 'request_version', self.request_version #print 'headers' #print ' type ', self.headers.type #print ' maintype', self.headers.maintype #print ' subtype ', self.headers.subtype #print ' params ', self.headers.plist path = self.path.lower() if path.endswith('wsdl'): method = 'wsdl' function = namespace = None if self.server.funcmap.has_key(namespace) \ and self.server.funcmap[namespace].has_key(method): function = self.server.funcmap[namespace][method] else: if namespace in self.server.objmap.keys(): function = self.server.objmap[namespace] l = method.split(".") for i in l: function = getattr(function, i) if function: self.send_response(200) self.send_header("Content-type", 'text/plain') self.end_headers() response = apply(function, ()) self.wfile.write(str(response)) return # return error self.send_response(200) self.send_header("Content-type", 'text/html') self.end_headers() self.wfile.write('''\ <head>Error!</head>

Oops!

This server supports HTTP GET requests only for the the purpose of obtaining Web Services Description Language (WSDL) for a specific service. Either you requested an URL that does not end in "wsdl" or this server does not implement a wsdl method.

''') def log_message(self, format, *args): if self.server.log: BaseHTTPServer.BaseHTTPRequestHandler.\ log_message (self, format, *args) class SOAPInsecureRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): '''Request handler that does load POSTed doctypes''' ignore_ext = False class SOAPServer(SOAPServerBase, SocketServer.TCPServer): def __init__(self, addr = ('localhost', 8000), RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', config = Config, namespace = None, ssl_context = None): # Test the encoding, raising an exception if it's not known if encoding != None: ''.encode(encoding) if ssl_context != None and not config.SSLserver: raise AttributeError, \ "SSL server not supported by this Python installation" self.namespace = namespace self.objmap = {} self.funcmap = {} self.ssl_context = ssl_context self.encoding = encoding self.config = config self.log = log self.allow_reuse_address= 1 SocketServer.TCPServer.__init__(self, addr, RequestHandler) class ThreadingSOAPServer(SOAPServerBase, SocketServer.ThreadingTCPServer): def __init__(self, addr = ('localhost', 8000), RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', config = Config, namespace = None, ssl_context = None): # Test the encoding, raising an exception if it's not known if encoding != None: ''.encode(encoding) if ssl_context != None and not config.SSLserver: raise AttributeError, \ "SSL server not supported by this Python installation" self.namespace = namespace self.objmap = {} self.funcmap = {} self.ssl_context = ssl_context self.encoding = encoding self.config = config self.log = log self.allow_reuse_address= 1 SocketServer.ThreadingTCPServer.__init__(self, addr, RequestHandler) # only define class if Unix domain sockets are available if hasattr(socket, "AF_UNIX"): class SOAPUnixSocketServer(SOAPServerBase, SocketServer.UnixStreamServer): def __init__(self, addr = 8000, RequestHandler = SOAPRequestHandler, log = 0, encoding = 'UTF-8', config = Config, namespace = None, ssl_context = None): # Test the encoding, raising an exception if it's not known if encoding != None: ''.encode(encoding) if ssl_context != None and not config.SSLserver: raise AttributeError, \ "SSL server not supported by this Python installation" self.namespace = namespace self.objmap = {} self.funcmap = {} self.ssl_context = ssl_context self.encoding = encoding self.config = config self.log = log self.allow_reuse_address= 1 SocketServer.UnixStreamServer.__init__(self, str(addr), RequestHandler) SOAPpy-0.12.22/src/SOAPpy/Types.py000066400000000000000000001466161235077700100163710ustar00rootroot00000000000000""" ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ from __future__ import nested_scopes ident = '$Id: Types.py 1496 2010-03-04 23:46:17Z pooryorick $' from version import __version__ import UserList import base64 import cgi import urllib import copy import re import time from types import * # SOAPpy modules from Errors import * from NS import NS from Utilities import encodeHexString, cleanDate from Config import Config NaN = float('NaN') PosInf = float('Inf') NegInf = -PosInf ############################################################################### # Utility functions ############################################################################### def isPrivate(name): return name[0]=='_' def isPublic(name): return name[0]!='_' ############################################################################### # Types and Wrappers ############################################################################### class anyType: _validURIs = (NS.XSD, NS.XSD2, NS.XSD3, NS.ENC) def __init__(self, data = None, name = None, typed = 1, attrs = None): if self.__class__ == anyType: raise Error, "anyType can't be instantiated directly" if type(name) in (ListType, TupleType): self._ns, self._name = name else: self._ns = self._validURIs[0] self._name = name self._typed = typed self._attrs = {} self._cache = None self._type = self._typeName() self._data = self._checkValueSpace(data) if attrs != None: self._setAttrs(attrs) def __str__(self): if hasattr(self,'_name') and self._name: return "<%s %s at %d>" % (self.__class__, self._name, id(self)) return "<%s at %d>" % (self.__class__, id(self)) __repr__ = __str__ def _checkValueSpace(self, data): return data def _marshalData(self): return str(self._data) def _marshalAttrs(self, ns_map, builder): a = '' for attr, value in self._attrs.items(): ns, n = builder.genns(ns_map, attr[0]) a += n + ' %s%s="%s"' % \ (ns, attr[1], cgi.escape(str(value), 1)) return a def _fixAttr(self, attr): if type(attr) in (StringType, UnicodeType): attr = (None, attr) elif type(attr) == ListType: attr = tuple(attr) elif type(attr) != TupleType: raise AttributeError, "invalid attribute type" if len(attr) != 2: raise AttributeError, "invalid attribute length" if type(attr[0]) not in (NoneType, StringType, UnicodeType): raise AttributeError, "invalid attribute namespace URI type" return attr def _getAttr(self, attr): attr = self._fixAttr(attr) try: return self._attrs[attr] except: return None def _setAttr(self, attr, value): attr = self._fixAttr(attr) if type(value) is StringType: value = unicode(value) self._attrs[attr] = value def _setAttrs(self, attrs): if type(attrs) in (ListType, TupleType): for i in range(0, len(attrs), 2): self._setAttr(attrs[i], attrs[i + 1]) return if type(attrs) == DictType: d = attrs elif isinstance(attrs, anyType): d = attrs._attrs else: raise AttributeError, "invalid attribute type" for attr, value in d.items(): self._setAttr(attr, value) def _setMustUnderstand(self, val): self._setAttr((NS.ENV, "mustUnderstand"), val) def _getMustUnderstand(self): return self._getAttr((NS.ENV, "mustUnderstand")) def _setActor(self, val): self._setAttr((NS.ENV, "actor"), val) def _getActor(self): return self._getAttr((NS.ENV, "actor")) def _typeName(self): return self.__class__.__name__[:-4] def _validNamespaceURI(self, URI, strict): if not hasattr(self, '_typed') or not self._typed: return None if URI in self._validURIs: return URI if not strict: return self._ns raise AttributeError, \ "not a valid namespace for type %s" % self._type class voidType(anyType): pass class stringType(anyType): def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (StringType, UnicodeType): raise AttributeError, "invalid %s type:" % self._type return data def _marshalData(self): return self._data class untypedType(stringType): def __init__(self, data = None, name = None, attrs = None): stringType.__init__(self, data, name, 0, attrs) class IDType(stringType): pass class NCNameType(stringType): pass class NameType(stringType): pass class ENTITYType(stringType): pass class IDREFType(stringType): pass class languageType(stringType): pass class NMTOKENType(stringType): pass class QNameType(stringType): pass class tokenType(anyType): _validURIs = (NS.XSD2, NS.XSD3) __invalidre = '[\n\t]|^ | $| ' def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (StringType, UnicodeType): raise AttributeError, "invalid %s type" % self._type if type(self.__invalidre) == StringType: self.__invalidre = re.compile(self.__invalidre) if self.__invalidre.search(data): raise ValueError, "invalid %s value" % self._type return data class normalizedStringType(anyType): _validURIs = (NS.XSD3,) __invalidre = '[\n\r\t]' def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (StringType, UnicodeType): raise AttributeError, "invalid %s type" % self._type if type(self.__invalidre) == StringType: self.__invalidre = re.compile(self.__invalidre) if self.__invalidre.search(data): raise ValueError, "invalid %s value" % self._type return data class CDATAType(normalizedStringType): _validURIs = (NS.XSD2,) class booleanType(anyType): def __int__(self): return self._data __nonzero__ = __int__ def _marshalData(self): return ['false', 'true'][self._data] def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if data in (0, '0', 'false', ''): return 0 if data in (1, '1', 'true'): return 1 raise ValueError, "invalid %s value" % self._type class decimalType(anyType): def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType, FloatType): raise Error, "invalid %s value" % self._type return data class floatType(anyType): def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType, FloatType) or \ data < -3.4028234663852886E+38 or \ data > 3.4028234663852886E+38: raise ValueError, "invalid %s value: %s" % (self._type, repr(data)) return data def _marshalData(self): return "%.18g" % self._data # More precision class doubleType(anyType): def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType, FloatType) or \ data < -1.7976931348623158E+308 or \ data > 1.7976931348623157E+308: raise ValueError, "invalid %s value: %s" % (self._type, repr(data)) return data def _marshalData(self): return "%.18g" % self._data # More precision class durationType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type try: # A tuple or a scalar is OK, but make them into a list if type(data) == TupleType: data = list(data) elif type(data) != ListType: data = [data] if len(data) > 6: raise Exception, "too many values" # Now check the types of all the components, and find # the first nonzero element along the way. f = -1 for i in range(len(data)): if data[i] == None: data[i] = 0 continue if type(data[i]) not in \ (IntType, LongType, FloatType): raise Exception, "element %d a bad type" % i if data[i] and f == -1: f = i # If they're all 0, just use zero seconds. if f == -1: self._cache = 'PT0S' return (0,) * 6 # Make sure only the last nonzero element has a decimal fraction # and only the first element is negative. d = -1 for i in range(f, len(data)): if data[i]: if d != -1: raise Exception, \ "all except the last nonzero element must be " \ "integers" if data[i] < 0 and i > f: raise Exception, \ "only the first nonzero element can be negative" elif data[i] != long(data[i]): d = i # Pad the list on the left if necessary. if len(data) < 6: n = 6 - len(data) f += n d += n data = [0] * n + data # Save index of the first nonzero element and the decimal # element for _marshalData. self.__firstnonzero = f self.__decimal = d except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return tuple(data) def _marshalData(self): if self._cache == None: d = self._data t = 0 if d[self.__firstnonzero] < 0: s = '-P' else: s = 'P' t = 0 for i in range(self.__firstnonzero, len(d)): if d[i]: if i > 2 and not t: s += 'T' t = 1 if self.__decimal == i: s += "%g" % abs(d[i]) else: s += "%d" % long(abs(d[i])) s += ['Y', 'M', 'D', 'H', 'M', 'S'][i] self._cache = s return self._cache class timeDurationType(durationType): _validURIs = (NS.XSD, NS.XSD2, NS.ENC) class dateTimeType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): try: if data == None: data = time.time() if (type(data) in (IntType, LongType)): data = list(time.gmtime(data)[:6]) elif (type(data) == FloatType): f = data - int(data) data = list(time.gmtime(int(data))[:6]) data[5] += f elif type(data) in (ListType, TupleType): if len(data) < 6: raise Exception, "not enough values" if len(data) > 9: raise Exception, "too many values" data = list(data[:6]) cleanDate(data) else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return tuple(data) def _marshalData(self): if self._cache == None: d = self._data s = "%04d-%02d-%02dT%02d:%02d:%02d" % ((abs(d[0]),) + d[1:]) if d[0] < 0: s = '-' + s f = d[5] - int(d[5]) if f != 0: s += ("%g" % f)[1:] s += 'Z' self._cache = s return self._cache class recurringInstantType(anyType): _validURIs = (NS.XSD,) def _checkValueSpace(self, data): try: if data == None: data = list(time.gmtime(time.time())[:6]) if (type(data) in (IntType, LongType)): data = list(time.gmtime(data)[:6]) elif (type(data) == FloatType): f = data - int(data) data = list(time.gmtime(int(data))[:6]) data[5] += f elif type(data) in (ListType, TupleType): if len(data) < 1: raise Exception, "not enough values" if len(data) > 9: raise Exception, "too many values" data = list(data[:6]) if len(data) < 6: data += [0] * (6 - len(data)) f = len(data) for i in range(f): if data[i] == None: if f < i: raise Exception, \ "only leftmost elements can be none" else: f = i break cleanDate(data, f) else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return tuple(data) def _marshalData(self): if self._cache == None: d = self._data e = list(d) neg = '' if not e[0]: e[0] = '--' else: if e[0] < 0: neg = '-' e[0] = abs(e[0]) if e[0] < 100: e[0] = '-' + "%02d" % e[0] else: e[0] = "%04d" % e[0] for i in range(1, len(e)): if e[i] == None or (i < 3 and e[i] == 0): e[i] = '-' else: if e[i] < 0: neg = '-' e[i] = abs(e[i]) e[i] = "%02d" % e[i] if d[5]: f = abs(d[5] - int(d[5])) if f: e[5] += ("%g" % f)[1:] s = "%s%s-%s-%sT%s:%s:%sZ" % ((neg,) + tuple(e)) self._cache = s return self._cache class timeInstantType(dateTimeType): _validURIs = (NS.XSD, NS.XSD2, NS.ENC) class timePeriodType(dateTimeType): _validURIs = (NS.XSD2, NS.ENC) class timeType(anyType): def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[3:6] elif (type(data) == FloatType): f = data - int(data) data = list(time.gmtime(int(data))[3:6]) data[2] += f elif type(data) in (IntType, LongType): data = time.gmtime(data)[3:6] elif type(data) in (ListType, TupleType): if len(data) == 9: data = data[3:6] elif len(data) > 3: raise Exception, "too many values" data = [None, None, None] + list(data) if len(data) < 6: data += [0] * (6 - len(data)) cleanDate(data, 3) data = data[3:] else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return tuple(data) def _marshalData(self): if self._cache == None: d = self._data #s = '' # #s = time.strftime("%H:%M:%S", (0, 0, 0) + d + (0, 0, -1)) s = "%02d:%02d:%02d" % d f = d[2] - int(d[2]) if f != 0: s += ("%g" % f)[1:] s += 'Z' self._cache = s return self._cache class dateType(anyType): def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[0:3] elif type(data) in (IntType, LongType, FloatType): data = time.gmtime(data)[0:3] elif type(data) in (ListType, TupleType): if len(data) == 9: data = data[0:3] elif len(data) > 3: raise Exception, "too many values" data = list(data) if len(data) < 3: data += [1, 1, 1][len(data):] data += [0, 0, 0] cleanDate(data) data = data[:3] else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return tuple(data) def _marshalData(self): if self._cache == None: d = self._data s = "%04d-%02d-%02dZ" % ((abs(d[0]),) + d[1:]) if d[0] < 0: s = '-' + s self._cache = s return self._cache class gYearMonthType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[0:2] elif type(data) in (IntType, LongType, FloatType): data = time.gmtime(data)[0:2] elif type(data) in (ListType, TupleType): if len(data) == 9: data = data[0:2] elif len(data) > 2: raise Exception, "too many values" data = list(data) if len(data) < 2: data += [1, 1][len(data):] data += [1, 0, 0, 0] cleanDate(data) data = data[:2] else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return tuple(data) def _marshalData(self): if self._cache == None: d = self._data s = "%04d-%02dZ" % ((abs(d[0]),) + d[1:]) if d[0] < 0: s = '-' + s self._cache = s return self._cache class gYearType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[0:1] elif type(data) in (IntType, LongType, FloatType): data = [data] if type(data) in (ListType, TupleType): if len(data) == 9: data = data[0:1] elif len(data) < 1: raise Exception, "too few values" elif len(data) > 1: raise Exception, "too many values" if type(data[0]) == FloatType: try: s = int(data[0]) except: s = long(data[0]) if s != data[0]: raise Exception, "not integral" data = [s] elif type(data[0]) not in (IntType, LongType): raise Exception, "bad type" else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return data[0] def _marshalData(self): if self._cache == None: d = self._data s = "%04dZ" % abs(d) if d < 0: s = '-' + s self._cache = s return self._cache class centuryType(anyType): _validURIs = (NS.XSD2, NS.ENC) def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[0:1] / 100 elif type(data) in (IntType, LongType, FloatType): data = [data] if type(data) in (ListType, TupleType): if len(data) == 9: data = data[0:1] / 100 elif len(data) < 1: raise Exception, "too few values" elif len(data) > 1: raise Exception, "too many values" if type(data[0]) == FloatType: try: s = int(data[0]) except: s = long(data[0]) if s != data[0]: raise Exception, "not integral" data = [s] elif type(data[0]) not in (IntType, LongType): raise Exception, "bad type" else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return data[0] def _marshalData(self): if self._cache == None: d = self._data s = "%02dZ" % abs(d) if d < 0: s = '-' + s self._cache = s return self._cache class yearType(gYearType): _validURIs = (NS.XSD2, NS.ENC) class gMonthDayType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[1:3] elif type(data) in (IntType, LongType, FloatType): data = time.gmtime(data)[1:3] elif type(data) in (ListType, TupleType): if len(data) == 9: data = data[0:2] elif len(data) > 2: raise Exception, "too many values" data = list(data) if len(data) < 2: data += [1, 1][len(data):] data = [0] + data + [0, 0, 0] cleanDate(data, 1) data = data[1:3] else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return tuple(data) def _marshalData(self): if self._cache == None: self._cache = "--%02d-%02dZ" % self._data return self._cache class recurringDateType(gMonthDayType): _validURIs = (NS.XSD2, NS.ENC) class gMonthType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[1:2] elif type(data) in (IntType, LongType, FloatType): data = [data] if type(data) in (ListType, TupleType): if len(data) == 9: data = data[1:2] elif len(data) < 1: raise Exception, "too few values" elif len(data) > 1: raise Exception, "too many values" if type(data[0]) == FloatType: try: s = int(data[0]) except: s = long(data[0]) if s != data[0]: raise Exception, "not integral" data = [s] elif type(data[0]) not in (IntType, LongType): raise Exception, "bad type" if data[0] < 1 or data[0] > 12: raise Exception, "bad value" else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return data[0] def _marshalData(self): if self._cache == None: self._cache = "--%02d--Z" % self._data return self._cache class monthType(gMonthType): _validURIs = (NS.XSD2, NS.ENC) class gDayType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): try: if data == None: data = time.gmtime(time.time())[2:3] elif type(data) in (IntType, LongType, FloatType): data = [data] if type(data) in (ListType, TupleType): if len(data) == 9: data = data[2:3] elif len(data) < 1: raise Exception, "too few values" elif len(data) > 1: raise Exception, "too many values" if type(data[0]) == FloatType: try: s = int(data[0]) except: s = long(data[0]) if s != data[0]: raise Exception, "not integral" data = [s] elif type(data[0]) not in (IntType, LongType): raise Exception, "bad type" if data[0] < 1 or data[0] > 31: raise Exception, "bad value" else: raise Exception, "invalid type" except Exception, e: raise ValueError, "invalid %s value - %s" % (self._type, e) return data[0] def _marshalData(self): if self._cache == None: self._cache = "---%02dZ" % self._data return self._cache class recurringDayType(gDayType): _validURIs = (NS.XSD2, NS.ENC) class hexBinaryType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (StringType, UnicodeType): raise AttributeError, "invalid %s type" % self._type return data def _marshalData(self): if self._cache == None: self._cache = encodeHexString(self._data) return self._cache class base64BinaryType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (StringType, UnicodeType): raise AttributeError, "invalid %s type" % self._type return data def _marshalData(self): if self._cache == None: self._cache = base64.encodestring(self._data) return self._cache class base64Type(base64BinaryType): _validURIs = (NS.ENC,) class binaryType(anyType): _validURIs = (NS.XSD, NS.ENC) def __init__(self, data, name = None, typed = 1, encoding = 'base64', attrs = None): anyType.__init__(self, data, name, typed, attrs) self._setAttr('encoding', encoding) def _marshalData(self): if self._cache == None: if self._getAttr((None, 'encoding')) == 'base64': self._cache = base64.encodestring(self._data) else: self._cache = encodeHexString(self._data) return self._cache def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (StringType, UnicodeType): raise AttributeError, "invalid %s type" % self._type return data def _setAttr(self, attr, value): attr = self._fixAttr(attr) if attr[1] == 'encoding': if attr[0] != None or value not in ('base64', 'hex'): raise AttributeError, "invalid encoding" self._cache = None anyType._setAttr(self, attr, value) class anyURIType(anyType): _validURIs = (NS.XSD3,) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (StringType, UnicodeType): raise AttributeError, "invalid %s type" % self._type return data def _marshalData(self): if self._cache == None: self._cache = urllib.quote(self._data) return self._cache class uriType(anyURIType): _validURIs = (NS.XSD,) class uriReferenceType(anyURIType): _validURIs = (NS.XSD2,) class NOTATIONType(anyType): def __init__(self, data, name = None, typed = 1, attrs = None): if self.__class__ == NOTATIONType: raise Error, "a NOTATION can't be instantiated directly" anyType.__init__(self, data, name, typed, attrs) class ENTITIESType(anyType): def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) in (StringType, UnicodeType): return (data,) if type(data) not in (ListType, TupleType) or \ filter (lambda x: type(x) not in (StringType, UnicodeType), data): raise AttributeError, "invalid %s type" % self._type return data def _marshalData(self): return ' '.join(self._data) class IDREFSType(ENTITIESType): pass class NMTOKENSType(ENTITIESType): pass class integerType(anyType): def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType): raise ValueError, "invalid %s value" % self._type return data class nonPositiveIntegerType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or data > 0: raise ValueError, "invalid %s value" % self._type return data class non_Positive_IntegerType(nonPositiveIntegerType): _validURIs = (NS.XSD,) def _typeName(self): return 'non-positive-integer' class negativeIntegerType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or data >= 0: raise ValueError, "invalid %s value" % self._type return data class negative_IntegerType(negativeIntegerType): _validURIs = (NS.XSD,) def _typeName(self): return 'negative-integer' class longType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < -9223372036854775808L or \ data > 9223372036854775807L: raise ValueError, "invalid %s value" % self._type return data class intType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < -2147483648L or \ data > 2147483647L: raise ValueError, "invalid %s value" % self._type return data class shortType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < -32768 or \ data > 32767: raise ValueError, "invalid %s value" % self._type return data class byteType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < -128 or \ data > 127: raise ValueError, "invalid %s value" % self._type return data class nonNegativeIntegerType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or data < 0: raise ValueError, "invalid %s value" % self._type return data class non_Negative_IntegerType(nonNegativeIntegerType): _validURIs = (NS.XSD,) def _typeName(self): return 'non-negative-integer' class unsignedLongType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < 0 or \ data > 18446744073709551615L: raise ValueError, "invalid %s value" % self._type return data class unsignedIntType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < 0 or \ data > 4294967295L: raise ValueError, "invalid %s value" % self._type return data class unsignedShortType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < 0 or \ data > 65535: raise ValueError, "invalid %s value" % self._type return data class unsignedByteType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or \ data < 0 or \ data > 255: raise ValueError, "invalid %s value" % self._type return data class positiveIntegerType(anyType): _validURIs = (NS.XSD2, NS.XSD3, NS.ENC) def _checkValueSpace(self, data): if data == None: raise ValueError, "must supply initial %s value" % self._type if type(data) not in (IntType, LongType) or data <= 0: raise ValueError, "invalid %s value" % self._type return data class positive_IntegerType(positiveIntegerType): _validURIs = (NS.XSD,) def _typeName(self): return 'positive-integer' # Now compound types class compoundType(anyType): def __init__(self, data = None, name = None, typed = 1, attrs = None): if self.__class__ == compoundType: raise Error, "a compound can't be instantiated directly" anyType.__init__(self, data, name, typed, attrs) self._keyord = [] if type(data) == DictType: self.__dict__.update(data) def _aslist(self, item=None): if item is not None: return self.__dict__[self._keyord[item]] else: return map( lambda x: self.__dict__[x], self._keyord) def _asdict(self, item=None, encoding=Config.dict_encoding): if item is not None: if type(item) in (UnicodeType,StringType): item = item.encode(encoding) return self.__dict__[item] else: retval = {} def fun(x): retval[x.encode(encoding)] = self.__dict__[x] if hasattr(self, '_keyord'): map( fun, self._keyord) else: for name in dir(self): if isPublic(name): retval[name] = getattr(self,name) return retval def __getitem__(self, item): if type(item) == IntType: return self.__dict__[self._keyord[item]] else: return getattr(self, item) def __len__(self): return len(self._keyord) def __nonzero__(self): return 1 def _keys(self): return filter(lambda x: x[0] != '_', self.__dict__.keys()) def _addItem(self, name, value, attrs = None): if name in self._keyord: if type(self.__dict__[name]) != ListType: self.__dict__[name] = [self.__dict__[name]] self.__dict__[name].append(value) else: self.__dict__[name] = value self._keyord.append(name) def _placeItem(self, name, value, pos, subpos = 0, attrs = None): if subpos == 0 and type(self.__dict__[name]) != ListType: self.__dict__[name] = value else: self.__dict__[name][subpos] = value # only add to key order list if it does not already # exist in list if not (name in self._keyord): if pos < len(x): self._keyord[pos] = name else: self._keyord.append(name) def _getItemAsList(self, name, default = []): try: d = self.__dict__[name] except: return default if type(d) == ListType: return d return [d] def __str__(self): return anyType.__str__(self) + ": " + str(self._asdict()) def __repr__(self): return self.__str__() class structType(compoundType): pass class headerType(structType): _validURIs = (NS.ENV,) def __init__(self, data = None, typed = 1, attrs = None): structType.__init__(self, data, "Header", typed, attrs) class bodyType(structType): _validURIs = (NS.ENV,) def __init__(self, data = None, typed = 1, attrs = None): structType.__init__(self, data, "Body", typed, attrs) class arrayType(UserList.UserList, compoundType): def __init__(self, data = None, name = None, attrs = None, offset = 0, rank = None, asize = 0, elemsname = None): if data: if type(data) not in (ListType, TupleType): raise Error, "Data must be a sequence" UserList.UserList.__init__(self, data) compoundType.__init__(self, data, name, 0, attrs) self._elemsname = elemsname or "item" if data == None: self._rank = rank # According to 5.4.2.2 in the SOAP spec, each element in a # sparse array must have a position. _posstate keeps track of # whether we've seen a position or not. It's possible values # are: # -1 No elements have been added, so the state is indeterminate # 0 An element without a position has been added, so no # elements can have positions # 1 An element with a position has been added, so all elements # must have positions self._posstate = -1 self._full = 0 if asize in ('', None): asize = '0' self._dims = map (lambda x: int(x), str(asize).split(',')) self._dims.reverse() # It's easier to work with this way self._poss = [0] * len(self._dims) # This will end up # reversed too for i in range(len(self._dims)): if self._dims[i] < 0 or \ self._dims[i] == 0 and len(self._dims) > 1: raise TypeError, "invalid Array dimensions" if offset > 0: self._poss[i] = offset % self._dims[i] offset = int(offset / self._dims[i]) # Don't break out of the loop if offset is 0 so we test all the # dimensions for > 0. if offset: raise AttributeError, "invalid Array offset" a = [None] * self._dims[0] for i in range(1, len(self._dims)): b = [] for j in range(self._dims[i]): b.append(copy.deepcopy(a)) a = b self.data = a def _aslist(self, item=None): if item is not None: return self.data[int(item)] else: return self.data def _asdict(self, item=None, encoding=Config.dict_encoding): if item is not None: if type(item) in (UnicodeType,StringType): item = item.encode(encoding) return self.data[int(item)] else: retval = {} def fun(x): retval[str(x).encode(encoding)] = self.data[x] map( fun, range(len(self.data)) ) return retval def __getitem__(self, item): try: return self.data[int(item)] except ValueError: return getattr(self, item) def __len__(self): return len(self.data) def __nonzero__(self): return 1 def __str__(self): return anyType.__str__(self) + ": " + str(self._aslist()) def _keys(self): return filter(lambda x: x[0] != '_', self.__dict__.keys()) def _addItem(self, name, value, attrs): if self._full: raise ValueError, "Array is full" pos = attrs.get((NS.ENC, 'position')) if pos != None: if self._posstate == 0: raise AttributeError, \ "all elements in a sparse Array must have a " \ "position attribute" self._posstate = 1 try: if pos[0] == '[' and pos[-1] == ']': pos = map (lambda x: int(x), pos[1:-1].split(',')) pos.reverse() if len(pos) == 1: pos = pos[0] curpos = [0] * len(self._dims) for i in range(len(self._dims)): curpos[i] = pos % self._dims[i] pos = int(pos / self._dims[i]) if pos == 0: break if pos: raise Exception elif len(pos) != len(self._dims): raise Exception else: for i in range(len(self._dims)): if pos[i] >= self._dims[i]: raise Exception curpos = pos else: raise Exception except: raise AttributeError, \ "invalid Array element position %s" % str(pos) else: if self._posstate == 1: raise AttributeError, \ "only elements in a sparse Array may have a " \ "position attribute" self._posstate = 0 curpos = self._poss a = self.data for i in range(len(self._dims) - 1, 0, -1): a = a[curpos[i]] if curpos[0] >= len(a): a += [None] * (len(a) - curpos[0] + 1) a[curpos[0]] = value if pos == None: self._poss[0] += 1 for i in range(len(self._dims) - 1): if self._poss[i] < self._dims[i]: break self._poss[i] = 0 self._poss[i + 1] += 1 if self._dims[-1] and self._poss[-1] >= self._dims[-1]: #self._full = 1 #FIXME: why is this occuring? pass def _placeItem(self, name, value, pos, subpos, attrs = None): curpos = [0] * len(self._dims) for i in range(len(self._dims)): if self._dims[i] == 0: curpos[0] = pos break curpos[i] = pos % self._dims[i] pos = int(pos / self._dims[i]) if pos == 0: break if self._dims[i] != 0 and pos: raise Error, "array index out of range" a = self.data for i in range(len(self._dims) - 1, 0, -1): a = a[curpos[i]] if curpos[0] >= len(a): a += [None] * (len(a) - curpos[0] + 1) a[curpos[0]] = value class mapType(arrayType): _validURIs = ('http://xml.apache.org/xml-soap',) def __init__(self, data = None, name = None, attrs = None, offset = 0, rank = None, asize = 0, elemsname = None): arrayType.__init__(self, data, name, attrs, offset, rank, asize, elemsname) self._keyord=['key','value'] class typedArrayType(arrayType): def __init__(self, data = None, name = None, typed = None, attrs = None, offset = 0, rank = None, asize = 0, elemsname = None, complexType = 0): arrayType.__init__(self, data, name, attrs, offset, rank, asize, elemsname) self._typed = 1 self._type = typed self._complexType = complexType class faultType(structType, Error): def __init__(self, faultcode = "", faultstring = "", detail = None): self.faultcode = faultcode self.faultstring = faultstring if detail != None: self.detail = detail structType.__init__(self, None, 0) def _setDetail(self, detail = None): if detail != None: self.detail = detail else: try: del self.detail except AttributeError: pass def __repr__(self): if getattr(self, 'detail', None) != None: return "" % (self.faultcode, self.faultstring, self.detail) else: return "" % (self.faultcode, self.faultstring) __str__ = __repr__ def __call__(self): return (self.faultcode, self.faultstring, self.detail) class SOAPException(Exception): def __init__(self, code="", string="", detail=None): self.value = ("SOAPpy SOAP Exception", code, string, detail) self.code = code self.string = string self.detail = detail def __str__(self): return repr(self.value) class RequiredHeaderMismatch(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class MethodNotFound(Exception): def __init__(self, value): (val, detail) = value.split(":") self.value = val self.detail = detail def __str__(self): return repr(self.value, self.detail) class AuthorizationFailed(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class MethodFailed(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) ####### # Convert complex SOAPpy objects to native python equivalents ####### def simplify(object, level=0): """ Convert the SOAPpy objects and their contents to simple python types. This function recursively converts the passed 'container' object, and all public subobjects. (Private subobjects have names that start with '_'.) Conversions: - faultType --> raise python exception - arrayType --> array - compoundType --> dictionary """ if level > 10: return object if isinstance( object, faultType ): if object.faultstring == "Required Header Misunderstood": raise RequiredHeaderMismatch(object.detail) elif object.faultstring == "Method Not Found": raise MethodNotFound(object.detail) elif object.faultstring == "Authorization Failed": raise AuthorizationFailed(object.detail) elif object.faultstring == "Method Failed": raise MethodFailed(object.detail) else: se = SOAPException(object.faultcode, object.faultstring, object.detail) raise se elif isinstance( object, arrayType ): data = object._aslist() for k in range(len(data)): data[k] = simplify(data[k], level=level+1) return data elif isinstance( object, compoundType ) or isinstance(object, structType): data = object._asdict() for k in data.keys(): if isPublic(k): data[k] = simplify(data[k], level=level+1) return data elif type(object)==DictType: for k in object.keys(): if isPublic(k): object[k] = simplify(object[k]) return object elif type(object)==list: for k in range(len(object)): object[k] = simplify(object[k]) return object else: return object def simplify_contents(object, level=0): """ Convert the contents of SOAPpy objects to simple python types. This function recursively converts the sub-objects contained in a 'container' object to simple python types. Conversions: - faultType --> raise python exception - arrayType --> array - compoundType --> dictionary """ if level>10: return object if isinstance( object, faultType ): for k in object._keys(): if isPublic(k): setattr(object, k, simplify(object[k], level=level+1)) raise object elif isinstance( object, arrayType ): data = object._aslist() for k in range(len(data)): object[k] = simplify(data[k], level=level+1) elif isinstance(object, structType): data = object._asdict() for k in data.keys(): if isPublic(k): setattr(object, k, simplify(data[k], level=level+1)) elif isinstance( object, compoundType ) : data = object._asdict() for k in data.keys(): if isPublic(k): object[k] = simplify(data[k], level=level+1) elif type(object)==DictType: for k in object.keys(): if isPublic(k): object[k] = simplify(object[k]) elif type(object)==list: for k in range(len(object)): object[k] = simplify(object[k]) return object SOAPpy-0.12.22/src/SOAPpy/URLopener.py000066400000000000000000000011101235077700100171130ustar00rootroot00000000000000"""Provide a class for loading data from URL's that handles basic authentication""" ident = '$Id: URLopener.py 541 2004-01-31 04:20:06Z warnes $' from version import __version__ from Config import Config from urllib import FancyURLopener class URLopener(FancyURLopener): username = None passwd = None def __init__(self, username=None, passwd=None, *args, **kw): FancyURLopener.__init__( self, *args, **kw) self.username = username self.passwd = passwd def prompt_user_passwd(self, host, realm): return self.username, self.passwd SOAPpy-0.12.22/src/SOAPpy/Utilities.py000066400000000000000000000117701235077700100172300ustar00rootroot00000000000000""" ################################################################################ # Copyright (c) 2003, Pfizer # Copyright (c) 2001, Cayce Ullman. # Copyright (c) 2001, Brian Matthews. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # Neither the name of actzero, inc. nor the names of its contributors may # be used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ################################################################################ """ ident = '$Id: Utilities.py 1298 2006-11-07 00:54:15Z sanxiyn $' from version import __version__ import re import string import sys from types import * # SOAPpy modules from Errors import * ################################################################################ # Utility infielders ################################################################################ def collapseWhiteSpace(s): return re.sub('\s+', ' ', s).strip() def decodeHexString(data): conv = { '0': 0x0, '1': 0x1, '2': 0x2, '3': 0x3, '4': 0x4, '5': 0x5, '6': 0x6, '7': 0x7, '8': 0x8, '9': 0x9, 'a': 0xa, 'b': 0xb, 'c': 0xc, 'd': 0xd, 'e': 0xe, 'f': 0xf, 'A': 0xa, 'B': 0xb, 'C': 0xc, 'D': 0xd, 'E': 0xe, 'F': 0xf, } ws = string.whitespace bin = '' i = 0 while i < len(data): if data[i] not in ws: break i += 1 low = 0 while i < len(data): c = data[i] if c in string.whitespace: break try: c = conv[c] except KeyError: raise ValueError, \ "invalid hex string character `%s'" % c if low: bin += chr(high * 16 + c) low = 0 else: high = c low = 1 i += 1 if low: raise ValueError, "invalid hex string length" while i < len(data): if data[i] not in string.whitespace: raise ValueError, \ "invalid hex string character `%s'" % c i += 1 return bin def encodeHexString(data): h = '' for i in data: h += "%02X" % ord(i) return h def leapMonth(year, month): return month == 2 and \ year % 4 == 0 and \ (year % 100 != 0 or year % 400 == 0) def cleanDate(d, first = 0): ranges = (None, (1, 12), (1, 31), (0, 23), (0, 59), (0, 61)) months = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) names = ('year', 'month', 'day', 'hours', 'minutes', 'seconds') if len(d) != 6: raise ValueError, "date must have 6 elements" for i in range(first, 6): s = d[i] if type(s) == FloatType: if i < 5: try: s = int(s) except OverflowError: if i > 0: raise s = long(s) if s != d[i]: raise ValueError, "%s must be integral" % names[i] d[i] = s elif type(s) == LongType: try: s = int(s) except: pass elif type(s) != IntType: raise TypeError, "%s isn't a valid type" % names[i] if i == first and s < 0: continue if ranges[i] != None and \ (s < ranges[i][0] or ranges[i][1] < s): raise ValueError, "%s out of range" % names[i] if first < 6 and d[5] >= 61: raise ValueError, "seconds out of range" if first < 2: leap = first < 1 and leapMonth(d[0], d[1]) if d[2] > months[d[1]] + leap: raise ValueError, "day out of range" def debugHeader(title): s = '*** ' + title + ' ' print s + ('*' * (72 - len(s))) def debugFooter(title): print '*' * 72 sys.stdout.flush() SOAPpy-0.12.22/src/SOAPpy/WSDL.py000066400000000000000000000117541235077700100160300ustar00rootroot00000000000000"""Parse web services description language to get SOAP methods. Rudimentary support.""" ident = '$Id: WSDL.py 1467 2008-05-16 23:32:51Z warnes $' from version import __version__ import wstools import xml from Errors import Error from Client import SOAPProxy, SOAPAddress from Config import Config import urllib class Proxy: """WSDL Proxy. SOAPProxy wrapper that parses method names, namespaces, soap actions from the web service description language (WSDL) file passed into the constructor. The WSDL reference can be passed in as a stream, an url, a file name, or a string. Loads info into self.methods, a dictionary with methodname keys and values of WSDLTools.SOAPCallinfo. For example, url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' wsdl = WSDL.Proxy(url) print len(wsdl.methods) # 1 print wsdl.methods.keys() # getTemp See WSDLTools.SOAPCallinfo for more info on each method's attributes. """ def __init__(self, wsdlsource, config=Config, **kw ): reader = wstools.WSDLTools.WSDLReader() self.wsdl = None # From Mark Pilgrim's "Dive Into Python" toolkit.py--open anything. if self.wsdl is None and hasattr(wsdlsource, "read"): print 'stream:', wsdlsource try: self.wsdl = reader.loadFromStream(wsdlsource) except xml.parsers.expat.ExpatError, e: newstream = urllib.URLopener(key_file=config.SSL.key_file, cert_file=config.SSL.cert_file).open(wsdlsource) buf = newstream.readlines() raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ (wsdlsource, "\t".join(buf)) # NOT TESTED (as of April 17, 2003) #if self.wsdl is None and wsdlsource == '-': # import sys # self.wsdl = reader.loadFromStream(sys.stdin) # print 'stdin' if self.wsdl is None: try: file(wsdlsource) self.wsdl = reader.loadFromFile(wsdlsource) #print 'file' except (IOError, OSError): pass except xml.parsers.expat.ExpatError, e: newstream = urllib.urlopen(wsdlsource) buf = newstream.readlines() raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ (wsdlsource, "\t".join(buf)) if self.wsdl is None: try: stream = urllib.URLopener(key_file=config.SSL.key_file, cert_file=config.SSL.cert_file).open(wsdlsource) self.wsdl = reader.loadFromStream(stream, wsdlsource) except (IOError, OSError): pass except xml.parsers.expat.ExpatError, e: newstream = urllib.urlopen(wsdlsource) buf = newstream.readlines() raise Error, "Unable to parse WSDL file at %s: \n\t%s" % \ (wsdlsource, "\t".join(buf)) if self.wsdl is None: import StringIO self.wsdl = reader.loadFromString(str(wsdlsource)) #print 'string' # Package wsdl info as a dictionary of remote methods, with method name # as key (based on ServiceProxy.__init__ in ZSI library). self.methods = {} service = self.wsdl.services[0] port = service.ports[0] name = service.name binding = port.getBinding() portType = binding.getPortType() for operation in portType.operations: callinfo = wstools.WSDLTools.callInfoFromWSDL(port, operation.name) self.methods[callinfo.methodName] = callinfo self.soapproxy = SOAPProxy('http://localhost/dummy.webservice', config=config, **kw) def __str__(self): s = '' for method in self.methods.values(): s += str(method) return s def __getattr__(self, name): """Set up environment then let parent class handle call. Raises AttributeError is method name is not found.""" if not self.methods.has_key(name): raise AttributeError, name callinfo = self.methods[name] self.soapproxy.proxy = SOAPAddress(callinfo.location) self.soapproxy.namespace = callinfo.namespace self.soapproxy.soapaction = callinfo.soapAction return self.soapproxy.__getattr__(name) def show_methods(self): for key in self.methods.keys(): method = self.methods[key] print "Method Name:", key.ljust(15) print inps = method.inparams for parm in range(len(inps)): details = inps[parm] print " In #%d: %s (%s)" % (parm, details.name, details.type) print outps = method.outparams for parm in range(len(outps)): details = outps[parm] print " Out #%d: %s (%s)" % (parm, details.name, details.type) print SOAPpy-0.12.22/src/SOAPpy/__init__.py000066400000000000000000000005461235077700100170130ustar00rootroot00000000000000 ident = '$Id: __init__.py 541 2004-01-31 04:20:06Z warnes $' from version import __version__ from Client import * from Config import * from Errors import * from NS import * from Parser import * from SOAPBuilder import * from Server import * from Types import * from Utilities import * import wstools import WSDL SOAPpy-0.12.22/src/SOAPpy/version.py000066400000000000000000000001771235077700100167410ustar00rootroot00000000000000try: import pkg_resources __version__ = pkg_resources.get_distribution("SOAPpy").version except: __version__="xxx" SOAPpy-0.12.22/tests/000077500000000000000000000000001235077700100141355ustar00rootroot00000000000000SOAPpy-0.12.22/tests/BabelfishWSDLTest.py000077500000000000000000000015711235077700100177270ustar00rootroot00000000000000#!/usr/bin/env python ident = '$Id: BabelfishWSDLTest.py,v 1.1 2003/07/18 15:58:28 warnes Exp $' import os, re import sys sys.path.insert(1, "..") from SOAPpy import WSDL # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None server = WSDL.Proxy('http://www.xmethods.net/sd/2001/BabelFishService.wsdl', http_proxy=proxy) english = "Hi Friend!" print "Babelfish Translations" print "------------------------" print "English: '%s'" % english print "French: '%s'" % server.BabelFish('en_fr',english) print "Spanish: '%s'" % server.BabelFish('en_es',english) print "Italian: '%s'" % server.BabelFish('en_it',english) print "German: '%s'" % server.BabelFish('en_de',english) print "Done." SOAPpy-0.12.22/tests/Bug1001646.py000066400000000000000000000030751235077700100157730ustar00rootroot00000000000000""" Check handing of unicode. """ import sys sys.path.insert(1, "..") from SOAPpy import * # Uncomment to see outgoing HTTP headers and SOAP and incoming #Config.debug = 1 #Config.dumpHeadersIn = 1 #Config.dumpSOAPIn = 1 #Config.dumpSOAPOut = 1 # ask for returned SOAP responses to be converted to basic python types Config.simplify_objects = 1 #Config.BuildWithNoType = 1 #Config.BuildWithNoNamespacePrefix = 1 def headers(): '''Return a soap header containing all the needed information.''' hd = Types.headerType() hd.useragent = Types.stringType("foo") return hd server = SOAPProxy("http://localhost:9900/",header=headers()) adgroupid = 197497504 keyword1 = { 'status': 'Moderate', 'adGroupId': 197497504, 'destinationURL': None, 'language': '', 'text': 'does not work', 'negative': bool(0), 'maxCpc': 50000, 'type': 'Keyword', 'id': 1 } keyword2 = { 'status': 'Moderate', 'adGroupId': 197497504, 'destinationURL': None, 'language': '', 'text': 'yes it does not', 'negative': bool(0), 'maxCpc': 50000, 'type': 'Keyword', 'id': 2 } keylist = [keyword1, keyword2] # Check that the data goes through properly retval = server.echo_simple(adgroupid, keylist) kw1 = retval[1][0] kw2 = retval[1][1] assert(retval[0] == adgroupid) for key in kw1.keys(): assert(kw1[key]==keyword1[key]) for key in kw2.keys(): assert(kw2[key]==keyword2[key]) # Check that the header is preserved retval = server.echo_header((adgroupid, keylist)) assert(retval[1].has_key('useragent')) assert(retval[1]['useragent'] == 'foo') server.quit() print "Success!" SOAPpy-0.12.22/tests/Bug916265.py000066400000000000000000000015071235077700100157240ustar00rootroot00000000000000""" Check handing of unicode. """ import sys sys.path.insert(1, "..") from SOAPpy import * # Uncomment to see outgoing HTTP headers and SOAP and incoming #Config.debug = 1 #Config.dumpHeadersIn = 1 #Config.dumpSOAPIn = 1 #Config.dumpSOAPOut = 1 # ask for returned SOAP responses to be converted to basic python types Config.simplify_objects = 0 #Config.BuildWithNoType = 1 #Config.BuildWithNoNamespacePrefix = 1 server = SOAPProxy("http://localhost:9900/") x = u'uMOO' # Single unicode string y = server.echo_simple((x,)) assert( x==y[0] ) x = [u'uMoo1',u'uMoo2'] # array of unicode strings y = server.echo_simple(x) assert( x[0] == y[0] ) assert( x[1] == y[1] ) x = { u'A':1, u'B':u'B', 'C':u'C', 'D':'D' } y = server.echo_simple(x) for key in x.keys(): assert( x[key] == y[0][key] ) print "Success" SOAPpy-0.12.22/tests/Bug918216.py000066400000000000000000000026171235077700100157250ustar00rootroot00000000000000import sys sys.path.insert(1, "..") from SOAPpy import * detailed_fault = \ """ soapenv:Server.generalException Exception thrown on Server ... Login failure (504):Unknown User ... ... ... ... """ z = parseSOAPRPC(detailed_fault.strip() ) assert(z.__class__==faultType) assert(z.faultstring=="Exception thrown on Server") assert(z.detail.loginFailureFault.description=='Login failure (504):Unknown User') print "Success" SOAPpy-0.12.22/tests/ComplexTypes.py000066400000000000000000000012101235077700100171350ustar00rootroot00000000000000import sys sys.path.insert(1, "..") import SOAPpy import time dep = SOAPpy.dateTimeType((2004, 3, 24, 12, 30, 59, 4, 86, 0)) ret = SOAPpy.dateTimeType((2004, 3, 26, 12, 30, 59, 4, 86, 0)) in0 = SOAPpy.structType() in0._addItem('outwardDate', dep) in0._addItem('returnDate', ret) in0._addItem('originAirport', 'den') in0._addItem('destinationAirport', 'iad') x = SOAPpy.buildSOAP( in0, method="getAirFareQuote", namespace="urn:SBGAirFareQuotes.sbg.travel.ws.dsdata.co.uk" ) wsdl = 'http://www.xmethods.net/sd/2001/TemperatureService.wsdl' proxy = SOAPpy.WSDL.Proxy(wsdl) SOAPpy-0.12.22/tests/GoogleTest.py000066400000000000000000000006221235077700100165630ustar00rootroot00000000000000from SOAPpy import WSDL server = WSDL.Proxy('/home/warneg/src/google/googleapi/GoogleSearch.wsdl') key = "6k0oDPZQFHL0zpjy6ZO6ufUVFKBgvqTo" results = server.doGoogleSearch(key, 'warnes', 0, 10, False, "", False, "", "utf-8", "utf-8") for i in range(len(results.resultElements)): res = results.resultElements[i] print '%d: %s --> %s' % ( i, res.title, res.URL ) SOAPpy-0.12.22/tests/SOAPtest.py000077500000000000000000004214671235077700100161720ustar00rootroot00000000000000#!/usr/bin/env python ################################################################################ # # A bunch of regression type tests for the builder and parser. # ################################################################################ ident = '$Id: SOAPtest.py,v 1.19 2004/04/01 13:25:46 warnes Exp $' import urllib import sys import unittest import re sys.path.insert(1, "..") from SOAPpy import * config=Config config.strict_range=1 # run these tests with this variable set both to 1 and 0 config.simplify_objects=0 # as borrowed from jake.soapware.org for float compares. def nearlyeq(a, b, prec = 1e-7): return abs(a - b) <= abs(a) * prec # helper def negfloat(x): return float(x) * -1.0 class Book(structType): def __init__(self): self.title = "Title of a book" structType.__init__(self) class Person(structType): def __init__(self): self.age = "49" self.height = "5.5" structType.__init__(self) class Result(structType): def __init__(self): structType.__init__(self, name = 'Result') self.Book = Book() self.Person = Person() class one: def __init__(self): self.str = "one" class two: def __init__(self): self.str = "two" class three: def __init__(self): self.str = "three" ws = ' \t\r\n' N = None class SOAPTestCase(unittest.TestCase): # big message def notestBigMessage(self): x=[] for y in string.lowercase: x.append(y*999999) buildSOAP(x) # test arrayType def testArrayType(self): x = structType( {"name":"widg1","quantity":200, "price":decimalType(45.99), "_typename":"LineItem"}) y = buildSOAP([x, x]) # could be parsed using an XML parser? self.failUnless(string.find(y, "LineItem")>-1) # test arguments ordering def testOrdering(self): x = buildSOAP(method="newCustomer", namespace="urn:customer", \ kw={"name":"foo1", "address":"bar"}, \ config=SOAPConfig(argsOrdering={"newCustomer":("address", "name")})) # could be parsed using an XML parser? self.failUnless(string.find(x, "
string.find(x, " My Life and Work Henry Ford 49 5.5 ''' # parse rules pr = {'SomeMethod': {'Result': {'Book': {'title':(NS.XSD, "string")}, 'Person': {'age':(NS.XSD, "int"), 'height':negfloat} } } } y = parseSOAPRPC(x, rules=pr) if config.simplify_objects: self.assertEquals(y['Result']['Person']['age'], 49); self.assertEquals(y['Result']['Person']['height'], -5.5); else: self.assertEquals(y.Result.Person.age, 49); self.assertEquals(y.Result.Person.height, -5.5); # Try the reverse def testStructOut(self): x = buildSOAP(Result()) def testIntFloat(self): x=''' West Virginia -546 -5.398 New Mexico -641 -9.351 Missouri -819 1.375 ''' y = parseSOAPRPC(x) if(config.simplify_objects): self.assertEquals(y['return'][0]['varString'], "West Virginia") self.assertEquals(y['return'][1]['varInt'], -641) self.assertEquals(y['return'][2]['varFloat'], 1.375) else: self.assertEquals(getattr(y,"return")[0].varString, "West Virginia") self.assertEquals(getattr(y,"return")[1].varInt, -641) self.assertEquals(getattr(y,"return")[2].varFloat, 1.375) def testArray1(self): x=''' West Virginia -546 -5.398 New Mexico -641 -9.351 Missouri -819 1.375 ''' y = parseSOAPRPC(x) if(config.simplify_objects): self.assertEquals(y["return"][0]['string'], "West Virginia") self.assertEquals(y["return"][1]['int'], -641) self.assertEquals(y["return"][2]['float'], 1.375) else: self.assertEquals(getattr(y,"return")[0].string, "West Virginia") self.assertEquals(getattr(y,"return")[1].int, -641) self.assertEquals(getattr(y,"return")[2].float, 1.375) def testUTF8Encoding1(self): x = ''' Hello \'<&>" ''' y = parseSOAPRPC(x) if config.simplify_objects: self.assertEquals(y['return2'][1], "Hello") else: self.assertEquals(y.return2[1], "Hello") def testUTF8Encoding2(self): x = ''' Hello \'<&>" Goodbye ''' y = parseSOAPRPC(x) self.assertEquals(type(y.a), type([])) self.assertEquals(type(y.b), type('')) self.assertEquals(type(y._getItemAsList('a')), type([])) self.assertEquals(type(y._getItemAsList('b')), type([])) self.assertEquals(y.b, 'Goodbye') self.assertEquals(y.a, ['', 'Hello', '\'<&>"']) self.assertEquals(y._getItemAsList('b'), ['Goodbye']) self.assertEquals(y._getItemAsList('c'), []) self.assertEquals(y._getItemAsList('c', 'hello'), 'hello') def testUTF8Encoding2(self): x = ''' Hello \'<&>" Goodbye ''' y = parseSOAP(x) self.assertEquals(y.a1, 'Hello') self.assertEquals(y.a3, 'Goodbye') self.failIf(hasattr(y, 'a2')) def testUTF8Encoding3(self): x = ''' My Life and Work Henry Ford
mailto:henryford@hotmail.com http://www.henryford.com
''' y = parseSOAPRPC(x) if config.simplify_objects: self.assertEquals(y['Result']['Book']['author']['name'], "Henry Ford") self.assertEquals(y['Result']['Book']['author']['address']['web'], "http://www.henryford.com") self.assertEquals(y['Result']['Book']['author']['address']['pers']['name'], "Henry Ford") else: self.assertEquals(y.Result.Book.author.name, "Henry Ford") self.assertEquals(y.Result.Book.author.address.web, "http://www.henryford.com") self.assertEquals(y.Result.Book.author.address.pers.name, "Henry Ford") # ref example def testRef(self): x = ''' 0 1 -1 3853.33325 ''' y = parseSOAPRPC(x) if config.simplify_objects: self.assertEquals(y['Return'][0], 0) self.assertEquals(y['Return'][1], 1) self.assertEquals(y['Return'][2], -1) self.failUnless(nearlyeq(y['Return'][3], 3853.33325)) else: self.assertEquals(y.Return[0], 0) self.assertEquals(y.Return[1], 1) self.assertEquals(y.Return[2], -1) self.failUnless(nearlyeq(y.Return[3], 3853.33325)) # Make sure passing in our own bodyType works. def testBodyType(self): a = [23, 42] b = bodyType() b.a = b.b = a x = buildSOAP(b) y = parseSOAP(x) self.assertEquals(id(y.a), id(y.b)) self.assertEquals(y.a, a) self.assertEquals(y.b, a) # Test Envelope versioning (see section 4.1.2 of http://www.w3.org/TR/SOAP). def testEnvelopeVersioning(self): xml = ''' <_1 xsi:type="xsd:int" SOAP-ENC:root="1">1 ''' try: parseSOAP(xml) except Exception, e: self.failUnless(isinstance(e, faultType)) self.assertEquals(e.faultcode, '%s:VersionMismatch' % NS.ENV_T) self.failIf(hasattr(e, 'detail')) # Big terrible ordered data with attributes test. def testBigOrderedData(self): data = ''' first_main_item whatever etc. unoItem1 unoItem2 unoItem3 second_main_item whatever etc. dosItem1 dosItem2 dosItem3 single_main_item whatever etc. singleItem1 ''' x = parseSOAP(data) # print ".>",x.replyBlock.itemList._ns y = buildSOAP(x) def testEnvelope1(self): my_xml2 = ''' 5 34.5 10000 ''' (x,h) = parseSOAPRPC(my_xml2,header=1) def testEnvelope2(self): x =''' ''' x = parseSOAPRPC(x) def testEnvelope3(self): x = ''' hello ''' x, a = parseSOAPRPC(x, attrs = 1) if config.simplify_objects: self.assertEquals(a[id(x['Result'])][(None, 'name')], 'fred') else: self.assertEquals(a[id(x.Result)][(None, 'name')], 'fred') def testParseException(self): x=''' SOAP-ENV:Server Exception thrown on Server System.Runtime.Serialization.SerializationException, mscorlib, Version=1.0.2411.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Soap Parser Error System.Runtime.Serialization.SerializationException: Parse Error, xsd type not valid: Array at System.Runtime.Serialization.Formatters.Soap.SoapHandler.ProcessGetType(String value, String xmlKey) at System.Runtime.Serialization.Formatters.Soap.SoapHandler.ProcessType(ParseRecord pr, ParseRecord objectPr) at System.Runtime.Serialization.Formatters.Soap.SoapHandler.ProcessAttributes(ParseRecord pr, ParseRecord objectPr) at System.Runtime.Serialization.Formatters.Soap.SoapHandler.StartElement(String prefix, String name, String urn) at System.XML.XmlParser.ParseElement() at System.XML.XmlParser.ParseTag() at System.XML.XmlParser.Parse() at System.XML.XmlParser.Parse0() at System.XML.XmlParser.Run() at System.Runtime.Serialization.Formatters.Soap.SoapHandler.Error(IXmlProcessor p, Exception ex) at System.XML.XmlParser.Run() at System.Runtime.Serialization.Formatters.Soap.SoapParser.Run() at System.Runtime.Serialization.Formatters.Soap.ObjectReader.Deserialize(HeaderHandler handler, ISerParser serParser) at System.Runtime.Serialization.Formatters.Soap.SoapFormatter.Deserialize(Stream serializationStream, HeaderHandler handler) at System.Runtime.Remoting.Channels.CoreChannel.DeserializeMessage(String mimeType, Stream xstm, Boolean methodRequest, IMessage msg, Header[] h) at System.Runtime.Remoting.Channels.SoapServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, ITransportHeaders requestHeaders, Stream requestStream, IMessage& msg, ITransportHeaders& responseHeaders, Stream& responseStream) ''' z = parseSOAPRPC(x) self.assertEquals(z.__class__,faultType) self.assertEquals(z.faultstring, "Exception thrown on Server") def testFlatEnvelope(self): x = ''' ''' z = parseSOAPRPC(x) if config.simplify_objects: self.assertEquals(type(z['Result']), type('')) else: self.assertEquals(type(z.Result), type('')) def testNumericArray(self): x = [1,2,3,4,5] y = buildSOAP(x) z = parseSOAPRPC(y) self.assertEquals(x, z) def testStringArray(self): x = ["cayce", "asd", "buy"] y = buildSOAP(x) z = parseSOAPRPC(y) self.assertEquals(x, z) def testStringArray1(self): x = arrayType(['a', 'b', 'c']) y = buildSOAP(x) z = parseSOAP(y) if config.simplify_objects: self.assertEquals(z.v1._elemsname, 'item') self.assertEquals(z.v1, x) else: self.assertEquals(z['v1']['_elemsname'], 'item') self.assertEquals(z['v1'], x) def testStringArray2(self): x = arrayType(['d', 'e', 'f'], elemsname = 'elementals') y = buildSOAP(x) z = parseSOAP(y) if config.simplify_objects: self.assertEquals(z.v1._elemsname, 'elementals') self.assertEquals(z.v1, x) else: self.assertEquals(z['v1']['_elemsname'], 'elementals') self.assertEquals(z['v1'], x) def testInt1(self): my_xml = ''' 41 ''' s = parseSOAPRPC(my_xml) if config.simplify_objects: self.assertEquals(s['statenum'], 41) self.assertEquals(type(s['statenum']), type(0)) else: self.assertEquals(s.statenum, 41) self.assertEquals(type(s.statenum), type(0)) def testInt2(self): my_xml_ns = ''' 41 ''' s = parseSOAPRPC(my_xml_ns) if config.simplify_objects: self.assertEquals(s['statenum'], 41, "NS one failed") self.assertEquals(type(s['statenum']), type(0)) else: self.assertEquals(s.statenum, 41, "NS one failed") self.assertEquals(type(s.statenum), type(0)) def testPriceAndVolume(self): my_xml2 = ''' 5 34.5 10000 ''' s = parseSOAPRPC(my_xml2) if config.simplify_objects: self.assertEquals(s['PriceAndVolume']['LastTradePrice'].strip(), "34.5") self.assertEquals(s['PriceAndVolume']['DayVolume'].strip(), "10000") else: self.assertEquals(s.PriceAndVolume.LastTradePrice.strip(), "34.5") self.assertEquals(s.PriceAndVolume.DayVolume.strip(), "10000") def testInt3(self): my_xml3 = ''' 18 139 ''' s = parseSOAPRPC(my_xml3) if config.simplify_objects: self.assertEquals(s['param']['lowerBound'], 18) self.assertEquals(s['param']['upperBound'], 139) else: self.assertEquals(s.param.lowerBound, 18) self.assertEquals(s.param.upperBound, 139) def testBoolean(self): my_xml4 = ''' 12 Egypt 0 -31 7 ''' s = parseSOAPRPC(my_xml4) if config.simplify_objects: self.assertEquals(s['param'][0], 12) self.assertEquals(s['param'][1], "Egypt") self.assertEquals(s['param'][2], 0) self.assertEquals(s['param'][3], -31) self.assertEquals(s['param1'], None) self.assertEquals(s['param2'], None) self.assertEquals(s['param3'], 7) else: self.assertEquals(s.param[0], 12) self.assertEquals(s.param[1], "Egypt") self.assertEquals(s.param[2], 0) self.assertEquals(s.param[3], -31) self.assertEquals(s.param1, None) self.assertEquals(s.param2, None) self.assertEquals(s.param3, 7) def testFault(self): my_xml5 = ''' SOAP-ENV:Client Cant call getStateName because there are too many parameters. ''' s = parseSOAPRPC(my_xml5) self.assertEquals(s.__class__, faultType) self.assertEquals(s.faultcode, "SOAP-ENV:Client") def testArray2(self): my_xml6 = ''' 5 3 2 monkey cay hello 5 4 3 2 1 moose 5 ''' q = parseSOAPRPC(my_xml6) self.assertEquals(q[0], 5) self.assertEquals(q[1], 3) self.assertEquals(q[2], 2) self.assertEquals(q[3], 'monkey') self.assertEquals(q[4], 'cay') x = q[5] if config.simplify_objects: self.assertEquals(x['monkey'], 5) self.assertEquals(x['cat'], "hello") self.assertEquals(x['ferret'][0], 5) self.assertEquals(x['ferret'][3], 2) self.assertEquals(x['ferret'][5]['cow'], "moose") else: self.assertEquals(x.monkey, 5) self.assertEquals(x.cat, "hello") self.assertEquals(x.ferret[0], 5) self.assertEquals(x.ferret[3], 2) self.assertEquals(x.ferret[5].cow, "moose") def testArray3(self): x = arrayType([5,4,3,21], "spam") y = buildSOAP(x) z = parseSOAPRPC(y) self.assertEquals(x, z) # test struct def testStruct(self): x = structType(name = "eggs") x.test = 5 y = buildSOAP(x) z = parseSOAPRPC(y) if config.simplify_objects: self.assertEquals( x['test'], z['test'] ) else: self.assertEquals( x.test, z.test ) # test faults def testFault1(self): x = faultType("ServerError","Howdy",[5,4,3,2,1]) y = buildSOAP(x) z = parseSOAPRPC(y) self.assertEquals( x.faultcode , z.faultcode) self.assertEquals( x.faultstring , z.faultstring) self.assertEquals( x.detail , z.detail) # Test the recursion def testRecursion(self): o = one() t = two() o.t = t t.o = o tre = three() tre.o = o tre.t = t x = buildSOAP(tre) y = parseSOAPRPC(x) if config.simplify_objects: self.assertEquals( y['t']['o']['t']['o']['t']['o']['t']['str'] , "two") else: self.assertEquals( y.t.o.t.o.t.o.t.str , "two") # Test the recursion with structs def testRecursionWithStructs(self): o = structType("one") t = structType("two") o.t = t o.str = "one" t.o = o t.str = "two" tre = structType("three") tre.o = o tre.t = t tre.str = "three" x = buildSOAP(tre) y = parseSOAPRPC(x) if config.simplify_objects: self.assertEquals( y['t']['o']['t']['o']['t']['o']['t']['str'] , "two") else: self.assertEquals( y.t.o.t.o.t.o.t.str , "two") def testAmp(self): m = "Test Message & " x = structType("test") x.msg = m y = buildSOAP(x) z = parseSOAPRPC(y) if config.simplify_objects: self.assertEquals( m , z['msg']) else: self.assertEquals( m , z.msg) def testInt4(self): my_xml7 = ''' 18 139 ''' x = parseSOAPRPC(my_xml7) y = buildSOAP(x) # Does buildSOAP require a valid encoding? def testBuildSOAPEncoding(self): try: x = buildSOAP('hello', encoding = 'gleck') except LookupError, e: if str (e)[0:16] != 'unknown encoding': raise x = None except: print "Got unexpected exception: %s %s" % tuple (sys.exc_info ()[0:2]) x = '' self.assertEquals( x , None) # Does SOAPProxy require a valid encoding? def testSOAPProxyEncoding(self): try: x = SOAPProxy('', encoding = 'gleck') except LookupError, e: if str (e)[0:16] != 'unknown encoding': raise x = None except: print "Got unexpected exception: %s %s" % tuple (sys.exc_info ()[0:2]) x = '' self.assertEquals( x , None) # Does SOAPServer require a valid encoding? def testSOAPServerEncoding(self): try: x = SOAPServer(('localhost', 0), encoding = 'gleck') except LookupError, e: if str (e)[0:16] != 'unknown encoding': raise x = None except: print "Got unexpected exception: %s %s" % tuple (sys.exc_info ()[0:2]) x = '' self.assertEquals( x , None) def testEncodings(self): encodings = ('US-ASCII', 'ISO-8859-1', 'UTF-8', 'UTF-16') tests = ('A', u'\u0041') for t in tests: for i in range (len (encodings)): x = buildSOAP (t, encoding = encodings[i]) y = parseSOAPRPC (x) self.assertEquals( y , t) tests = (u'\u00a1',) for t in tests: for i in range (len (encodings)): try: x = buildSOAP (t, encoding = encodings[i]) except: if i > 0: raise continue y = parseSOAPRPC (x) self.assertEquals( y , t) tests = (u'\u01a1', u'\u2342') for t in tests: for i in range (len (encodings)): try: x = buildSOAP (t, encoding = encodings[i]) except: if i > 1: raise continue y = parseSOAPRPC (x) self.assertEquals( y , t) def build_xml(self, schema, type, value, attrs = ''): return ''' <_1 xsi:type="xsd:%(type)s"%(attrs)s>%(value)s ''' % {'schema': schema, 'type': type, 'value': value, 'attrs': attrs} # Make sure the various limits are checked when parsing def testIntegerLimits(self): for t, l in SOAPParser.intlimits.items(): try: parseSOAP(xml % (NS.XSD, t, 'hello')) raise AssertionError, "parsed %s of 'hello' without error" % t except AssertionError: raise except: pass if l[1] != None: try: parseSOAP(self.build_xml(NS.XSD, t, l[1] - 1)) raise AssertionError, "parsed %s of %s without error" % \ (t, l[1] - 1) except AssertionError: raise except UnderflowError: pass if l[2] != None: try: parseSOAP(self.build_xml(NS.XSD, t, l[2] + 1)) raise AssertionError, "parsed %s of %s without error" % \ (t, l[2] + 1) except AssertionError: raise except OverflowError: pass # Make sure the various limits are checked when parsing # Next, floats. Note that chances are good this won't work in any non-Unix Pythons. def testFloatLimits(self): for i in \ ( ('float', '-3.402823466391E+38'), ('float', '3.402823466391E+38'), ('float', '3.5e+38'), ('float', '6.9e-46'), ('double', '-1.7976931348623159E+308'), ('double', '1.7976931348623159E+308'), ('double', '1.8e308'), ('double', '2.4e-324'), ): try: parseSOAP(self.build_xml(NS.XSD, i[0], i[1])) # Hide this error for now, cause it is a bug in python 2.0 and 2.1 #if not (sys.version_info[0] == 2 and sys.version_info[1] <= 2) \ # and i[1]=='1.7976931348623159E+308': raise AssertionError, "parsed %s of %s without error" % i except AssertionError: raise except (UnderflowError, OverflowError): pass # Make sure we can't instantiate the base classes def testCannotInstantiateBaseClasses(self): for t in (anyType, NOTATIONType): try: x = t() raise AssertionError, "instantiated %s directly" % repr(t) except: pass # Try everything that requires initial data without any. def testMustBeInitialized(self): for t in (CDATAType, ENTITIESType, ENTITYType, IDType, IDREFType, IDREFSType, NCNameType, NMTOKENType, NMTOKENSType, NOTATIONType, NameType, QNameType, anyURIType, base64Type, base64BinaryType, binaryType, booleanType, byteType, decimalType, doubleType, durationType, floatType, hexBinaryType, intType, integerType, languageType, longType, negative_IntegerType, negativeIntegerType, non_Negative_IntegerType, non_Positive_IntegerType, nonNegativeIntegerType, nonPositiveIntegerType, normalizedStringType, positive_IntegerType, positiveIntegerType, shortType, stringType, timeDurationType, tokenType, unsignedByteType, unsignedIntType, unsignedLongType, unsignedShortType, untypedType, uriType, uriReferenceType): try: t() raise AssertionError, "instantiated a %s with no value" % t.__name__ except AssertionError: raise except: pass def testInstantiations(self): # string, ENTITY, ID, IDREF, language, Name, NCName, # NMTOKEN, QName, untypedType for t in (stringType, ENTITYType, IDType, IDREFType, languageType, NameType, NCNameType, NMTOKENType, QNameType, untypedType): # First some things that shouldn't be taken as the current type test = (10, (), [], {}) for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad type (%s)" % \ (repr(t), repr(type(i))) except AssertionError: raise except: pass # Now some things that should for i in ('hello', u'goodbye'): x = t(i) d = x._marshalData() if d != i: raise AssertionError, "expected %s, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (i, z) # ENTITIES, IDREFS, NMTOKENS for t in (ENTITIESType, IDREFSType, NMTOKENSType): # First some things that shouldn't be taken as the current type test = ({}, lambda x: x, ((),), ([],), [{}], [()]) for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad type (%s)" % \ repr(t), repr(type(i)) except AssertionError: raise except: pass # Now some things that should for i in ('hello', (), [], ('hello', 'goodbye'), ['aloha', 'guten_tag']): x = t(i) d = x._marshalData() if type(i) in (type(()), type([])): j = list(i) else: j = [i] k = ' '.join(j) if d != k: raise AssertionError, "expected %s, got %s" % (k, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != j: raise AssertionError, "expected %s, got %s" % (repr(j), repr(z)) # uri, uriReference, anyURI for t in (uriType, uriReferenceType, anyURIType): # First some things that shouldn't be taken as the current type test = (10, (), [], {}) for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad type (%s)" % \ t.__name__, repr(type(i)) except AssertionError: raise except: pass # Now some things that should for i in ('hello', u'goodbye', '!@#$%^&*()-_=+[{]}\|;:\'",<.>/?`~'): x = t(i) d = x._marshalData() j = urllib.quote(i) if d != j: raise AssertionError, "expected %s, got %s" % (j, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # token First some things that shouldn't be valid because of type test = (42, 3.14, (), [], {}) t = tokenType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad type (%s)" % (t.__name__, repr(i)) except AssertionError: raise except AttributeError: pass # Now some things that shouldn't be valid because of content test = (' hello', 'hello ', 'hel\nlo', 'hel\tlo', 'hel lo', ' \n \t ') for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should be valid for i in ('', 'hello', u'hello'): x = t(i) d = x._marshalData() if d != i: raise AssertionError, "expected %s, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i and i != '': raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) #### CDATA, normalizedString for t in (CDATAType, normalizedStringType): # First some things that shouldn't be valid because of type test = (42, 3.14, (), [], {}) for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad type (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except AttributeError: pass # Now some things that shouldn't be valid because of content test = ('hel\nlo', 'hel\rlo', 'hel\tlo', '\n\r\t') for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should be valid for i in ('', 'hello', u'hello', 'hel lo'): x = t(i) d = x._marshalData() if d != i: raise AssertionError, "expected %s, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i and i != '': raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) #### boolean # First some things that shouldn't be valid test = (10, 'hello', (), [], {}) t = booleanType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % (t.__name__, repr(i)) except AssertionError: raise except: pass # Now some things that should for i in ((0, 'false'), ('false', 'false'), (1, 'true'), ('true', 'true'), (0.0, 'false'), (1.0, 'true')): x = t(i[0]) d = x._marshalData() if d != i[1]: raise AssertionError, "%s: expected %s, got %s" % (i[0], i[1], d) y = buildSOAP(x) z = parseSOAPRPC(y) j = ('false', 'true')[z] if j != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], repr(i[1]), repr(j)) # Now test parsing, both valid and invalid test = (('10', None), ('hello', None), ('false', 0), ('FALSE', 0), (ws + 'false' + ws, 0), (ws + '0' + ws, 0), ('0', 0), ('true', 1), ('TRUE', 1), ('1', 1), (ws + 'true' + ws, 1), (ws + '1' + ws, 1)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != None: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) # Can we give it a name and no type? #print x = t(1, name = 'George', typed = 0) #print "x=",x y = buildSOAP(x) #print "y=",y z = parseSOAP(y) #print "z=",z test = 'true' if z.George != test: raise AssertionError, "expected %s, got %s" % (repr(test), repr(z)) # How about some attributes, set in various and sundry manners? x = t(1, attrs = {'nonamespaceURI': 1}) x._setAttrs({(None, 'NonenamespaceURI'): 2, ('http://some/namespace', 'namespaceURIattr1'): 3}) x._setAttr(('http://some/other/namespace', 'namespaceURIattr2'), 4) self.assertEquals( x._getAttr('nonamespaceURI') , 1) self.assertEquals( x._getAttr('NonenamespaceURI') , 2) self.assertEquals( x._getAttr(('http://some/namespace', 'namespaceURIattr1')) , 3) self.assertEquals( x._getAttr(('http://some/other/namespace', 'namespaceURIattr2')) , 4) self.assertEquals( x._getAttr('non-extant attr') , None) y = buildSOAP(x) z = parseSOAPRPC(y) self.assertEquals( z , 1) #### decimal # First some things that shouldn't be valid test = ('hello', (), [], {}) t = decimalType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad type (%s)" % \ (t.__name__, repr(type(i))) except AssertionError: raise except: pass # Now some things that should for i in (10, 3.14, 23L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %f, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', None), ('1.2.3', None), ('10', 10), ('10.', 10), ('.1', .1), ('.1000000', .1), (ws + '10.4' + ws, 10.4)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != None: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) #### float # First some things that shouldn't be valid test = ('hello', (), [], {}, -3.402823466391E+38, 3.402823466391E+38) t = floatType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (10, 3.14, 23L, -3.4028234663852886E+38, 3.4028234663852886E+38): x = t(i) d = x._marshalData() if not nearlyeq(float(d), i): raise AssertionError, "expected %f, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if not nearlyeq(z, i): raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', None), ('1.2.3', None), ('10', 10), ('10.', 10), ('.1', .1), ('.1000000', .1), (ws + '10.4' + ws, 10.4), ('-3.402823466391E+38', None), ('3.402823466391E+38', None), ('-3.4028234663852886E+38', -3.4028234663852886E+38), ('3.4028234663852886E+38', 3.4028234663852886E+38)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if abs(z - i[1]) > 1e-6: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != None: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) #### double # First some things that shouldn't be valid test = ('hello', (), [], {}, -1.7976931348623159E+308, 1.7976931348623159E+308) t = doubleType for i in test: try: t(i) # Hide this error for now, cause it is a bug in python 2.0 and 2.1 if not (sys.version_info[0] == 2 and sys.version_info[1] <= 2 and i==1.7976931348623159E+308): raise AssertionError, \ "instantiated a double with a bad value (%s)" % repr(i) except AssertionError: raise except ValueError: pass # Now some things that should for i in (10, 3.14, 23L, -1.79769313486E+308, 1.79769313486E+308): x = t(i) d = x._marshalData() if not nearlyeq(float(d), i): raise AssertionError, "expected %s, got %s" % (i, str(x)) y = buildSOAP(x) z = parseSOAPRPC(y) if not nearlyeq(z, i): raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', None), ('1.2.3', None), ('10', 10), ('10.', 10), ('.1', .1), ('.1000000', .1), (ws + '10.4' + ws, 10.4), ('-1.7976931348623159E+308', None), ('1.7976931348623158E+308', None), ('-1.79769313486E+308', -1.79769313486E+308), ('1.79769313486E+308', 1.79769313486E+308)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if abs(z - i[1]) > 1e-6: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != None: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) #### hexBinary x = '' for i in range(256): x += chr(i) test = ('', x, 'hello') t = hexBinaryType l = [] for i in test: l.append(hexBinaryType(i)) x = buildSOAP(l) y = parseSOAPRPC(x) for i in range(len(test)): if test[i] != y[i]: raise AssertionError, "@ %d expected '%s', got '%s'" % \ (i, test[i], y[i]) # Now test parsing, both valid and invalid test = (('hello', None), ('6163 747A65726F', None), ('6163747A65726', None), ('6163747A65726F', 'actzero'), (ws + '6163747A65726F' + ws, 'actzero')) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != None: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) #### base64Binary and base64 s = '' for i in range(256): s += chr(i) for t in (base64BinaryType, base64Type): # First some things that shouldn't be valid test = ((), [], {}, lambda x: x) for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except AttributeError: pass # Now some things that should test = ('', s, u'hello') l = [] for i in test: l.append(t(i)) x = buildSOAP(l) y = parseSOAPRPC(x) for i in range(len(test)): if test[i] != y[i]: raise AssertionError, "@ %d expected '%s', got '%s'" % \ (i, test[i], y[i]) # Now test parsing, both valid and invalid test = (('hello', None), ('YWN0emVybw=', None), ('YWN 0emVybw==', 'actzero'), ('YWN0emVybw==', 'actzero'), (ws + 'YWN0emVybw==' + ws, 'actzero')) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != None: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) #### binary (uses s from above) # First some check invalid encodings try: x = binaryType('hello', encoding = 'yellow') raise AssertionError, "created binary with invalid encoding" except AssertionError: raise except: pass for t in ('hex', 'base64'): # First some things that shouldn't be valid test = ((), [], {}, lambda x: x) for i in test: try: binaryType(i, encoding = t) raise AssertionError, \ "instantiated a %s binary with a bad value (%s)" % \ (e, repr(i)) except AssertionError: raise except AttributeError: pass # Now some things that should test = ('', s, u'hello') l = [] for i in test: l.append(binaryType(i, encoding = t)) x = buildSOAP(l) y = parseSOAPRPC(x) for i in range(len(test)): if test[i] != y[i]: raise AssertionError, "@ %d expected '%s', got '%s'" % \ (i, test[i], y[i]) # Now test parsing, both valid and invalid if t == 'hex': test = (('hello', None), ('6163 747A65726F', None), ('6163747A65726', None), ('6163747A65726F', 'actzero'), (ws + '6163747A65726F' + ws, 'actzero')) else: test = (('hello', None), ('YWN0emVybw=', None), ('YWN 0emVybw==', 'actzero'), ('YWN0emVybw==', 'actzero'), (ws + 'YWN0emVybw==' + ws, 'actzero')) for i in test: try: z = parseSOAPRPC(self.build_xml(NS.XSD, 'binary', i[0], ' encoding="%s"' % t)) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != None: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t, sys.exc_info()[0], sys.exc_info()[1]) # Finally try an Array of binaries (with references!) test = ('', s, u'hello') l = [] for i in test: l.append(binaryType(i, encoding = t)) l.append(l[1]) x = buildSOAP(l) y = parseSOAPRPC(x) for i in range(len(test)): if test[i] != y[i]: raise AssertionError, "@ %d expected '%s', got '%s'" % \ (i, test[i], y[i]) # Make sure the references worked self.assertEquals( id(y[1]) , id(y[3])) def badTest(self, t, data): for i in data: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except: pass def goodTest(self, t, data): for i in data: x = t(i[0]) d = x._marshalData() if d != i[1]: raise AssertionError, "%s(%s): expected %s, got %s" % \ (t.__name__, repr(i[0]), i[1], d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i[2]: raise AssertionError, "%s(%s): expected %s, got %s" % \ (t.__name__, repr(i[0]), repr(i[2]), repr(z)) def parseTest(self, t, data): for i in data: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s(%s): expected %s, got %s" % \ (t.__name__, repr(i[0]), i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def allTests(self, t, baddata, gooddata, parsedata): self.badTest(t, baddata) self.goodTest(t, gooddata) self.parseTest(t, parsedata) # duration and timeDuration def testTimeDuration(self): baddata = \ ( 'hello', ('hello',), (-10, -10), (-10, 0, -10), (10.5, 10.5), (0, 10.5, 0, 10.5, 0), (1, 2, 3, 4, 5, 6, 7), (1, 2, 'hello', 4, 5, 6), (1, 2, 3.5, 4, 5, 6), ) gooddata = \ ( (0, 'PT0S', (N, N, N, N, N, 0.0,)), ((), 'PT0S', (N, N, N, N, N, 0.0,)), ([], 'PT0S', (N, N, N, N, N, 0.0,)), ((0.5,), 'PT0.5S', (N, N, N, N, N, 0.5,)), (10L, 'PT10S', (N, N, N, N, N, 10.0,)), (-10, '-PT10S', (N, N, N, N, N, -10.0,)), (10.5, 'PT10.5S', (N, N, N, N, N, 10.5,)), ((10L, 20), 'PT10M20S', (N, N, N, N, 10, 20.0)), ((-10, 20), '-PT10M20S', (N, N, N, N, -10, 20.0)), ((10, 0), 'PT10M', (N, N, N, N, 10, N)), ((10, 0, 0), 'PT10H', (N, N, N, 10, N, N)), ((10, 0L, 0, 0), 'P10D', (N, N, 10, N, N, N)), ((10, 0, 0, 0, 0), 'P10M', (N, 10, N, N, N, N)), ((10, 0, 0, 0L, 0, 0), 'P10Y', (10, N, N, N, N, N)), ((-10, 0, 0, 0, 0, 0), '-P10Y', (-10, N, N, N, N, N)), ((10, 0, 0, 0, 0, 20L), 'P10YT20S', (10, N, N, N, N, 20.0,)), ((1, 2, 3, 4, 5, 6.75), 'P1Y2M3DT4H5M6.75S', (1, 2, 3, 4, 5, 6.75)), ((-1, 2, 3, 4, 5, 6.75), '-P1Y2M3DT4H5M6.75S', (-1, 2, 3, 4, 5, 6.75)), ((1, 2, 3, 10, 30, 0), 'P1Y2M3DT10H30M', (1, 2, 3, 10, 30, N)), ((1e6, 2e6, 3e6, 4e6, 5e6, 6.7e6), 'P1000000Y2000000M3000000DT4000000H5000000M6700000S', (1e6, 2e6, 3e6, 4e6, 5e6, 6.7e6)), ((1347, 0, N, 0, 0), 'P1347M', (N, 1347, N, N, N, N)), ((-1347, 0, 0, 0, N), '-P1347M', (N, -1347, N, N, N, N)), ((1e15, 0, 0, 0, 0), 'P1000000000000000M', (N, 1000000000000000L, N, N, N, N)), ((-1e15, 0, 0, 0, 0), '-P1000000000000000M', (N, -1000000000000000L, N, N, N, N)), ((1000000000000000L, 0, 0, 0, 0), 'P1000000000000000M', (N, 1000000000000000L, N, N, N, N)), ((-1000000000000000L, 0, 0, 0, 0), '-P1000000000000000M', (N, -1000000000000000L, N, N, N, N)), ) parsedata = ( ('hello', N), ('P T0S', N), ('P10.5Y10.5M', N), ('P1Y2MT', N), ('PT0S', (N, N, N, N, N, 0,)), ('P10Y', (10, N, N, N, N, N)), (ws + 'P10M' + ws, (N, 10, N, N, N, N)), ('P0Y1347M', (0, 1347, N, N, N, N)), ('P0Y1347M0D', (0, 1347, 0, N, N, N)), ('P0MT0M', (N, 0, N, N, 0, N)), ) for t in (durationType, timeDurationType): self.allTests(t, baddata, gooddata, parsedata) # dateTime, timeInstant, and timePeriod def testTimePeriod(self): baddata = \ ( 'hello', ('hello',), (1, 2, 3, 4, 5), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (1, 2, 3, 4, 5, 'hello'), (1, 2.5, 3, 4, 5, 6), (1, 0, 3, 4, 5, 6), (1, 13, 3, 4, 5, 6), (1, 1, 0, 4, 5, 6), (1, 1, 32, 4, 5, 6), (1, 2, 29, 4, 5, 6), (0, 2, 30, 4, 5, 6), (100, 2, 29, 4, 5, 6), (1, 2, 3, -1, 5, 6), (1, 2, 3, 24, 5, 6), (1, 2, 3, 4, -1, 6), (1, 2, 3, 4, 60, 6), (1, 2, 3, 4, 5, -1), (1, 2, 3, 4, 5, 61), (1, 3, 32, 4, 5, 6), (1, 4, 31, 4, 5, 6), (1, 5, 32, 4, 5, 6), (1, 6, 31, 4, 5, 6), (1, 7, 32, 4, 5, 6), (1, 8, 32, 4, 5, 6), (1, 9, 31, 4, 5, 6), (1, 10, 32, 4, 5, 6), (1, 11, 31, 4, 5, 6), (1, 12, 32, 4, 5, 6), ) gooddata = \ ( (1L, '1970-01-01T00:00:01Z', (1970, 1, 1, 0, 0, 1.0)), (1.5, '1970-01-01T00:00:01.5Z', (1970, 1, 1, 0, 0, 1.5)), ((-1, 2, 3, 4, 5, 6), '-0001-02-03T04:05:06Z', (-1, 2, 3, 4, 5, 6.0)), ((1, 2, 3, 4, 5, 6), '0001-02-03T04:05:06Z', (1, 2, 3, 4, 5, 6.0)), ((10, 2, 3, 4, 5, 6), '0010-02-03T04:05:06Z', (10, 2, 3, 4, 5, 6.0)), ((100, 2, 3, 4, 5, 6), '0100-02-03T04:05:06Z', (100, 2, 3, 4, 5, 6.0)), ((1970, 2, 3, 4, 5, 6), '1970-02-03T04:05:06Z', (1970, 2, 3, 4, 5, 6.0)), ((-1970, 2, 3, 4, 5, 6), '-1970-02-03T04:05:06Z', (-1970, 2, 3, 4, 5, 6.0)), ((1970L, 2.0, 3.0, 4L, 5L, 6.875), '1970-02-03T04:05:06.875Z', (1970, 2, 3, 4, 5, 6.875)), ((11990, 1, 2, 3, 4L, 5.25, 0, 0, 0), '11990-01-02T03:04:05.25Z', (11990, 1, 2, 3, 4, 5.25)), ((1e15, 1, 2, 3, 4L, 5.25, 0, 0, 0), '1000000000000000-01-02T03:04:05.25Z', (1e15, 1, 2, 3, 4, 5.25)), ((-1e15, 1, 2, 3, 4L, 5.25, 0, 0, 0), '-1000000000000000-01-02T03:04:05.25Z', (-1e15, 1, 2, 3, 4, 5.25)), ((1000000000000000L, 1, 2, 3, 4L, 5.25, 0, 0, 0), '1000000000000000-01-02T03:04:05.25Z', (1e15, 1, 2, 3, 4, 5.25)), ((-1000000000000000L, 1, 2, 3, 4L, 5.25, 0, 0, 0), '-1000000000000000-01-02T03:04:05.25Z', (-1e15, 1, 2, 3, 4, 5.25)), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('1970 -01 -01T00:00:01Z', N), ('0001-02-03t07:08:23Z', N), # Invalid ranges ('2001-00-03T07:08:23Z', N), ('2001-13-03T07:08:23Z', N), ('2001-02-00T07:08:23Z', N), ('2001-02-29T07:08:23Z', N), ('2000-02-30T07:08:23Z', N), ('1900-02-29T07:08:23Z', N), ('2001-02-03T24:08:23Z', N), ('2001-02-03T04:60:23Z', N), ('2001-02-03T04:05:61Z', N), ('2001-01-32T04:05:06Z', N), ('2001-03-32T04:05:06Z', N), ('2001-04-31T04:05:06Z', N), ('2001-05-32T04:05:06Z', N), ('2001-06-31T04:05:06Z', N), ('2001-07-32T04:05:06Z', N), ('2001-08-32T04:05:06Z', N), ('2001-09-31T04:05:06Z', N), ('2001-10-32T04:05:06Z', N), ('2001-11-31T04:05:06Z', N), ('2001-12-32T04:05:06Z', N), # Whitespace (ws + '1970-01-01T00:00:00Z' + ws, (1970, 1, 1, 0, 0, 0)), # No timezones ('11971-02-03T04:05:06.125', (11971, 2, 3, 4, 5, 6.125)), ('1971-02-03T04:05:06.125', (1971, 2, 3, 4, 5, 6.125)), ('-1971-02-03T04:05:06.125', (-1971, 2, 3, 4, 5, 6.125)), # Non-zulu ('11971-02-03T04:05:06.125-07:08', (11971, 2, 3, 11, 13, 6.125)), ('11971-02-03T04:05:06.125+07:08', (11971, 2, 2, 20, 57, 6.125)), ('-11971-02-03T04:05:06.125-07:08', (-11971, 2, 3, 11, 13, 6.125)), ('-11971-02-03T04:05:06.125+07:08', (-11971, 2, 2, 20, 57, 6.125)), ('1971-02-03T04:05:06.125-07:08', (1971, 2, 3, 11, 13, 6.125)), ('1971-02-03T04:05:06.125+07:08', (1971, 2, 2, 20, 57, 6.125)), ('-1971-02-03T04:05:06.125-07:08', (-1971, 2, 3, 11, 13, 6.125)), ('-1971-02-03T04:05:06.125+07:08', (-1971, 2, 2, 20, 57, 6.125)), # Edgepoints (ranges) ('2001-01-03T07:08:09Z', (2001, 1, 3, 7, 8, 9)), ('2001-12-03T07:08:09Z', (2001, 12, 3, 7, 8, 9)), ('2001-02-01T07:08:09Z', (2001, 2, 1, 7, 8, 9)), ('2001-02-28T07:08:09Z', (2001, 2, 28, 7, 8, 9)), ('2000-02-29T07:08:09Z', (2000, 2, 29, 7, 8, 9)), ('1900-02-28T07:08:09Z', (1900, 2, 28, 7, 8, 9)), ('2001-02-03T00:08:09Z', (2001, 2, 3, 0, 8, 9)), ('2001-02-03T23:08:09Z', (2001, 2, 3, 23, 8, 9)), ('2001-02-03T04:00:09Z', (2001, 2, 3, 4, 0, 9)), ('2001-02-03T04:59:09Z', (2001, 2, 3, 4, 59, 9)), ('2001-02-03T04:05:00Z', (2001, 2, 3, 4, 5, 0)), ('2001-02-03T04:05:60.9Z', (2001, 2, 3, 4, 5, 60.9)), ('2001-01-31T04:05:06Z', (2001, 1, 31, 4, 5, 6)), ('2001-03-31T04:05:06Z', (2001, 3, 31, 4, 5, 6)), ('2001-04-30T04:05:06Z', (2001, 4, 30, 4, 5, 6)), ('2001-05-31T04:05:06Z', (2001, 5, 31, 4, 5, 6)), ('2001-06-30T04:05:06Z', (2001, 6, 30, 4, 5, 6)), ('2001-07-31T04:05:06Z', (2001, 7, 31, 4, 5, 6)), ('2001-08-31T04:05:06Z', (2001, 8, 31, 4, 5, 6)), ('2001-09-30T04:05:06Z', (2001, 9, 30, 4, 5, 6)), ('2001-10-31T04:05:06Z', (2001, 10, 31, 4, 5, 6)), ('2001-11-30T04:05:06Z', (2001, 11, 30, 4, 5, 6)), ('2001-12-31T04:05:06Z', (2001, 12, 31, 4, 5, 6)), # Edgepoints (crossing boundaries) ('0001-01-01T07:08:23+07:08', (1, 1, 1, 0, 0, 23)), ('0001-01-01T07:07:42+07:08', (0, 12, 31, 23, 59, 42)), ('-0004-01-01T07:07:42+07:08', (-5, 12, 31, 23, 59, 42)), ('2001-03-01T07:07:42+07:08', (2001, 2, 28, 23, 59, 42)), ('2000-03-01T07:07:42+07:08', (2000, 2, 29, 23, 59, 42)), ('1900-03-01T07:07:42+07:08', (1900, 2, 28, 23, 59, 42)), ) for t in (dateTimeType, timeInstantType, timePeriodType): self.allTests(t, baddata, gooddata, parsedata) # recurringInstant def testRecurringInstant(self): baddata = \ ( 'hello', ('hello',), (1, 2, N, 3, 4, 5), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (1, 2, 3, 4, 5, 'hello'), (1, 2, 3.5, 4, 5, 6), ) gooddata = \ ( (1L, '1970-01-01T00:00:01Z', (1970, 1, 1, 0, 0, 1.0)), (1.5, '1970-01-01T00:00:01.5Z', (1970, 1, 1, 0, 0, 1.5)), (1e9, '2001-09-09T01:46:40Z', (2001, 9, 9, 1, 46, 40.0)), ((1, 1, 2, 3, 4, 5), '-01-01-02T03:04:05Z', (1, 1, 2, 3, 4, 5)), ((-1, 1, 2, 3, 4, 5), '--01-01-02T03:04:05Z', (-1, 1, 2, 3, 4, 5)), ((10, 1, 2, 3, 4, 5), '-10-01-02T03:04:05Z', (10, 1, 2, 3, 4, 5)), ((-10, 1, 2, 3, 4, 5), '--10-01-02T03:04:05Z', (-10, 1, 2, 3, 4, 5)), ((100, 1, 2, 3, 4, 5), '0100-01-02T03:04:05Z', (100, 1, 2, 3, 4, 5)), ((-100, 1, 2, 3, 4, 5), '-0100-01-02T03:04:05Z', (-100, 1, 2, 3, 4, 5)), ((1970L, 1, 2, 3, 4, 5), '1970-01-02T03:04:05Z', (1970, 1, 2, 3, 4, 5)), ((1970L, 1, 2L, 3, 4.0, 5.25), '1970-01-02T03:04:05.25Z', (1970, 1, 2, 3, 4, 5.25)), ((11990, 1, 2, 3L, 4, 5.25), '11990-01-02T03:04:05.25Z', (11990, 1, 2, 3, 4, 5.25)), ((1e15, 1, 2, 3L, 4, 5.25), '1000000000000000-01-02T03:04:05.25Z', (1e15, 1, 2, 3, 4, 5.25)), ((-1e15, 1, 2, 3L, 4, 5.25), '-1000000000000000-01-02T03:04:05.25Z', (-1e15, 1, 2, 3, 4, 5.25)), ((N, 1, 2, 3, 4L, 5.25), '---01-02T03:04:05.25Z', (N, 1, 2, 3, 4, 5.25)), ((N, N, 2, 3, 4, 5.25, 0, 0, 0), '-----02T03:04:05.25Z', (N, N, 2, 3, 4, 5.25)), ((N, N, -2, 3, 4, 5.25, 0, 0, 0), '------02T03:04:05.25Z', (N, N, -2, 3, 4, 5.25)), ((N, N, N, 3, 4, 5.25), '------T03:04:05.25Z', (N, N, N, 3, 4, 5.25)), ((N, N, N, N, 4, 5.25, 0, 0, 0), '------T-:04:05.25Z', (N, N, N, N, 4, 5.25)), ((N, N, N, N, N, 5.25), '------T-:-:05.25Z', (N, N, N, N, N, 5.25)), ((N, N, N, N, N, -5.25), '-------T-:-:05.25Z', (N, N, N, N, N, -5.25)), ((N, N, N, N, N, N, 0, 0, 0), '------T-:-:-Z', (N, N, N, N, N, N)), ((N, N, N, N, N, N, N), '------T-:-:-Z', (N, N, N, N, N, N)), ((N, N, N, N, N, N, N, N), '------T-:-:-Z', (N, N, N, N, N, N)), ((N, N, N, N, N, N, N, N, N), '------T-:-:-Z', (N, N, N, N, N, N)), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('1970 -01 -01T00:00:01Z', N), ('0001-01-01t07:08:23+07:08', N), # Invalid ranges ('2001-00-03T07:08:23Z', N), ('2001-13-03T07:08:23Z', N), ('2001-02-00T07:08:23Z', N), ('2001-02-29T07:08:23Z', N), ('2000-02-30T07:08:23Z', N), ('1900-02-29T07:08:23Z', N), ('2001-02-03T24:08:23Z', N), ('2001-02-03T04:60:23Z', N), ('2001-02-03T04:05:61Z', N), ('2001-01-32T04:05:06Z', N), ('2001-03-32T04:05:06Z', N), ('2001-04-31T04:05:06Z', N), ('2001-05-32T04:05:06Z', N), ('2001-06-31T04:05:06Z', N), ('2001-07-32T04:05:06Z', N), ('2001-08-32T04:05:06Z', N), ('2001-09-31T04:05:06Z', N), ('2001-10-32T04:05:06Z', N), ('2001-11-31T04:05:06Z', N), ('2001-12-32T04:05:06Z', N), # Whitespace (ws + '1970-01-01T00:00:01Z' + ws, (1970, 1, 1, 0, 0, 1)), # No timezones ('11971-02-03T04:05:06.125', (11971, 2, 3, 4, 5, 6.125)), ('-11971-02-03T04:05:06.125', (-11971, 2, 3, 4, 5, 6.125)), ('1971-02-03T04:05:06.125', (1971, 2, 3, 4, 5, 6.125)), ('-1971-02-03T04:05:06.125', (-1971, 2, 3, 4, 5, 6.125)), ('-71-02-03T04:05:06.125', (71, 2, 3, 4, 5, 6.125)), ('--71-02-03T04:05:06.125', (-71, 2, 3, 4, 5, 6.125)), ('---02-03T04:05:06.125', (N, 2, 3, 4, 5, 6.125)), ('----02-03T04:05:06.125', (N, -2, 3, 4, 5, 6.125)), ('-----03T04:05:06.125', (N, N, 3, 4, 5, 6.125)), ('------03T04:05:06.125', (N, N, -3, 4, 5, 6.125)), ('------T04:05:06.125', (N, N, N, 4, 5, 6.125)), ('-------T04:05:06.125', (N, N, N, -4, 5, 6.125)), ('------T-:05:06.125', (N, N, N, N, 5, 6.125)), ('-------T-:05:06.125', (N, N, N, N, -5, 6.125)), ('------T-:-:06.125', (N, N, N, N, N, 6.125)), ('-------T-:-:06.125', (N, N, N, N, N, -6.125)), ('------T-:-:-', (N, N, N, N, N, N)), ('-------T-:-:-', (N, N, N, N, N, N)), # Non-zulu ('11971-02-03T04:05:06.125-07:08', (11971, 2, 3, 11, 13, 6.125)), ('11971-02-03T04:05:06.125+07:08', (11971, 2, 2, 20, 57, 6.125)), ('-11971-02-03T04:05:06.125-07:08', (-11971, 2, 3, 11, 13, 6.125)), ('-11971-02-03T04:05:06.125+07:08', (-11971, 2, 2, 20, 57, 6.125)), ('1971-02-03T04:05:06.125-07:08', (1971, 2, 3, 11, 13, 6.125)), ('1971-02-03T04:05:06.125+07:08', (1971, 2, 2, 20, 57, 6.125)), ('-1971-02-03T04:05:06.125-07:08', (-1971, 2, 3, 11, 13, 6.125)), ('-1971-02-03T04:05:06.125+07:08', (-1971, 2, 2, 20, 57, 6.125)), ('-71-02-03T04:05:06.125-07:08', (71, 2, 3, 11, 13, 6.125)), ('-71-02-03T04:05:06.125+07:08', (71, 2, 2, 20, 57, 6.125)), ('--71-02-03T04:05:06.125-07:08', (-71, 2, 3, 11, 13, 6.125)), ('--71-02-03T04:05:06.125+07:08', (-71, 2, 2, 20, 57, 6.125)), ('---02-03T04:05:06.125-07:08', (N, 2, 3, 11, 13, 6.125)), ('---02-03T04:05:06.125+07:08', (N, 2, 2, 20, 57, 6.125)), ('----02-03T04:05:06.125-07:08', (N, -2, 3, 11, 13, 6.125)), ('----02-03T04:05:06.125+07:08', (N, -2, 2, 20, 57, 6.125)), ('-----03T04:05:06.125-07:08', (N, N, 3, 11, 13, 6.125)), ('-----03T04:05:06.125+07:08', (N, N, 2, 20, 57, 6.125)), ('------03T04:05:06.125-07:08', (N, N, -3, 11, 13, 6.125)), ('------03T04:05:06.125+07:08', (N, N, -4, 20, 57, 6.125)), ('------T04:05:06.125-07:08', (N, N, N, 11, 13, 6.125)), ('------T04:05:06.125+07:08', (N, N, N, -4, 57, 6.125)), ('-------T04:05:06.125-07:08', (N, N, N, 3, 13, 6.125)), ('-------T04:05:06.125+07:08', (N, N, N, -12, 57, 6.125)), ('------T-:05:06.125-07:08', (N, N, N, N, 433, 6.125)), ('------T-:05:06.125+07:08', (N, N, N, N, -423, 6.125)), ('-------T-:05:06.125-07:08', (N, N, N, N, 423, 6.125)), ('-------T-:05:06.125+07:08', (N, N, N, N, -433, 6.125)), ('------T-:-:06.125-07:08', (N, N, N, N, 428, 6.125)), ('------T-:-:06.125+07:08', (N, N, N, N, -428, 6.125)), ('-------T-:-:06.125-07:08', (N, N, N, N, 427, 53.875)), ('-------T-:-:06.125+07:08', (N, N, N, N, -429, 53.875)), ('------T-:-:--07:08', (N, N, N, N, 428, 0)), ('------T-:-:-+07:08', (N, N, N, N, -428, 0)), ('-------T-:-:--07:08', (N, N, N, N, 428, 0)), ('-------T-:-:-+07:08', (N, N, N, N, -428, 0)), # Edgepoints (ranges) ('2001-01-03T07:08:09Z', (2001, 1, 3, 7, 8, 9)), ('2001-12-03T07:08:09Z', (2001, 12, 3, 7, 8, 9)), ('2001-02-01T07:08:09Z', (2001, 2, 1, 7, 8, 9)), ('2001-02-28T07:08:09Z', (2001, 2, 28, 7, 8, 9)), ('2000-02-29T07:08:09Z', (2000, 2, 29, 7, 8, 9)), ('1900-02-28T07:08:09Z', (1900, 2, 28, 7, 8, 9)), ('2001-02-03T00:08:09Z', (2001, 2, 3, 0, 8, 9)), ('2001-02-03T23:08:09Z', (2001, 2, 3, 23, 8, 9)), ('2001-02-03T04:00:09Z', (2001, 2, 3, 4, 0, 9)), ('2001-02-03T04:59:09Z', (2001, 2, 3, 4, 59, 9)), ('2001-02-03T04:05:00Z', (2001, 2, 3, 4, 5, 0)), ('2001-02-03T04:05:60.9Z', (2001, 2, 3, 4, 5, 60.9)), ('2001-01-31T04:05:06Z', (2001, 1, 31, 4, 5, 6)), ('2001-03-31T04:05:06Z', (2001, 3, 31, 4, 5, 6)), ('2001-04-30T04:05:06Z', (2001, 4, 30, 4, 5, 6)), ('2001-05-31T04:05:06Z', (2001, 5, 31, 4, 5, 6)), ('2001-06-30T04:05:06Z', (2001, 6, 30, 4, 5, 6)), ('2001-07-31T04:05:06Z', (2001, 7, 31, 4, 5, 6)), ('2001-08-31T04:05:06Z', (2001, 8, 31, 4, 5, 6)), ('2001-09-30T04:05:06Z', (2001, 9, 30, 4, 5, 6)), ('2001-10-31T04:05:06Z', (2001, 10, 31, 4, 5, 6)), ('2001-11-30T04:05:06Z', (2001, 11, 30, 4, 5, 6)), ('2001-12-31T04:05:06Z', (2001, 12, 31, 4, 5, 6)), # Edgepoints (crossing boundaries) ('0001-01-01T07:08:23+07:08', (1, 1, 1, 0, 0, 23)), ('0001-01-01T07:07:42+07:08', (0, 12, 31, 23, 59, 42)), ('-0004-01-01T07:07:42+07:08', (-5, 12, 31, 23, 59, 42)), ('2001-03-01T07:07:42+07:08', (2001, 2, 28, 23, 59, 42)), ('2000-03-01T07:07:42+07:08', (2000, 2, 29, 23, 59, 42)), ('1900-03-01T07:07:42+07:08', (1900, 2, 28, 23, 59, 42)), ('---03-01T07:07:42+07:08', (N, 2, 28, 23, 59, 42)), ) for t in (recurringInstantType,): self.allTests(t, baddata, gooddata, parsedata) def testTime(self): baddata = \ ( 'hello', ('hello',), (1, 2, 3, 4, 5), (1, 2, 3, 4, 5, 6, 7, 8), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (1, 2, 'hello'), (1, 2.5, 3), (25, 0, 0), (1, 60, 0), (1, 0, 61), ) gooddata = \ ( (1L, '00:00:01Z', (0, 0, 1.0)), (1.5, '00:00:01.5Z', (0, 0, 1.5)), (3661.5, '01:01:01.5Z', (1, 1, 1.5)), (86399.75, '23:59:59.75Z', (23, 59, 59.75)), ((1,), '01:00:00Z', (1, 0, 0)), ((1, 2), '01:02:00Z', (1, 2, 0)), ((10L, 20.0, 30), '10:20:30Z', (10, 20, 30.0)), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('00 00:01Z', N), ('07:O8:23Z', N), # Invalid ranges ('24:08:23Z', N), ('04:60:23Z', N), ('04:05:61Z', N), # Whitespace (ws + '00:00:01Z' + ws, (0, 0, 1)), # No timezones ('04:05:06.125', (4, 5, 6.125)), # Non-zulu ('04:05:06.125-07:08', (11, 13, 6.125)), ('04:05:06.125+07:08', (-4, 57, 6.125)), # Edgepoints (ranges) ('00:08:09Z', (0, 8, 9)), ('23:08:09Z', (23, 8, 9)), ('04:00:09Z', (4, 0, 9)), ('04:59:09Z', (4, 59, 9)), ('04:05:00Z', (4, 5, 0)), ('04:05:60.9Z', (4, 5, 60.9)), # Edgepoints (crossing boundaries) ('07:08:23+07:08', (0, 0, 23)), ('07:07:42+07:08', (-1, 59, 42)), ) for t in (timeType,): self.allTests(t, baddata, gooddata, parsedata) def testDate(self): baddata = \ ( 'hello', ('hello',), (1, 2, 3, 4, 5), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (1, 2, 3, 4, 5, 'hello'), (1, 2.5, 3, 4, 5, 6), (1, 2, 3.5), (1, 0, 3), (1, 13, 3), (1, 1, 0), (1, 1, 32), (1, 2, 29), (0, 2, 30), (100, 2, 29), (1, 3, 32), (1, 4, 31), (1, 5, 32), (1, 6, 31), (1, 7, 32), (1, 8, 32), (1, 9, 31), (1, 10, 32), (1, 11, 31), (1, 12, 32), ) gooddata = \ ( (1L, '1970-01-01Z', (1970, 1, 1)), (1.5, '1970-01-01Z', (1970, 1, 1)), ((2,), '0002-01-01Z', (2, 1, 1)), ((2, 3), '0002-03-01Z', (2, 3, 1)), ((-2, 3, 4), '-0002-03-04Z', (-2, 3, 4)), ((2, 3, 4), '0002-03-04Z', (2, 3, 4)), ((10, 2, 3), '0010-02-03Z', (10, 2, 3)), ((100, 2, 3), '0100-02-03Z', (100, 2, 3)), ((1970, 2, 3), '1970-02-03Z', (1970, 2, 3)), ((-1970, 2, 3), '-1970-02-03Z', (-1970, 2, 3)), ((1970L, 2.0, 3.0), '1970-02-03Z', (1970, 2, 3)), ((11990, 1L, 2), '11990-01-02Z', (11990, 1, 2)), ((1e15, 1, 2), '1000000000000000-01-02Z', (1e15, 1, 2)), ((-1e15, 1, 2), '-1000000000000000-01-02Z', (-1e15, 1, 2)), ((1000000000000000L, 1, 2), '1000000000000000-01-02Z', (1e15, 1, 2)), ((-1000000000000000L, 1, 2), '-1000000000000000-01-02Z', (-1e15, 1, 2)), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('1970 -01 -01Z', N), ('0001-02-03z', N), # Invalid ranges ('2001-00-03Z', N), ('2001-13-03Z', N), ('2001-02-00Z', N), ('2001-02-29Z', N), ('2000-02-30Z', N), ('1900-02-29Z', N), ('2001-01-32Z', N), ('2001-03-32Z', N), ('2001-04-31Z', N), ('2001-05-32Z', N), ('2001-06-31Z', N), ('2001-07-32Z', N), ('2001-08-32Z', N), ('2001-09-31Z', N), ('2001-10-32Z', N), ('2001-11-31Z', N), ('2001-12-32Z', N), # Whitespace (ws + '1970-01-01Z' + ws, (1970, 1, 1)), # No timezones ('11971-02-03', (11971, 2, 3)), ('1971-02-03', (1971, 2, 3)), ('-1971-02-03', (-1971, 2, 3)), # Non-zulu ('11971-02-03-07:08', (11971, 2, 3)), ('11971-02-03+07:08', (11971, 2, 2)), ('-11971-02-03-07:08', (-11971, 2, 3)), ('-11971-02-03+07:08', (-11971, 2, 2)), ('1971-02-03-07:08', (1971, 2, 3)), ('1971-02-03+07:08', (1971, 2, 2)), ('-1971-02-03-07:08', (-1971, 2, 3)), ('-1971-02-03+07:08', (-1971, 2, 2)), # Edgepoints (ranges) ('2001-01-03Z', (2001, 1, 3)), ('2001-12-03Z', (2001, 12, 3)), ('2001-02-01Z', (2001, 2, 1)), ('2001-02-28Z', (2001, 2, 28)), ('2000-02-29Z', (2000, 2, 29)), ('1900-02-28Z', (1900, 2, 28)), ('2001-01-31Z', (2001, 1, 31)), ('2001-03-31Z', (2001, 3, 31)), ('2001-04-30Z', (2001, 4, 30)), ('2001-05-31Z', (2001, 5, 31)), ('2001-06-30Z', (2001, 6, 30)), ('2001-07-31Z', (2001, 7, 31)), ('2001-08-31Z', (2001, 8, 31)), ('2001-09-30Z', (2001, 9, 30)), ('2001-10-31Z', (2001, 10, 31)), ('2001-11-30Z', (2001, 11, 30)), ('2001-12-31Z', (2001, 12, 31)), # Edgepoints (crossing boundaries) ('0001-01-01+07:08', (0, 12, 31)), ('-0004-01-01+07:08', (-5, 12, 31)), ('2001-03-01+07:08', (2001, 2, 28)), ('2000-03-01+07:08', (2000, 2, 29)), ('1900-03-01+07:08', (1900, 2, 28)), ) for t in (dateType,): self.allTests(t, baddata, gooddata, parsedata) def testGYearMonth(self): baddata = \ ( 'hello', ('hello',), (1, 2, 3), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (1, 2, 3.5), (1, 'hello'), (1, 2.5), (1, 0), (1, 13), ) gooddata = \ ( (1L, '1970-01Z', (1970, 1)), (1.5, '1970-01Z', (1970, 1)), ((2,), '0002-01Z', (2, 1)), ((2, 3), '0002-03Z', (2, 3)), ((-2, 3), '-0002-03Z', (-2, 3)), ((10, 2), '0010-02Z', (10, 2)), ((100, 2), '0100-02Z', (100, 2)), ((1970, 2), '1970-02Z', (1970, 2)), ((-1970, 2), '-1970-02Z', (-1970, 2)), ((1970L, 2.0), '1970-02Z', (1970, 2)), ((11990, 1L), '11990-01Z', (11990, 1)), ((1e15, 1), '1000000000000000-01Z', (1e15, 1)), ((-1e15, 1), '-1000000000000000-01Z', (-1e15, 1)), ((1000000000000000L, 1), '1000000000000000-01Z', (1e15, 1)), ((-1000000000000000L, 1), '-1000000000000000-01Z', (-1e15, 1)), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('1970 -01Z', N), ('0001-02z', N), # Invalid ranges ('2001-00Z', N), ('2001-13Z', N), # Whitespace (ws + '1970-01Z' + ws, (1970, 1)), # No timezones ('11971-02', (11971, 2)), ('1971-02', (1971, 2)), ('-1971-02', (-1971, 2)), # Non-zulu ('11971-02-07:08', (11971, 2)), ('11971-02+07:08', (11971, 1)), ('-11971-02-07:08', (-11971, 2)), ('-11971-02+07:08', (-11971, 1)), ('1971-02-07:08', (1971, 2)), ('1971-02+07:08', (1971, 1)), ('-1971-02-07:08', (-1971, 2)), ('-1971-02+07:08', (-1971, 1)), # Edgepoints (ranges) ('2001-01Z', (2001, 1)), ('2001-12Z', (2001, 12)), # Edgepoints (crossing boundaries) ('0001-01+07:08', (0, 12)), ('-0004-01+07:08', (-5, 12)), ('2001-03+07:08', (2001, 2)), ('2000-03+07:08', (2000, 2)), ('1900-03+07:08', (1900, 2)), ) for t in (gYearMonthType,): self.allTests(t, baddata, gooddata, parsedata) def testGYearAndYear(self): baddata = \ ( 'hello', ('hello',), (1, 2), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (2.5,), ) gooddata = \ ( (1L, '0001Z', 1), (10, '0010Z', 10), (100, '0100Z', 100), (1970, '1970Z', 1970), (-1970, '-1970Z', -1970), (1970L, '1970Z', 1970), (11990.0, '11990Z', 11990), (1e15, '1000000000000000Z', 1e15), (-1e15, '-1000000000000000Z', -1e15), (1000000000000000L, '1000000000000000Z', 1e15), (-1000000000000000L, '-1000000000000000Z', -1e15), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('197OZ', N), ('0001z', N), # Whitespace (ws + '1970Z' + ws, 1970), # No timezones ('11971', 11971), ('1971', 1971), ('-1971', -1971), # Non-zulu ('11971-07:08', 11971), ('11971+07:08', 11970), ('-11971-07:08', -11971), ('-11971+07:08', -11972), ('1971-07:08', 1971), ('1971+07:08', 1970), ('-1971-07:08', -1971), ('-1971+07:08', -1972), # Edgepoints (crossing boundaries) ('0001+07:08', 0), ('-0004+07:08', -5), ) for t in (gYearType, yearType): self.allTests(t, baddata, gooddata, parsedata) def testCentury(self): baddata = \ ( 'hello', ('hello',), (1, 2), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (2.5,), ) gooddata = \ ( (1L, '01Z', 1), (10, '10Z', 10), (100, '100Z', 100), (19, '19Z', 19), (-19, '-19Z', -19), (19L, '19Z', 19), (119.0, '119Z', 119), (1e15, '1000000000000000Z', 1e15), (-1e15, '-1000000000000000Z', -1e15), (1000000000000000L, '1000000000000000Z', 1e15), (-1000000000000000L, '-1000000000000000Z', -1e15), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('197OZ', N), ('0001z', N), # Whitespace (ws + '1970Z' + ws, 1970), # No timezones ('11971', 11971), ('1971', 1971), ('-1971', -1971), # Non-zulu ('11971-07:08', 11971), ('11971+07:08', 11970), ('-11971-07:08', -11971), ('-11971+07:08', -11972), ('1971-07:08', 1971), ('1971+07:08', 1970), ('-1971-07:08', -1971), ('-1971+07:08', -1972), # Edgepoints (crossing boundaries) ('0001+07:08', 0), ('-0004+07:08', -5), ) for t in (centuryType,): self.allTests(t, baddata, gooddata, parsedata) def testGMonthDayAndRecurringDate(self): baddata = \ ( 'hello', ('hello',), (3, 4, 5), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (4, 5, 'hello'), (2.5, 3), (0, 3), (13, 3), (1, 0), (1, 32), (2, 29), (3, 32), (4, 31), (5, 32), (6, 31), (7, 32), (8, 32), (9, 31), (10, 32), (11, 31), (12, 32), ) gooddata = \ ( (1L, '--01-01Z', (1, 1)), (1.5, '--01-01Z', (1, 1)), ((2,), '--02-01Z', (2, 1)), ((2, 3), '--02-03Z', (2, 3)), ((10, 2), '--10-02Z', (10, 2)), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('--01 -01Z', N), ('--02-03z', N), # Invalid ranges ('--00-03Z', N), ('--13-03Z', N), ('--01-32Z', N), ('--02-00Z', N), ('--02-29Z', N), ('--03-32Z', N), ('--04-31Z', N), ('--05-32Z', N), ('--06-31Z', N), ('--07-32Z', N), ('--08-32Z', N), ('--09-31Z', N), ('--10-32Z', N), ('--11-31Z', N), ('--12-32Z', N), # Whitespace (ws + '--01-01Z' + ws, (1, 1)), # No timezones ('--02-03', (2, 3)), # Non-zulu ('--02-03-07:08', (2, 3)), ('--02-03+07:08', (2, 2)), # Edgepoints (ranges) ('--01-03Z', (1, 3)), ('--12-03Z', (12, 3)), ('--01-31Z', (1, 31)), ('--02-01Z', (2, 1)), ('--02-28Z', (2, 28)), ('--03-31Z', (3, 31)), ('--04-30Z', (4, 30)), ('--05-31Z', (5, 31)), ('--06-30Z', (6, 30)), ('--07-31Z', (7, 31)), ('--08-31Z', (8, 31)), ('--09-30Z', (9, 30)), ('--10-31Z', (10, 31)), ('--11-30Z', (11, 30)), ('--12-31Z', (12, 31)), # Edgepoints (crossing boundaries) ('--01-01+07:08', (12, 31)), ('--03-01+07:08', (2, 28)), ) for t in (gMonthDayType, recurringDateType): self.allTests(t, baddata, gooddata, parsedata) def testGMonthAndMonth(self): baddata = \ ( 'hello', ('hello',), (3, 4,), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (2.5,), (0,), (13,), ) gooddata = \ ( (1L, '--01--Z', 1), ((2,), '--02--Z', 2), ((10,), '--10--Z', 10), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('--01 --Z', N), ('--03--z', N), # Invalid ranges ('--00--Z', N), ('--13--Z', N), # Whitespace (ws + '--01--Z' + ws, 1), # No timezones ('--03--', 3), # Non-zulu ('--03---07:08', 3), ('--03--+07:08', 2), # Edgepoints (ranges) ('--01--Z', 1), ('--12--Z', 12), # Edgepoints (crossing boundaries) ('--01--+07:08', 12), ('--12---07:08', 12), ) for t in (gMonthType, monthType): self.allTests(t, baddata, gooddata, parsedata) def testGDayAndRecurringDay(self): baddata = \ ( 'hello', ('hello',), (3, 4,), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10), (2.5,), (0,), (32,), ) gooddata = \ ( (1L, '---01Z', 1), ((2,), '---02Z', 2), ((10,), '---10Z', 10), ) parsedata = \ ( # Some strings that won't match the r.e. ('hello', N), ('---01 Z', N), ('---03z', N), # Invalid ranges ('---00Z', N), ('---32Z', N), # Whitespace (ws + '---01Z' + ws, 1), # No timezones ('---03', 3), # Non-zulu ('---03-07:08', 3), ('---03+07:08', 2), # Edgepoints (ranges) ('---01Z', 1), ('---31Z', 31), # Edgepoints (crossing boundaries) ('---01+07:08', 31), ('---31-07:08', 31), ) for t in (gDayType, recurringDayType): self.allTests(t, baddata, gooddata, parsedata) def testInteger(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}) t = integerType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (10, 23L, 1111111111111111111111111111111111111111111111111111L): x = integerType(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('10 000', N), ('1', 1), ('123456789012345678901234567890', 123456789012345678901234567890L), (ws + '12' + ws, 12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testNonPositiveInteger(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, 1, 23) for t in (nonPositiveIntegerType, non_Positive_IntegerType): for i in test: try: t(i) raise AssertionError, \ "instantiated a t with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (0, -23L, -1111111111111111111111111111111111111111111111111L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('1', N), ('0', 0), ('-1', -1), ('-123456789012345678901234567890', -123456789012345678901234567890L), (ws + '-12' + ws, -12)) for i in test: try: if t == nonPositiveIntegerType: n = t.__name__[:-4] else: n = 'non-positive-integer' z = parseSOAPRPC(self.build_xml(t._validURIs[0], n, i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testNegativeInteger(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, 0, 23) for t in (negativeIntegerType, negative_IntegerType): for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (-1, -23L, -111111111111111111111111111111111111111111111111L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('1', N), ('0', N), ('-1', -1), ('-123456789012345678901234567890', -123456789012345678901234567890L), (ws + '-12' + ws, -12)) for i in test: try: if t == negativeIntegerType: n = t.__name__[:-4] else: n = 'negative-integer' z = parseSOAPRPC(self.build_xml(t._validURIs[0], n, i[0])) if z != i[1]: raise AssertionError, "expected %s, got %s" % (i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testLong(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -9223372036854775809L, 9223372036854775808L) t = longType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (-1, -23L, -9223372036854775808L, 9223372036854775807L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-9223372036854775809', N), ('9223372036854775808', N), ('-1', -1), ('0', 0), ('1', 1), ('-9223372036854775808', -9223372036854775808L), ('9223372036854775807', 9223372036854775807L), (ws + '-12' + ws, -12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testInt(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -2147483649L, 2147483648L) t = intType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (-1, -23L, -2147483648L, 2147483647): x = intType(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-2147483649', N), ('2147483648', N), ('-1', -1), ('0', 0), ('1', 1), ('-2147483648', -2147483648L), ('2147483647', 2147483647), (ws + '-12' + ws, -12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testShort(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -32769, 32768) t = shortType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (-1, -23L, -32768, 32767): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-32769', N), ('32768', N), ('-1', -1), ('0', 0), ('1', 1), ('-32768', -32768), ('32767', 32767), (ws + '-12' + ws, -12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testByte(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -129, 128) t = byteType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (-1, -23L, -128, 127): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-129', N), ('128', N), ('-1', -1), ('0', 0), ('1', 1), ('-128', -128), ('127', 127), (ws + '-12' + ws, -12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testNonNegativeInteger(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -42, -1) for t in (nonNegativeIntegerType, non_Negative_IntegerType): for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (0, 1, 23L, 111111111111111111111111111111111111111111111111L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-1', N), ('0', 0), ('1', 1), ('123456789012345678901234567890', 123456789012345678901234567890L), (ws + '12' + ws, 12)) for i in test: try: if t == nonNegativeIntegerType: n = t.__name__[:-4] else: n = 'non-negative-integer' z = parseSOAPRPC(self.build_xml(t._validURIs[0], n, i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testUnsignedLong(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -42, -1, 18446744073709551616L) t = unsignedLongType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (0, 23L, 18446744073709551615L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-1', N), ('18446744073709551616', N), ('0', 0), ('1', 1), ('18446744073709551615', 18446744073709551615L), (ws + '12' + ws, 12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testUnsignedInt(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -42, -1, 4294967296L) t = unsignedIntType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (0, 23L, 4294967295L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-1', N), ('4294967296', N), ('0', 0), ('1', 1), ('4294967295', 4294967295L), (ws + '12' + ws, 12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testUnsignedShort(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -42, -1, 65536) t = unsignedShortType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (0, 23L, 65535): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-1', N), ('65536', N), ('0', 0), ('1', 1), ('65535', 65535), (ws + '12' + ws, 12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testUnsignedByte(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -42, -1, 256) t = unsignedByteType for i in test: try: t(i) raise AssertionError, \ "instantiated a %s with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (0, 23L, 255): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-1', N), ('256', N), ('0', 0), ('1', 1), ('255', 255), (ws + '12' + ws, 12)) for i in test: try: z = parseSOAPRPC(self.build_xml(t._validURIs[0], t.__name__[:-4], i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testPositiveInteger(self): # First some things that shouldn't be valid test = ('hello', 3.14, (), [], {}, -42, -1, 0) for t in (positiveIntegerType, positive_IntegerType): for i in test: try: t(i) raise AssertionError, \ "instantiated a t with a bad value (%s)" % \ (t.__name__, repr(i)) except AssertionError: raise except ValueError: pass # Now some things that should for i in (1, 23L, 1111111111111111111111111111111111111111111111111111L): x = t(i) d = x._marshalData() if d != str(i): raise AssertionError, "expected %d, got %s" % (i, d) y = buildSOAP(x) z = parseSOAPRPC(y) if z != i: raise AssertionError, "expected %s, got %s" % (repr(i), repr(z)) # Now test parsing, both valid and invalid test = (('hello', N), ('3.14', N), ('-10 000', N), ('-1', N), ('0', N), ('1', 1), ('123456789012345678901234567890', 123456789012345678901234567890L), (ws + '12' + ws, 12)) for i in test: try: if t == positiveIntegerType: n = t.__name__[:-4] else: n = 'positive-integer' z = parseSOAPRPC(self.build_xml(t._validURIs[0], n, i[0])) if z != i[1]: raise AssertionError, "%s: expected %s, got %s" % \ (i[0], i[1], repr(z)) except AssertionError: raise except: if i[1] != N: raise AssertionError, \ "parsing %s as %s threw exception %s:%s" % \ (i[0], t.__name__, sys.exc_info()[0], sys.exc_info()[1]) def testUntyped(self): # Make sure untypedType really isn't typed a = stringType('hello', name = 'a') b = untypedType('earth', name = 'b') x = buildSOAP((a, b)) #print "x=",x self.failUnless(x.find('hello') != -1) self.failUnless(x.find('earth') != -1) # Now some Array tests def testArray(self): env = ''' %s ''' xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[4]" SOAP-ENC:offset="[2]" xsi:type="SOAP-ENC:Array"> <_2 SOAP-ENC:arrayType="xsd:int[2]" xsi:type="SOAP-ENC:Array"> 1 2 <_3 SOAP-ENC:arrayType="xsd:int[2]" xsi:type="SOAP-ENC:Array"> 3 4 ''' x = parseSOAPRPC(xml) self.assertEquals( x , [None, None, [1, 2], [3, 4]]) xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[3,4,2]" SOAP-ENC:offset="[17]" xsi:type="SOAP-ENC:Array"> 1 2 3 4 5 6 7 ''' x = parseSOAPRPC(xml) self.assertEquals( x , [ [[None, None], [None, None], [None, None], [None, None]], [[None, None], [None, None], [None, None], [None, None]], [[None, 1], [2, 3], [4, 5], [6, 7]] ]) xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[3,4,2]" xsi:type="SOAP-ENC:Array"> -17 13 -22 1 17 23 6 ''' x = parseSOAPRPC(xml) self.assertEquals( x , [ [[None, 1L], [None, None], [None, None], [6L, None]], [[None, None], [None, None], [None, 13L], [None, None]], [[None, 17L], [None, None], [None, None], [-22L, 23L]] ]) xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[4]" SOAP-ENC:offset="[3]" xsi:type="SOAP-ENC:Array"> 2 0 1 3 ''' x = parseSOAPRPC(xml) self.assertEquals( x , [0, 1, 2, 3]) xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,3,4]" SOAP-ENC:offset="[23]" xsi:type="SOAP-ENC:Array"> ''' x = parseSOAPRPC(xml) self.assertEquals( x , [ [ [None, None, None, None], [None, None, None, None], [None, None, None, None], ], [ [None, None, None, None], [None, None, None, None], [None, None, None, None], ] ]) xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[4]" SOAP-ENC:offset="[3]" xsi:type="SOAP-ENC:Array"> 2 3 ''' try: x = parseSOAPRPC(xml) raise AssertionError, "full array parsed" except AssertionError: raise except: pass xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,0,4]" xsi:type="SOAP-ENC:Array"> ''' try: x = parseSOAPRPC(xml) raise AssertionError, "array with bad dimension (0) parsed" except AssertionError: raise except: pass xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,3,-4]" xsi:type="SOAP-ENC:Array"> ''' try: x = parseSOAPRPC(xml) raise AssertionError, "array with bad dimension (negative) parsed" except AssertionError: raise except: pass xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,3,4.4]" xsi:type="SOAP-ENC:Array"> ''' try: x = parseSOAPRPC(xml) raise AssertionError, "array with bad dimension (non-integral) parsed" except AssertionError: raise except: pass xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,hello,4]" xsi:type="SOAP-ENC:Array"> ''' try: x = parseSOAPRPC(xml) raise AssertionError, "array with bad dimension (non-numeric) parsed" except AssertionError: raise except: pass xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,3,4]" SOAP-ENC:offset="[-4]" xsi:type="SOAP-ENC:Array"> ''' try: x = parseSOAPRPC(xml) raise AssertionError, "array with too large offset parsed" except AssertionError: raise except: pass xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,3,4]" SOAP-ENC:offset="[24]" xsi:type="SOAP-ENC:Array"> ''' try: x = parseSOAPRPC(xml) raise AssertionError, "array with too large offset parsed" except AssertionError: raise except: pass xml = env % ''' <_1 SOAP-ENC:arrayType="xsd:int[2,3,4]" xsi:type="SOAP-ENC:Array"> 2 3 ''' try: x = parseSOAPRPC(xml) raise AssertionError, "full array parsed" except AssertionError: raise except: pass xml = env % ''' 3 4 ''' x = parseSOAPRPC(xml) self.assertEquals( x , [3, 4]) xml = env % ''' 12345 6.789 Of Mans First Disobedience, and the Fruit Of that Forbidden Tree, whose mortal tast Brought Death into the World, and all our woe, http://www.dartmouth.edu/~milton/reading_room/ ''' x = parseSOAPRPC(xml) self.assertEquals( x , [12345, 6.789, '''Of Mans First Disobedience, and the Fruit Of that Forbidden Tree, whose mortal tast Brought Death into the World, and all our woe,''', 'http://www.dartmouth.edu/~milton/reading_room/']) xml = env % ''' Apple 1.56 Peach 1.48 ''' #x = parseSOAPRPC(xml) #print "x=",x xml = env % ''' r1c1 r1c2 r1c3 r2c1 r2c2 ''' x = parseSOAPRPC(xml) self.assertEquals( x , [['r1c1', 'r1c2', 'r1c3'], ['r2c1', 'r2c2'], ['r2c1', 'r2c2']]) xml = env % ''' r1c1 r1c2 r1c3 r2c1 r2c2 r2c3 ''' x = parseSOAPRPC(xml) self.assertEquals( x , [['r1c1', 'r1c2', 'r1c3'], ['r2c1', 'r2c2', 'r2c3']]) xml = env % ''' The third element The fourth element ''' x = parseSOAPRPC(xml) self.assertEquals( x , [None, None, 'The third element', 'The fourth element', None]) xml = env % ''' Third row, third col Eighth row, third col ''' x = parseSOAPRPC(xml) # Example using key data def testKeyData(self): xml = ''' Success Valid mailto:actzerotestkeyname MIIDPjCCAqegAwIBAgIEOroMvDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVI3nlMkH84ZdPKIyz60sNcVEwJ8kF+B6ZVNimCF+r7BWgLi/Dolce5CpbfMMyexZ+UQEMADrc7331eYS891KXSDQx mailto:actzerotestkeyname wgmV2FY6MBKvtaMmCvCoNi/0hycZkiPKC2PXjRLJKFJ5wjNfF+vWsQQUXxOKUQnu HjJqRkx90jJvnEzW3j9FlZFQcZTfJbE0v6BXhhSre2kZvkgcOERmDMeMs//oEA4u epnedUwrkPzedWU9AL7c/oN7rk65UuPWf7V8c/4E9bc= AQAB 9GKuRC3ISwE9aEatzDKW0WIp+P/ufOvCxy9d5jVglLaRiTTIelHoGKCE6cDG62HYOu/3ebce6M7Z6LX6l1J9pB5PUx+f2DaMYYEGuOtNA7/ei5Ga/mibRBCehQIcN6FF6ESFOwAJBRLajj+orgYSy0u1sTCla0V4nSBrYA2H6lx8mD3qfDJ4hie7nU0YqZxy50F9f9UxXKIVSeutyIIBjWDDKv0kVpKy7OUerOaZXOW6HBohXuV74kXMUZu+MpLIkMHOrhJeo+edfhmeFuw4kCo5it6GkrOKrGs6zo1hSxWp7uuvKAPbvUrumC6sTsTxAUg4KTGq85IUnBTYI40Q9TZtzMcONtrWfIIF23/7NJyOmygBaFa4wFqHxe7j2gSWCQRv2fPwXo/AAJTeKwsUIY8OgmANHHbFVqJEeg27jbCuSaQFxWD7ms240YurTb55HBLk6JSufDl0CUbxoUgjrDB++gUb8oalroWDIb5NcZ94QER+HiTQfB11HcPDHvONnzk/n+iF+Mcri53ZbAButnfp2x87sh6RedeiUUWruYA4eonRq5+aj2I9cIrGLQaLemna1AQ+PyD2SMelBLukfR7GUc7zaSPjPJh2W/aYAJSyjM98g6ABNntdfhuf+6jRYnYFqSXZL1W1JPf92OMOfwfuXTE2K68sNwCRhcbHDLM= ''' x = parseSOAPRPC(xml) def testZeroLengthTypedArray(self): """ Test that zero length typed arrays maintain thier type information when converted to a SOAP message. """ empty_int = typedArrayType(typed="int") empty_int_message = buildSOAP( empty_int ) self.assertNotEquals( re.search("xsd:int\[0\]", empty_int_message), None ) if __name__ == '__main__': print """ NOTE: The 'testArray' test will fail because 'referenced' elements are included in the return object. This is a known shortcoming of the current version of SOAPpy. All other tests should succeed. """ unittest.main() SOAPpy-0.12.22/tests/TCtest.py000077500000000000000000000102671235077700100157260ustar00rootroot00000000000000#!/usr/bin/env python import sys, unittest sys.path.insert(1, "..") from SOAPpy import * Config.debug=1 class ClientTestCase(unittest.TestCase): def testParseRules(self): x = """ My Life and Work Henry Ford 49 5.5 """ def negfloat(x): return float(x) * -1.0 # parse rules pr = {'SomeMethod': {'Result': { 'Book': {'title':'string'}, 'Person': {'age':'int', 'height':negfloat} } } } y = parseSOAPRPC(x, rules=pr) assert y.Result.Person.age == 49 assert y.Result.Person.height == -5.5 x = ''' 12 23 0 -31 ''' # parse rules pr = {'Bounds': {'param': 'arrayType=string[]', } } pr2 = {'Bounds': {'param': 'arrayType=int[4]', } } y = parseSOAPRPC(x, rules=pr) assert y.param[1]=='23' y = parseSOAPRPC(x, rules=pr2) assert y.param[1]==23 x = ''' 12 23 0 -31 ''' pr = {'Bounds': {'param': 'arrayType=ur-type[]' } } y = parseSOAPRPC(x, rules=pr) assert y.param[0]==12 assert y.param[1]=='23' assert y.param[2]==float(0) assert y.param[3]==-31 # Try the reverse, not implemented yet. def testBuildObject(self): class Book(structType): def __init__(self): self.title = "Title of a book" class Person(structType): def __init__(self): self.age = "49" self.height = "5.5" class Library(structType): def __init__(self): self._name = "Result" self.Book = Book() self.Person = Person() obj = Library() x = buildSOAP( kw={'Library':obj} ) print(x) if __name__ == '__main__': unittest.main() SOAPpy-0.12.22/tests/TemperatureService.wsdl000077500000000000000000000030021235077700100206440ustar00rootroot00000000000000 Returns current temperature in a given U.S. zipcode SOAPpy-0.12.22/tests/ZeroLengthArray.py000066400000000000000000000003021235077700100175620ustar00rootroot00000000000000import sys sys.path.insert(1, "..") from SOAPpy import * one = typedArrayType(data=[1],typed=type(1)) tmp = typedArrayType(data=[], typed=type(1)) print buildSOAP( one ) print buildSOAP( tmp ) SOAPpy-0.12.22/tests/alanbushTest.py000077500000000000000000000016771235077700100171620ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. ident = '$Id: alanbushTest.py,v 1.5 2003/05/21 14:52:37 warnes Exp $' import os, re,sys # add local SOAPpy code to search path sys.path.insert(1, "..") from SOAPpy import * Config.debug=0 # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None SoapEndpointURL = 'http://www.alanbushtrust.org.uk/soap/compositions.asp' MethodNamespaceURI = 'urn:alanbushtrust-org-uk:soap.methods' SoapAction = MethodNamespaceURI + ".GetCategories" server = SOAPProxy(SoapEndpointURL, namespace=MethodNamespaceURI, soapaction=SoapAction, http_proxy=proxy ) for category in server.GetCategories(): print category SOAPpy-0.12.22/tests/cardClient.py000077500000000000000000000014371235077700100165670ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. import sys sys.path.insert (1, '..') from SOAPpy import * ident = '$Id: cardClient.py,v 1.4 2004/02/18 21:22:13 warnes Exp $' endpoint = "http://localhost:12027/xmethodsInterop" sa = "urn:soapinterop" ns = "http://soapinterop.org/" serv = SOAPProxy(endpoint, namespace=ns, soapaction=sa) try: hand = serv.dealHand(NumberOfCards = 13, StringSeparator = '\n') except: print "no dealHand"; hand = 0 try: sortedhand = serv.dealArrangedHand(NumberOfCards=13,StringSeparator='\n') except: print "no sorted"; sortedhand = 0 try: card = serv.dealCard() except: print "no card"; card = 0 print "*****hand****\n",hand,"\n*********" print "******sortedhand*****\n",sortedhand,"\n*********" print "card:",card serv.quit() SOAPpy-0.12.22/tests/cardServer.py000077500000000000000000000056671235077700100166300ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. import string import sys sys.path.insert (1, '..') from SOAPpy import * ident = '$Id: cardServer.py,v 1.4 2004/02/18 21:22:13 warnes Exp $' # create the list of all cards, and keep strings for each suit __cs = "Clubs" __ds = "Diamonds" __hs = "Hearts" __ss = "Spades" __cards = [] for suit in [__cs, __ds, __hs, __ss]: for num in range(9): num += 1 __cards.append(str(num+1)+" of "+suit) for face in ["ace","King","Queen","Jack"]: __cards.append(face+" of "+suit) def deal(num): if num not in range(1,53): return -1 else: alreadydealt = [] ignore = 0 handdealt = [] import whrandom while num > 0: idx = int(str(whrandom.random())[2:4]) if idx in range(52) and idx not in alreadydealt: handdealt.append(__cards[idx]) alreadydealt.append(idx) num -= 1 else: ignore += 1 continue return handdealt def arrangeHand(hand): c = [] d = [] h = [] s = [] import string for card in hand: if string.find(card, __cs) != -1: c.append(card) elif string.find(card, __ds) != -1: d.append(card) elif string.find(card, __hs) != -1: h.append(card) elif string.find(card, __ss) != -1: s.append(card) for cards, str in ((c, __cs),(d, __ds),(h,__hs), (s,__ss)): cards.sort() idx = 0 if "10 of "+str in cards: cards.remove("10 of "+str) if "Jack of "+str in cards: idx += 1 if "Queen of "+str in cards: idx += 1 if "King of "+str in cards: idx += 1 if "ace of "+str in cards: idx +=1 cards.insert(len(cards)-idx,"10 of "+str) if "King of "+str in cards: cards.remove("King of "+str) if "ace of "+str in cards: cards.insert(len(cards)-1,"King of "+str) else: cards.append("King of "+str) return c+d+h+s def dealHand (NumberOfCards, StringSeparator): hand = deal(NumberOfCards) return string.join(hand,StringSeparator) def dealArrangedHand (NumberOfCards, StringSeparator): if NumberOfCards < 1 or NumberOfCards > 52: raise ValueError, "NumberOfCards must be between 1 and 52" unarranged = deal(NumberOfCards) hand = arrangeHand(unarranged) return string.join(hand, StringSeparator) def dealCard (): return deal(1)[0] run = 1 def quit(): global run run=0; namespace = 'http://soapinterop.org/' server = SOAPServer (("localhost", 12027)) server.registerKWFunction (dealHand, namespace) server.registerKWFunction (dealArrangedHand, namespace) server.registerKWFunction (dealCard, namespace) server.registerKWFunction (quit, namespace) try: while run: server.handle_request() except KeyboardInterrupt: pass SOAPpy-0.12.22/tests/echoClient.py000077500000000000000000000046601235077700100165750ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. import sys sys.path.insert(1, "..") from SOAPpy import * # Uncomment to see outgoing HTTP headers and SOAP and incoming #Config.debug = 1 #Config.dumpHeadersIn = 1 #Config.dumpSOAPIn = 1 #Config.dumpSOAPOut = 1 # ask for returned SOAP responses to be converted to basic python types Config.simplify_objects = 1 #Config.BuildWithNoType = 1 #Config.BuildWithNoNamespacePrefix = 1 if len(sys.argv) > 1 and sys.argv[1] == '-s': # Use secure http pathserver = SOAPProxy("https://localhost:9900/pathtest") server = SOAPProxy("https://localhost:9900") elif len(sys.argv) > 1 and sys.argv[1] == '-g': # use Globus for communication import pyGlobus pathserver = SOAPProxy("httpg://localhost:9900/pathtest") server = SOAPProxy("httpg://localhost:9900") else: # Default: use standard http pathserver = SOAPProxy("http://localhost:9900/pathtest") server = SOAPProxy("http://localhost:9900") # Echo... try: print server.echo("MOO") except Exception, e: print "Caught exception: ", e try: print pathserver.echo("MOO") except Exception, e: print "Caught exception: ", e # ...in an object try: print server.echo_ino("moo") except Exception, e: print "Caught exception: ", e try: print pathserver.echo_ino("cow") except Exception, e: print "Caught exception: ", e # ...in an object in an object try: print server.prop.echo2("moo") except Exception, e: print "Caught exception: ", e try: print pathserver.prop.echo2("cow") except Exception, e: print "Caught exception: ", e # ...with keyword arguments try: print server.echo_wkw(third = "three", first = "one", second = "two") except Exception, e: print "Caught exception: ", e try: print pathserver.echo_wkw(third = "three", first = "one", second = "two") except Exception, e: print "Caught exception: ", e # ...with a context object try: print server.echo_wc("moo") except Exception, e: print "Caught exception: ", e try: print pathserver.echo_wc("cow") except Exception, e: print "Caught exception: ", e # ...with a header hd = headerType(data = {"mystring": "Hello World"}) try: print server._hd(hd).echo_wc("moo") except Exception, e: print "Caught exception: ", e try: print pathserver._hd(hd).echo_wc("cow") except Exception, e: print "Caught exception: ", e # close down server server.quit() SOAPpy-0.12.22/tests/echoHeader.py000077500000000000000000000007001235077700100165360ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. import sys sys.path.insert(1, "..") from SOAPpy import * # Uncomment to see outgoing HTTP headers and SOAP and incoming #Config.debug = 1 Config.BuildWithNoType = 1 Config.BuildWithNoNamespacePrefix = 1 hd = headerType(data = {"mystring": "Hello World"}) server = SOAPProxy("http://localhost:9900/", header=hd) print server.echo("Hello world") server.quit() SOAPpy-0.12.22/tests/echoServer.py000077500000000000000000000114441235077700100166230ustar00rootroot00000000000000#!/usr/bin/env python # # Copyright (c) 2001 actzero, inc. All rights reserved. import sys sys.path.insert(1, "..") from SOAPpy import * # Uncomment to see outgoing HTTP headers and SOAP and incoming Config.dumpSOAPIn = 1 Config.dumpSOAPOut = 1 Config.debug = 1 # specify name of authorization function Config.authMethod = "_authorize" # Set this to 0 to test authorization allowAll = 1 # ask for returned SOAP responses to be converted to basic python types Config.simplify_objects = 1 # provide a mechanism to stop the server run = 1 def quit(): global run run=0; if Config.SSLserver: from M2Crypto import SSL def _authorize(*args, **kw): global allowAll, Config if Config.debug: print "Authorize (function) called! (result = %d)" % allowAll print "Arguments: %s" % kw if allowAll: return 1 else: return 0 # Simple echo def echo(s): global Config # Test of context retrieval ctx = Server.GetSOAPContext() if Config.debug: print "SOAP Context: ", ctx return s + s # An echo class class echoBuilder2: def echo2(self, val): return val * 3 # A class that has an instance variable which is an echo class class echoBuilder: def __init__(self): self.prop = echoBuilder2() def echo_ino(self, val): return val + val def _authorize(self, *args, **kw): global allowAll, Config if Config.debug: print "Authorize (method) called with arguments:" print "*args=%s" % str(args) print "**kw =%s" % str(kw) print "Approved -> %d" % allowAll if allowAll: return 1 else: return 0 # Echo with context def echo_wc(s, _SOAPContext): global Config c = _SOAPContext sep = '-' * 72 # The Context object has extra info about the call if Config.debug: print "-- XML", sep[7:] # The original XML request print c.xmldata print "-- Header", sep[10:] # The SOAP Header or None if not present print c.header if c.header: print "-- Header.mystring", sep[19:] # An element of the SOAP Header print c.header.mystring print "-- Body", sep[8:] # The whole Body object print c.body print "-- Peer", sep[8:] if not GSI: # The socket object, useful for print c.connection.getpeername() else: # The socket object, useful for print c.connection.get_remote_address() ctx = c.connection.get_security_context() print ctx.inquire()[0].display() print "-- SOAPAction", sep[14:] # The SOAPaction HTTP header print c.soapaction print "-- HTTP headers", sep[16:] # All the HTTP headers print c.httpheaders return s + s # Echo with keyword arguments def echo_wkw(**kw): return kw['first'] + kw['second'] + kw['third'] # Simple echo def echo_simple(*arg): return arg def echo_header(s, _SOAPContext): global Config c = _SOAPContext return s, c.header addr = ('localhost', 9900) GSI = 0 SSL = 0 if len(sys.argv) > 1 and sys.argv[1] == '-s': SSL = 1 if not Config.SSLserver: raise RuntimeError, \ "this Python installation doesn't have OpenSSL and M2Crypto" ssl_context = SSL.Context() ssl_context.load_cert('validate/server.pem') server = SOAPServer(addr, ssl_context = ssl_context) prefix = 'https' elif len(sys.argv) > 1 and sys.argv[1] == '-g': GSI = 1 from SOAPpy.GSIServer import GSISOAPServer server = GSISOAPServer(addr) prefix = 'httpg' else: server = SOAPServer(addr) prefix = 'http' print "Server listening at: %s://%s:%d/" % (prefix, addr[0], addr[1]) # register the method server.registerFunction(echo) server.registerFunction(echo, path = "/pathtest") server.registerFunction(_authorize) server.registerFunction(_authorize, path = "/pathtest") # Register a whole object o = echoBuilder() server.registerObject(o, path = "/pathtest") server.registerObject(o) # Register a function which gets called with the Context object server.registerFunction(MethodSig(echo_wc, keywords = 0, context = 1), path = "/pathtest") server.registerFunction(MethodSig(echo_wc, keywords = 0, context = 1)) # Register a function that takes keywords server.registerKWFunction(echo_wkw, path = "/pathtest") server.registerKWFunction(echo_wkw) server.registerFunction(echo_simple) server.registerFunction(MethodSig(echo_header, keywords=0, context=1)) server.registerFunction(quit) # Start the server try: while run: server.handle_request() except KeyboardInterrupt: pass SOAPpy-0.12.22/tests/esj_test_client.py000066400000000000000000000040371235077700100176710ustar00rootroot00000000000000#!/usr/bin/python2 #standard imports import syslog, sys #domain specific imports sys.path.insert (1, '..') import SOAPpy SOAPpy.Config.simplify_objects=1 ## def test_integer(self,pass_integer): ## def test_string(self,pass_string): ## def test_float(self,pass_float): ## def test_tuple(self,pass_tuple): ## def test_list(self,pass_list): ## def test_dictionary(self,pass_dictionary): if __name__ == "__main__": server = SOAPpy.SOAPProxy("http://localhost:9999") original_integer = 5 result_integer = server.test_integer(original_integer) print "original_integer %s" % original_integer print "result_integer %s" % result_integer assert(result_integer==original_integer) print original_string = "five" result_string = server.test_string(original_string) print "original_string %s" % original_string print "result_string %s" % result_string assert(result_string==original_string) print original_float = 5.0 result_float = server.test_float(original_float) print "original_float %s" % original_float print "result_float %s" % result_float assert(result_float==original_float) print original_tuple = (1,2,"three","four",5) result_tuple = server.test_tuple(original_tuple) print "original_tuple %s" % str(original_tuple) print "result_tuple %s" % str(result_tuple) assert(tuple(result_tuple)==original_tuple) print original_list = [5,4,"three",2,1] result_list = server.test_list(original_list) print "original_list %s" % original_list print "result_list %s" % result_list assert(result_list==original_list) print original_dictionary = { 'one': 1, "two": 2, "three": 3, "four": 4, "five": 5, } result_dictionary = server.test_dictionary(original_dictionary) print "original_dictionary %s" % original_dictionary print "result_dictionary %s" % result_dictionary assert(result_dictionary==original_dictionary) print server.quit() SOAPpy-0.12.22/tests/esj_test_server.py000066400000000000000000000020251235077700100177140ustar00rootroot00000000000000#!/usr/bin/python2 #standard imports import syslog, sys #domain specific imports sys.path.insert (1, '..') import SOAPpy class test_service: run = 1 def test_integer(self,pass_integer): print type(pass_integer) return pass_integer def test_string(self,pass_string): print type(pass_string) return pass_string def test_float(self,pass_float): print type(pass_float) return pass_float def test_tuple(self,pass_tuple): print type(pass_tuple), pass_tuple return pass_tuple def test_list(self,pass_list): print type(pass_list), pass_list return pass_list def test_dictionary(self,pass_dictionary): print type(pass_dictionary), pass_dictionary return pass_dictionary def quit(self): self.run = 0 server = SOAPpy.SOAPServer(("localhost",9999)) SOAPpy.Config.simplify_objects=1 access_object = test_service() server.registerObject(access_object) while access_object.run: server.handle_request() SOAPpy-0.12.22/tests/excelTest.py000077500000000000000000000004501235077700100164510ustar00rootroot00000000000000#!/usr/bin/env python import sys sys.path.insert(1, "..") from SOAPpy import * server = SOAPProxy("http://206.135.217.234:8000/") server.COM_SetProperty("Visible", 1) server.Workbooks.Open("c:\\test.xls") server.COM_NestedCall('ActiveSheet.Range("A2").EntireRow.Delete()') server.quit() SOAPpy-0.12.22/tests/largeDataTest.py000077500000000000000000000021031235077700100172320ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. import sys sys.path.insert(1, "..") from SOAPpy import * from SOAPpy import Parser # Uncomment to see outgoing HTTP headers and SOAP and incoming #Config.debug = 1 if len(sys.argv) > 1 and sys.argv[1] == '-s': server = SOAPProxy("https://localhost:9900") else: server = SOAPProxy("http://localhost:9900") # BIG data: big = repr('.' * (1<<18) ) # ...in an object print "server.echo_ino(big):..", tmp = server.echo_ino(big) print "done" # ...in an object in an object print "server.prop.echo2(big)..", tmp = server.prop.echo2(big) print "done" # ...with keyword arguments print 'server.echo_wkw(third = big, first = "one", second = "two")..', tmp = server.echo_wkw(third = big, first = "one", second = "two") print "done" # ...with a context object print "server.echo_wc(big)..", tmp = server.echo_wc(big) print "done" # ...with a header hd = headerType(data = {"mystring": "Hello World"}) print "server._hd(hd).echo_wc(big)..", tmp = server._hd(hd).echo_wc(big) print "done" server.quit() SOAPpy-0.12.22/tests/newsTest.py000077500000000000000000000026601235077700100163320ustar00rootroot00000000000000#!/usr/bin/env python ident = '$Id: newsTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' import os, re import sys sys.path.insert(1, "..") from SOAPpy import SOAPProxy # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None SoapEndpointURL = 'http://www22.brinkster.com/prasads/BreakingNewsService.asmx?WSDL' MethodNamespaceURI = 'http://tempuri.org/' # Three ways to do namespaces, force it at the server level server = SOAPProxy(SoapEndpointURL, namespace = MethodNamespaceURI, soapaction='http://tempuri.org/GetCNNNews', encoding = None, http_proxy=proxy) print "[server level CNN News call]" print server.GetCNNNews() # Do it inline ala SOAP::LITE, also specify the actually ns (namespace) and # sa (soapaction) server = SOAPProxy(SoapEndpointURL, encoding = None) print "[inline CNNNews call]" print server._ns('ns1', MethodNamespaceURI)._sa('http://tempuri.org/GetCNNNews').GetCNNNews() # Create an instance of your server with specific namespace and then use # inline soapactions for each call dq = server._ns(MethodNamespaceURI) print "[namespaced CNNNews call]" print dq._sa('http://tempuri.org/GetCNNNews').GetCNNNews() print "[namespaced CBSNews call]" print dq._sa('http://tempuri.org/GetCBSNews').GetCBSNews() SOAPpy-0.12.22/tests/quoteTest.py000077500000000000000000000023011235077700100165030ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. ident = '$Id: quoteTest.py,v 1.5 2003/12/18 06:31:50 warnes Exp $' import os, re import sys sys.path.insert(1, "..") from SOAPpy import SOAPProxy # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None # Three ways to do namespaces, force it at the server level server = SOAPProxy("http://services.xmethods.com:9090/soap", namespace = 'urn:xmethods-delayed-quotes', http_proxy=proxy) print "IBM>>", server.getQuote(symbol = 'IBM') # Do it inline ala SOAP::LITE, also specify the actually ns server = SOAPProxy("http://services.xmethods.com:9090/soap", http_proxy=proxy) print "IBM>>", server._ns('ns1', 'urn:xmethods-delayed-quotes').getQuote(symbol = 'IBM') # Create a namespaced version of your server dq = server._ns('urn:xmethods-delayed-quotes') print "IBM>>", dq.getQuote(symbol='IBM') print "ORCL>>", dq.getQuote(symbol='ORCL') print "INTC>>", dq.getQuote(symbol='INTC') SOAPpy-0.12.22/tests/simpleWSDL.py000066400000000000000000000003431235077700100164720ustar00rootroot00000000000000import sys sys.path.insert(1, "..") import SOAPpy url = 'http://www.xmethods.org/sd/2001/TemperatureService.wsdl' zip = '06340' proxy = SOAPpy.WSDL.Proxy(url) temp = proxy.getTemp(zip) print 'Temperature at', zip, 'is', temp SOAPpy-0.12.22/tests/speedTest.py000077500000000000000000000056401235077700100164570ustar00rootroot00000000000000#!/usr/bin/env python ident = '$Id: speedTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' import time import sys sys.path.insert(1, "..") x=''' USA japan ''' x2=''' West Virginia -546 -5.398 New Mexico -641 -9.351 Missouri -819 1.495 ''' # Import in function, because for some reason they slow each other # down in same namespace ??? def SOAPParse(inxml): from SOAPpy import parseSOAPRPC t= time.time() parseSOAPRPC(inxml) return time.time()-t def SAXParse(inxml): import xml.sax y = xml.sax.handler.ContentHandler() t= time.time() xml.sax.parseString(inxml,y) return time.time()-t def DOMParse(inxml): import xml.dom.minidom t= time.time() xml.dom.minidom.parseString(inxml) return time.time()-t # Wierd but the SAX parser runs really slow the first time. # Probably got to load a c module or something SAXParse(x) print print "Simple XML" print "SAX Parse, no marshalling ", SAXParse(x) print "SOAP Parse, and marshalling ", SOAPParse(x) print "DOM Parse, no marshalling ", DOMParse(x) print print "Complex XML (references)" print "SAX Parse, no marshalling ", SAXParse(x2) print "SOAP Parse, and marshalling ", SOAPParse(x2) print "DOM Parse, no marshalling ", DOMParse(x2) SOAPpy-0.12.22/tests/storageTest.py000077500000000000000000000100041235077700100170110ustar00rootroot00000000000000#!/usr/bin/env python ident = '$Id: storageTest.py,v 1.6 2005/02/16 04:24:54 warnes Exp $' import sys, os, time, signal, re sys.path.insert(1, "..") from SOAPpy import SOAPProxy, SOAPConfig, SOAPUserAgent # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) http_proxy = "%s:%s" % (phost, pport) except: http_proxy = None PROXY="http://www.soapware.org/xmlStorageSystem" EMAIL="SOAPpy@actzero.com" NAME="test_user" PASSWORD="mypasswd" SERIAL=1123214 MY_PORT=15600 def resourceChanged (url): print "\n##### NOTIFICATION MESSAGE: Resource %s has changed #####\n" % url return booleanType(1) def printstatus (cmd, stat): print if stat.flError: print "### %s failed: %s ###" % (cmd, stat.message) else: print "### %s successful: %s ###" % (cmd, stat.message) return not stat.flError server = SOAPProxy(encoding="US-ASCII", proxy=PROXY, soapaction="/xmlStorageSystem", http_proxy=http_proxy, # config=SOAPConfig(debug=1) ) # Register as a new user or update user information reg = server.registerUser(email=EMAIL, name=NAME, password=PASSWORD, clientPort=MY_PORT, userAgent=SOAPUserAgent(), serialnumber=SERIAL) printstatus("registerUser", reg) # See what this server can do reg = server.getServerCapabilities (email=EMAIL, password=PASSWORD) if printstatus("getServerCapabilities", reg): print "Legal file extensions: " + str(reg.legalFileExtensions) print "Maximum file size: " + str(reg.maxFileSize) print "Maximum bytes per user: " + str(reg.maxBytesPerUser) print "Number of bytes in use by the indicated user: " + str(reg.ctBytesInUse) print "URL of the folder containing your files: " + str(reg.yourUpstreamFolderUrl) # Store some files reg = server.saveMultipleFiles (email=EMAIL, password=PASSWORD, relativepathList=['index.html','again.html'], fileTextList=['bennett@actzero.com home page' + 'Hello Earth', 'bennett@actzero.com home page' + 'Hello Earth Again']) if printstatus("saveMultipleFiles", reg): print "Files stored:" for file in reg.urlList: print " %s" % file # Save this for call to test pleaseNotify mylist = reg.urlList else: mylist = [] # Check to see what files are stored reg = server.getMyDirectory (email=EMAIL, password=PASSWORD) if printstatus("getMyDirectory", reg): i = 1 while hasattr(reg.directory, "file%05d" % i): d = getattr(reg.directory, "file%05d" % i) print "Relative Path: %s" % d.relativePath print "Size: %d" % d.size print "Created: %s" % d.whenCreated print "Last Uploaded: %s" % d.whenLastUploaded print "URL: %s" % d.url print i += 1 # Set up notification reg = server.pleaseNotify(notifyProcedure="resourceChanged", port=MY_PORT, path="/", protocol="soap", urlList=mylist) printstatus("notifyProcedure", reg) pid = os.fork() if pid == 0: # I am a child process. Set up SOAP server to receive notification print print "## Starting notification server ##" s = SOAPServer(('localhost', MY_PORT)) s.registerFunction(resourceChanged) s.serve_forever() else: def handler(signum, frame): # Kill child process print "Killing child process %d" % pid os.kill(pid, signal.SIGINT) signal.signal(signal.SIGINT, handler) # I am a parent process # Change some files time.sleep(3) reg = server.saveMultipleFiles (email=EMAIL, password=PASSWORD, relativepathList=['index.html'], fileTextList=['bennett@actzero.com home page' + 'Hello Bennett']) if printstatus("saveMultipleFiles", reg): print "Files stored:" for file in reg.urlList: print " %s" % file os.waitpid(pid, 0) SOAPpy-0.12.22/tests/testClient1.py000077500000000000000000000056401235077700100167160ustar00rootroot00000000000000import gc import socket import threading import time import unittest import sys sys.path.insert(1, "..") import SOAPpy #SOAPpy.Config.debug=1 # global to shut down server quit = 0 def echoDateTime(dt): return dt def echo(s): """repeats a string twice""" return s + s def kill(): """tell the server to quit""" global quit quit = 1 def server1(): """start a SOAP server on localhost:8000""" print "Starting SOAP Server...", server = SOAPpy.Server.SOAPServer(addr=('127.0.0.1', 8000)) server.registerFunction(echoDateTime) server.registerFunction(echo) server.registerFunction(kill) print "Done." global quit while not quit: server.handle_request() quit = 0 print "Server shut down." class ClientTestCase(unittest.TestCase): server = None startup_timeout = 5 # seconds def setUp(self): '''This is run once before each unit test.''' serverthread = threading.Thread(target=server1, name="SOAPServer") serverthread.start() start = time.time() connected = False server = None while not connected and time.time() - start < self.startup_timeout: print "Trying to connect to the SOAP server...", try: server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') server.echo('Hello World') except socket.error, e: print "Failure:", e time.sleep(0.5) else: connected = True self.server = server print "Success." if not connected: raise 'Server failed to start.' def tearDown(self): '''This is run once after each unit test.''' print "Trying to shut down SOAP server..." if self.server is not None: self.server.kill() time.sleep(5) return 1 def testEcho(self): '''Test echo function.''' server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') s = 'Hello World' self.assertEquals(server.echo(s), s+s) def testNamedEcho(self): '''Test echo function.''' server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') s = 'Hello World' self.assertEquals(server.echo(s=s), s+s) def testEchoDateTime(self): '''Test passing DateTime objects.''' server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') dt = SOAPpy.Types.dateTimeType(data=time.time()) dt_return = server.echoDateTime(dt) self.assertEquals(dt_return, dt) # def testNoLeak(self): # '''Test for memory leak.''' # gc.set_debug(gc.DEBUG_SAVEALL) # for i in range(400): # server = SOAPpy.Client.SOAPProxy('127.0.0.1:8000') # s = 'Hello World' # server.echo(s) # gc.collect() # self.assertEquals(len(gc.garbage), 0) if __name__ == '__main__': unittest.main() SOAPpy-0.12.22/tests/testWSDL.py000077500000000000000000000114501235077700100161640ustar00rootroot00000000000000#!/usr/bin/env python import unittest import os, re import sys sys.path.insert (1, '..') import SOAPpy ident = '$Id: testWSDL.py,v 1.2 2003/05/09 12:46:11 warnes Exp $' # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) http_proxy = "%s:%s" % (phost, pport) except: http_proxy = None class IntegerArithmenticTestCase(unittest.TestCase): def setUp(self): self.wsdlstr1 = ''' Returns current temperature in a given U.S. zipcode ''' def testParseWsdlString(self): '''Parse XMethods TemperatureService wsdl from a string.''' wsdl = SOAPpy.WSDL.Proxy(self.wsdlstr1, http_proxy=http_proxy) self.assertEquals(len(wsdl.methods), 1) method = wsdl.methods.values()[0] self.assertEquals(method.methodName, 'getTemp') self.assertEquals(method.namespace, 'urn:xmethods-Temperature') self.assertEquals(method.location, 'http://services.xmethods.net:80/soap/servlet/rpcrouter') def testParseWsdlFile(self): '''Parse XMethods TemperatureService wsdl from a file.''' # figure out path to the test directory dir = os.path.abspath('.') fname = './TemperatureService.wsdl' try: f = file(fname) except (IOError, OSError): self.assert_(0, 'Cound not find wsdl file "%s"' % file) wsdl = SOAPpy.WSDL.Proxy(fname, http_proxy=http_proxy) self.assertEquals(len(wsdl.methods), 1) method = wsdl.methods.values()[0] self.assertEquals(method.methodName, 'getTemp') self.assertEquals(method.namespace, 'urn:xmethods-Temperature') self.assertEquals(method.location, 'http://services.xmethods.net:80/soap/servlet/rpcrouter') def testParseWsdlUrl(self): '''Parse XMethods TemperatureService wsdl from a url.''' wsdl = SOAPpy.WSDL.Proxy('http://www.xmethods.net/sd/2001/TemperatureService.wsdl', http_proxy=http_proxy) self.assertEquals(len(wsdl.methods), 1) method = wsdl.methods.values()[0] self.assertEquals(method.methodName, 'getTemp') self.assertEquals(method.namespace, 'urn:xmethods-Temperature') self.assertEquals(method.location, 'http://services.xmethods.net:80/soap/servlet/rpcrouter') def testGetTemp(self): '''Parse TemperatureService and call getTemp.''' zip = '01072' proxy = SOAPpy.WSDL.Proxy(self.wsdlstr1, http_proxy=http_proxy) temp = proxy.getTemp(zip) print 'Temperature at', zip, 'is', temp if __name__ == '__main__': unittest.main() SOAPpy-0.12.22/tests/testleak.py000077500000000000000000000005141235077700100163260ustar00rootroot00000000000000#!/usr/bin/python import sys sys.path.insert(1, "..") import SOAPpy import time import gc import types gc.set_debug(gc.DEBUG_SAVEALL) for i in range(400): try: t = SOAPpy.SOAP.parseSOAPRPC('bad soap payload') except: pass gc.collect() if len(gc.garbage): print 'still leaking' else: print 'no leak' SOAPpy-0.12.22/tests/testsclient.py000066400000000000000000000004051235077700100170470ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- __docformat__ = 'restructuredtext en' #!/usr/bin/env python # coding:utf-8 from SOAPpy import SOAPProxy server = SOAPProxy("http://localhost:8080/") print server.echo("Hello world") # vim:set et sts=4 ts=4 tw=80: SOAPpy-0.12.22/tests/testserver.py000066400000000000000000000005141235077700100167150ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- __docformat__ = 'restructuredtext en' #!/usr/bin/env python # encoding:utf-8 from SOAPpy import SOAPServer def echo(s): return s # repeats a string twice server = SOAPServer(("0.0.0.0", 8080)) server.registerFunction(echo) server.serve_forever() # vim:set et sts=4 ts=4 tw=80: SOAPpy-0.12.22/tests/translateTest.py000077500000000000000000000013431235077700100173500ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. ident = '$Id: translateTest.py,v 1.5 2003/05/21 14:52:37 warnes Exp $' import os, re import sys sys.path.insert(1, "..") from SOAPpy import SOAPProxy # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None server = SOAPProxy("http://services.xmethods.com:80/perl/soaplite.cgi", http_proxy=proxy) babel = server._ns('urn:xmethodsBabelFish#BabelFish') print babel.BabelFish(translationmode = "en_fr", sourcedata = "The quick brown fox did something or other") SOAPpy-0.12.22/tests/vul_etcpasswd.txt000066400000000000000000000012741235077700100175650ustar00rootroot00000000000000POST / HTTP/1.0 Host: localhost:8080 User-agent: SOAPpy 0.12.0 (pywebsvcs.sf.net) Content-type: text/xml; charset="UTF-8" Content-length: 10000000 SOAPAction: "echo" ]> &xxe; aaa SOAPpy-0.12.22/tests/vul_lol.txt000066400000000000000000000024441235077700100163560ustar00rootroot00000000000000POST / HTTP/1.0 Host: localhost:8080 User-agent: SOAPpy 0.12.0 (pywebsvcs.sf.net) Content-type: text/xml; charset="UTF-8" Content-length: 10000000 SOAPAction: "echo" ]> &lol9; SOAPpy-0.12.22/tests/weatherTest.py000077500000000000000000000013231235077700100170100ustar00rootroot00000000000000#!/usr/bin/env python ident = '$Id: weatherTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' import os, re import sys sys.path.insert(1, "..") from SOAPpy import SOAPProxy # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None SoapEndpointURL = 'http://services.xmethods.net:80/soap/servlet/rpcrouter' MethodNamespaceURI = 'urn:xmethods-Temperature' # Do it inline ala SOAP::LITE, also specify the actually ns server = SOAPProxy(SoapEndpointURL, http_proxy=proxy) print "inline", server._ns('ns1', MethodNamespaceURI).getTemp(zipcode='94063') SOAPpy-0.12.22/tests/whoisTest.py000077500000000000000000000012511235077700100165020ustar00rootroot00000000000000#!/usr/bin/env python ident = '$Id: whoisTest.py,v 1.4 2003/05/21 14:52:37 warnes Exp $' import os, re import sys sys.path.insert(1, "..") from SOAPpy import SOAPProxy # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None server = SOAPProxy("http://www.SoapClient.com/xml/SQLDataSoap.WSDL", http_proxy=proxy) print "whois>>", server.ProcessSRL(SRLFile="WHOIS.SRI", RequestName="whois", key = "microsoft.com") SOAPpy-0.12.22/tests/xmethods.py000066400000000000000000000016251235077700100163460ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. ident = '$Id: xmethods.py,v 1.4 2003/12/18 06:31:50 warnes Exp $' import os, re import sys sys.path.insert(1, "..") from SOAPpy import SOAPProxy # Check for a web proxy definition in environment try: proxy_url=os.environ['http_proxy'] phost, pport = re.search('http://([^:]+):([0-9]+)', proxy_url).group(1,2) proxy = "%s:%s" % (phost, pport) except: proxy = None print "##########################################" print " SOAP services registered at xmethods.net" print "##########################################" server = SOAPProxy("http://www.xmethods.net/interfaces/query", namespace = 'urn:xmethods-delayed-quotes', http_proxy=proxy) names = server.getAllServiceNames() for item in names: print 'name:', item['name'] print 'id :', item['id'] print SOAPpy-0.12.22/tools/000077500000000000000000000000001235077700100141335ustar00rootroot00000000000000SOAPpy-0.12.22/tools/.cvsignore000066400000000000000000000000061235077700100161270ustar00rootroot00000000000000*.pyc SOAPpy-0.12.22/tools/interop2html.py000077500000000000000000000061641235077700100171460ustar00rootroot00000000000000#!/usr/bin/env python import string import cgi ident = '$Id: interop2html.py 4 2001-06-27 21:36:11Z cullman $' lines = open('output.txt').readlines() #preserve the tally tally = lines[-6:] #whack the tally from lines lines = lines[:-6] table={} for line in lines: if line[:3] == ' ' or line == '>\n' : continue line = line[:-1] #delete end of line char row = [line[:line.find(': ')], line[line.find(': ')+2:]] #split server name from rest of line restofrow = row[1].split(' ',3) #break out method name, number, status code, status comment if len(restofrow) > 3: if restofrow[3].find('as expected') != -1: restofrow[2] = restofrow[2] + ' (as expected)' elif restofrow[3][:2] == '- ' : restofrow[3] = restofrow[3][2:] try: table[row[0]].append([restofrow[0],restofrow[2:]]) except KeyError: table[row[0]] = [[restofrow[0],restofrow[2:]]] print "" print "" print "
" for x in tally: z = x[:-1].split(":",1) print "" print "
Summary
",z[0],"",z[1],"

" c = 0 totalmethods = len(table[table.keys()[0]]) while c < totalmethods: print "
" print "" cols = [c, c + 1, c + 2] if c != 16: cols += [c + 3] for i in cols: try: header = table[table.keys()[0]][i][0] except: break print "" print "" l = table.keys() l.sort() for key in l: print "" for i in cols: try: status = table[key][i][1][0] except: break if status.find("succeed") != -1: bgcolor = "#339900" status = "Pass" elif status.find("expected") != -1: bgcolor = "#FF9900" hreftitle = table[key][i][1][1].replace("'","") # remove apostrophes from title properties popuphtml = '"' + cgi.escape(cgi.escape(table[key][i][1][1]).replace("'","'").replace('"',""")) + '"' status = "Failed (expected)" else: bgcolor = "#CC0000" hreftitle = table[key][i][1][1].replace("'","") # remove apostrophes from title properties popuphtml = '"' + cgi.escape(cgi.escape(table[key][i][1][1]).replace("'","'").replace('"',""")) + '"' status = "Failed" print "" print "" print "
",header,"
", key , "" , status , "
" c = c + len(cols) print "" SOAPpy-0.12.22/validate/000077500000000000000000000000001235077700100145645ustar00rootroot00000000000000SOAPpy-0.12.22/validate/.cvsignore000066400000000000000000000000061235077700100165600ustar00rootroot00000000000000*.pyc SOAPpy-0.12.22/validate/server.pem000077500000000000000000000065561235077700100166140ustar00rootroot00000000000000$Id: server.pem 4 2001-06-27 21:36:11Z cullman $ # Test certificate generated using CA.pl written by Steve Hensen # bundled with OpenSSL. # # Steps used to generate server.pem : # a)CA.pl -newca (creates a new CA heirarchy) # b)CA.pl -newreq (creates a new certificate request) # c)CA.pl -sign (sign the certificate request) # d)openssl rsa newkey.pem (unencrypt the private key) # e)Copy the certificate from newcert.pem, the unencrypted RSA # private key from newkey.pem and the certificate request from # newreq.pem and create server.pem to contain all three of them. -----BEGIN CERTIFICATE----- MIIDhjCCAu+gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBgDELMAkGA1UEBhMCVVMx CzAJBgNVBAgTAkNBMQswCQYDVQQHEwJSQzEQMA4GA1UEChMHYWN0emVybzETMBEG A1UECxMKdGVjaG5vbG9neTEPMA0GA1UEAxMGc3lzYWRtMR8wHQYJKoZIhvcNAQkB FhBpbmZvQGFjdHplcm8uY29tMB4XDTAxMDUxNjIyMzkwM1oXDTAyMDUxNjIyMzkw M1owgYAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UEBxMCUkMxEDAO BgNVBAoTB2FjdHplcm8xEzARBgNVBAsTCnRlY2hub2xvZ3kxDzANBgNVBAMTBnN5 c2FkbTEfMB0GCSqGSIb3DQEJARYQaW5mb0BhY3R6ZXJvLmNvbTCBnzANBgkqhkiG 9w0BAQEFAAOBjQAwgYkCgYEAyRBB6l+DI3aMNeYf7IuodvZ9nNxnfQHVnGyRtwhb 1g2tugTwFsE67oHA5qvwaDBILtsqkr9agXYDbZwJmV58xtBY675tibf7/1R8mcDO d4Dremdn0CMyk4+n6Z8GpLJ59TZ3y98DXUOqbLvzzltDz0si2XVa8G7f4K5k/xxB GZcCAwEAAaOCAQwwggEIMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5T U0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT/DGQzyXlwLXMWMaT4 lp9O928tvzCBrQYDVR0jBIGlMIGigBSdjwZua1AI3XoUtwLyW0Optc/4O6GBhqSB gzCBgDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMQswCQYDVQQHEwJSQzEQMA4G A1UEChMHYWN0emVybzETMBEGA1UECxMKdGVjaG5vbG9neTEPMA0GA1UEAxMGc3lz YWRtMR8wHQYJKoZIhvcNAQkBFhBpbmZvQGFjdHplcm8uY29tggEAMA0GCSqGSIb3 DQEBBAUAA4GBABQodV+rrwMsvTEEza08EeS1Rf2ISuzh6e9VbfiJLVB5Xv1SeEt1 sOv8ETZyN/4OXvZWQG/5md/5NNkf5K6CeKiwctztkyKTXdPIFS6FJVZdduWhiWPF 6gutQgOogtpCHTLwdSDk75n5MXFlnehORqOREMqqCJtFlHMEV1211Ssi -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDJEEHqX4Mjdow15h/si6h29n2c3Gd9AdWcbJG3CFvWDa26BPAW wTrugcDmq/BoMEgu2yqSv1qBdgNtnAmZXnzG0Fjrvm2Jt/v/VHyZwM53gOt6Z2fQ IzKTj6fpnwaksnn1NnfL3wNdQ6psu/POW0PPSyLZdVrwbt/grmT/HEEZlwIDAQAB AoGALcho6gBjsRCObrt+63MFokkQY0aAviNLy7mhGIdrufsVYvU64kOPsr2S+jOO o3rTBPBc6ltuNWp072GHggfU61y4Bvfqxq2IRRDVH+yjmsdKSPYoBSIs3ZKjwJGx pFAT1nfNP05MfqUwZm8HbTnqqakrWm0p53Zvv6NP3vNjmzECQQD6EK5a7bD7VSVz MawUgUkZGZUtForbZL5nwIo1j94/TbnxUuuwej0MiCJ0MQsPCY/LML/gYaxTdQOg qYkGyIAPAkEAzdXbgTc81FflECxc5CXw9Yi1g0+nMkH5drlk+sct5dCzokPJZBQ3 oxIaQcJP/rUMgG0A2mSpOnbAHNHX+z/F+QJAEQGbafGqTJ1wy5HAOzDDsOJNg+B5 lwwV6uZsP9JF8hYuJBxYjQrzJewIM9C2CNLEpbPuCKt71b0qfv2opP5zvwJAMyjh WveAvgJuo5tzJx2rC0wEWXPVya8OMw0XZSFWbhV2YHFav+4qefSI5ClIurUDO3Rc TuvQCAD19PPPK9qI+QJADpbLUWw8NsMaHpJgeigXVIsRtJcroDw2r87bJxsgcgQz CsIH32VLvFOmpJdwnji6GX+vD2i0UH4ythnMCq4NUg== -----END RSA PRIVATE KEY----- -----BEGIN CERTIFICATE REQUEST----- MIIBwTCCASoCAQAwgYAxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTELMAkGA1UE BxMCUkMxEDAOBgNVBAoTB2FjdHplcm8xEzARBgNVBAsTCnRlY2hub2xvZ3kxDzAN BgNVBAMTBnN5c2FkbTEfMB0GCSqGSIb3DQEJARYQaW5mb0BhY3R6ZXJvLmNvbTCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyRBB6l+DI3aMNeYf7IuodvZ9nNxn fQHVnGyRtwhb1g2tugTwFsE67oHA5qvwaDBILtsqkr9agXYDbZwJmV58xtBY675t ibf7/1R8mcDOd4Dremdn0CMyk4+n6Z8GpLJ59TZ3y98DXUOqbLvzzltDz0si2XVa 8G7f4K5k/xxBGZcCAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4GBAIoUVScm4lAkfo1o n4b2Mpq3oV+dZnnTgYog4vmn/2UF0OSSTWlWPvINVkRtfg0iskZsbcWGn+RDY5e/ aTqN7Xz+BV5XlbQLZzuQdKPsfBcZ766El1chmUuO5tELpFtQkmlAgAXRMuh0Xeb+ A9wmVNyCMU6/+ajqwO642nSPOLM0 -----END CERTIFICATE REQUEST----- SOAPpy-0.12.22/validate/silab.servers000077500000000000000000000245761235077700100173120ustar00rootroot00000000000000# This list of servers was taken from the SOAPBuilders Interoperability Lab # (http://www.xmethods.net/ilab/ilab.html) 4/23/01. # # $Id: silab.servers 4 2001-06-27 21:36:11Z cullman $ Name: SOAP.py 0.9.6 (1999) Endpoint: http://208.177.157.221:9595/xmethodsInterop SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Name: SOAP.py 0.9.6 (2001) Like: SOAP.py 0.9.6 (1999) Style: 2001 Name: Apache 2.1 WSDL: http://www.xmethods.net/sd/interop/ApacheInterop11.wsdl Endpoint: http://nagoya.apache.org:5089/soap/servlet/rpcrouter SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: echoFloatINF server returns 'Infinity' instead of 'INF' Nonfunctional: echoFloatNegINF server returns '-Infinity' instead of '-INF' Nonfunctional: echoStruct WSDL specifies 'inputStruct' parameter, method takes 'echoStruct' parameter Nonfunctional: echoDate not implemented by server Nonfunctional: echoBase64 not implemented by server Name: EasySoap++ WSDL: http://easysoap.sourceforge.net/interop.wsdl Endpoint: http://www.xmethods.net/c/easysoap.cgi SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 Nonfunctional: mustUnderstandEqualsOne server doesn't fail when mustUnderstand=1 Name: eSoapServer Endpoint: http://www.connecttel.com/cgi-bin/esoapserver.cgi SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Name: Frontier 7.0b43 Endpoint: http://www.soapware.org:80/xmethodsInterop SOAPAction: "/xmethodsInterop" Namespace: http://soapinterop.org/ Style: 2001 Name: 4S4C 1.3.3 WSDL: http://soap.4s4c.com/ilab/soap.asp?WSDL Endpoint: http://soap.4s4c.com/ilab/soap.asp SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: echoFloatINF server doesn't understand 'INF' Nonfunctional: echoFloatNaN server doesn't understand 'NaN' Nonfunctional: echoFloatNegINF server doesn't understand '-INF' Name: GLUE WSDL: http://209.61.190.164:8004/glue/http://soapinterop.org/.wsdl Endpoint: http://209.61.190.164:8004/glue/http://soapinterop.org/ SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 Nonfunctional: mustUnderstandEqualsOne server doesn't fail when mustUnderstand=1 Name: HP SOAP Page: http://soap.bluestone.com/interop/ WSDL: http://soap.bluestone.com:80/interop/EchoService/EchoService.wsdl Endpoint: http://soap.bluestone.com:80/scripts/SaISAPI.dll/SaServletEngine.class/hp-soap/soap/rpc/interop/EchoService SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Name: IDOOX WASP 1.0 Page: http://soap.idoox.net:7080/IopResults/jsp/index.jsp WSDL: http://soap.idoox.net:7080/soap/services/ilab.wsdl Endpoint: http://soap.idoox.net:7080/soap/servlet/soap/ilab SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Name: Kafka XSLT Interop Service Page: http://www.vbxml.com/soapworkshop/services/kafka10/services/interop.htm WSDL: http://www.vbxml.com/soapworkshop/services/kafka10/services/endpoint.asp?service=ilab&type=wsdl Endpoint: http://www.vbxml.com/soapworkshop/services/kafka10/services/endpoint.asp?service=ilab SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 Nonfunctional: echoDate not implemented by server Nonfunctional: echoBase64 not implemented by server Nonfunctional: mustUnderstandEqualsOne server doesn't fail when mustUnderstand=1 Name: MS ATL Server WSDL: http://4.34.185.52/ilab/ilab.wsdl Endpoint: http://4.34.185.52/ilab/ilab.dll?Handler=Default SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Style: 2001 Typed: no Name: MS SOAP Toolkit 2.0 (typed) Page: http://www.mssoapinterop.org/stk/ilab.htm WSDL: http://www.mssoapinterop.org/stk/InteropTyped.wsdl Endpoint: http://www.mssoapinterop.org/stk/InteropTyped.wsdl SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: echoBase64 return value doesn't have a type Nonfunctional: echoFloatINF server doesn't understand 'INF' Nonfunctional: echoFloatNaN server doesn't understand 'NaN' Nonfunctional: echoFloatNegINF server doesn't understand '-INF' Name: MS SOAP Toolkit 2.0 (untyped) Like: MS SOAP Toolkit 2.0 (typed) WSDL: http://www.mssoapinterop.org/stk/Interop.wsdl Endpoint: http://www.mssoapinterop.org/stk/Interop.wsdl Typed: no Functional: echoBase64 Name: MS .NET Beta 2 (typed) WSDL: http://www.mssoapinterop.org/test/typed.asmx?WSDL Endpoint: http://www.mssoapinterop.org/test/typed.asmx SOAPAction: "http://soapinterop.org/%(methodname)s" Namespace: http://soapinterop.org/ Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 Nonfunctional: mustUnderstandEqualsOne server doesn't fail when mustUnderstand=1 Nonfunctional: echoDate server doesn't recognize time zone of Z Nonfunctional: echoBase64 not implemented by server Name: MS .NET Beta 2 (untyped) Like: MS .NET Beta 2 (typed) WSDL: http://www.mssoapinterop.org/test/simple.asmx?WSDL Endpoint: http://www.mssoapinterop.org/test/simple.asmx Typed: no Name: MS .NET Remoting (1999 typed) WSDL: http://www.mssoapinterop.org/DotNetRemoting1999Typed/InteropService.WSDL Endpoint: http://www.mssoapinterop.org/DotNetRemoting1999Typed/InteropService.soap SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Name: MS .NET Remoting (1999 untyped) WSDL: http://www.mssoapinterop.org/DotNetRemoting1999/InteropService.WSDL Endpoint: http://www.mssoapinterop.org/DotNetRemoting1999/InteropService.soap SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Typed: no Name: MS .NET Remoting (2001 typed) WSDL: http://www.mssoapinterop.org/DotNetRemoting2001Typed/InteropService.WSDL Endpoint: http://www.mssoapinterop.org/DotNetRemoting2001Typed/InteropService.soap SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Style: 2001 Name: MS .NET Remoting (2001 untyped) WSDL: http://www.mssoapinterop.org/DotNetRemoting2001/InteropService.WSDL Endpoint: http://www.mssoapinterop.org/DotNetRemoting2001/InteropService.soap SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Typed: no Style: 2001 Name: Phalanx WSDL: http://www.phalanxsys.com/interop/interop.wsdl Endpoint: http://www.phalanxsys.com/interop/listener.asp SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Style: 2001 Name: SOAP::Lite WSDL: http://services.soaplite.com/interop.wsdl Endpoint: http://services.soaplite.com/interop.cgi SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Name: SOAPR4 (1999) Endpoint: http://www.jin.gr.jp/~nahi/Ruby/SOAP4R/SOAPBuildersInterop/1999/ SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 Nonfunctional: mustUnderstandEqualsOne server doesn't fail when mustUnderstand=1 Nonfunctional: echoVoid server return nil element instead of no elements Name: SOAPR4 (2001) Like: SOAPR4 (1999) Endpoint: http://www.jin.gr.jp/~nahi/Ruby/SOAP4R/SOAPBuildersInterop/ Style: 2001 Name: SOAPx4 for PHP Endpoint: http://dietrich.ganx4.com/soapx4/soap.php SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: actorShouldPass server returns type with no namespace Nonfunctional: actorShouldFail server doesn't fail when mustUnderstand=1 Nonfunctional: echoDate not implemented by server Nonfunctional: echoBase64 not implemented by server Nonfunctional: echoFloat server returns type with no namespace Nonfunctional: echoFloatArray server returns array elements as strings Nonfunctional: echoFloatINF server returns type with no namespace Nonfunctional: echoFloatNaN server returns type with no namespace Nonfunctional: echoFloatNegINF returns float 0 instead of -INF and type has no namespace Nonfunctional: echoFloatNegZero returns 0 instead of -0 and type has no namespace Nonfunctional: echoInteger server returns type with no namespace Nonfunctional: echoIntegerArray server returns array elements as strings Nonfunctional: echoString server responds with fault when sent '<&>" Nonfunctional: echoStringArray server responds with fault when an array element is '<&>" Nonfunctional: echoVeryLargeFloat server returns type with no namespace Nonfunctional: echoVerySmallFloat server returns type with no namespace Nonfunctional: echoVoid server doesn't return anything Nonfunctional: mustUnderstandEqualsOne server doesn't fail when mustUnderstand=1 Nonfunctional: mustUnderstandEqualsZero server returns type with no namespace Name: SoapRMI Endpoint: http://rainier.extreme.indiana.edu:1568 SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: echoDate not implemented by server Nonfunctional: echoBase64 not implemented by server Name: SQLData SOAP Server WSDL: http://www.SoapClient.com/interop/SQLDataInterop.wsdl Endpoint: http://www.soapclient.com/interop/sqldatainterop.wsdl SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Name: White Mesa SOAP RPC 2.2 (1999) WSDL: http://www.whitemesa.net/wsdl/interop.wsdl Endpoint: http://www.whitemesa.net/interop SOAPAction: "urn:soapinterop" Namespace: http://soapinterop.org/ Nonfunctional: echoFloatINF server doesn't understand 'INF' Nonfunctional: echoFloatNaN server doesn't understand 'NaN' Nonfunctional: echoFloatNegINF server doesn't understand '-INF' Nonfunctional: echoDate not implemented by server Nonfunctional: echoBase64 server returns data containing control character Style: 1999 Typed: no Name: White Mesa SOAP RPC 2.2 (2001) WSDL: http://www.whitemesa.net/wsdl/std/interop.wsdl Endpoint: http://www.whitemesa.net/interop/std SOAPAction: http://soapinterop.org/ Namespace: http://soapinterop.org/ Nonfunctional: echoFloatINF server doesn't understand 'INF' Nonfunctional: echoFloatNaN server doesn't understand 'NaN' Nonfunctional: echoFloatNegINF server doesn't understand '-INF' Nonfunctional: echoDate not implemented by server Nonfunctional: echoBase64 server returns data containing control character Style: 2001 Typed: no Name: Zolera SOAP Infrastructure Endpoint: http://63.142.188.184:7000/ SOAPAction: urn:soapinterop Namespace: http://soapinterop.org/ Style: 2001 Nonfunctional: actorShouldPass server claims message is unparsable Nonfunctional: echoBase64 server returns data with invalid type Nonfunctional: echoVoid server doesn't return an empty return value Nonfunctional: mustUnderstandEqualsZero server claims message is unparsable SOAPpy-0.12.22/validate/silabclient.py000077500000000000000000000546141235077700100174440ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. # This set of clients validates when run against the servers in # silab.servers. import copy import fileinput import getopt import re import string import sys import time import traceback sys.path.insert (1, '..') from SOAPpy import SOAP SOAP.Config.typesNamespace = SOAP.NS.XSD3 SOAP.Config.typesNamespace = SOAP.NS.XSD3 ident = '$Id: silabclient.py 98 2003-03-08 05:10:01Z warnes $' DEFAULT_SERVERS_FILE = 'silab.servers' DEFAULT_METHODS = \ ( 'actorShouldPass', 'actorShouldFail', 'echoDate', 'echoBase64', 'echoFloat', 'echoFloatArray', 'echoFloatINF', 'echoFloatNaN', 'echoFloatNegINF', 'echoFloatNegZero', 'echoInteger', 'echoIntegerArray', 'echoString', 'echoStringArray', 'echoStruct', 'echoStructArray', 'echoVeryLargeFloat', 'echoVerySmallFloat', 'echoVoid', 'mustUnderstandEqualsOne', 'mustUnderstandEqualsZero', ) def usage (error = None): sys.stdout = sys.stderr if error != None: print error print """usage: %s [options] [server ...] If a long option shows an argument is mandatory, it's mandatory for the equivalent short option also. -?, --help display this usage -d, --debug turn on debugging in the SOAP library -e, --exit-on-failure exit on the first (unexpected) failure -h, --harsh turn on harsh testing: - look for the documented error code from mustUnderstand failures - use non-ASCII strings in the string tests -i, --invert test servers *not* in the list of servers given -m, --method=METHOD#[,METHOD#...] call only the given methods, specify a METHOD# of ? for the list of method numbers -n, --no-stats, --no-statistics don't display success and failure statistics -N, --no-boring-stats, --no-boring-statistics only display unexpected failures and unimplemented tests, and only if non-zero -o, --output=TYPE turn on output, TYPE is one or more of s(uccess), f(ailure), n(ot implemented), F(ailed (as expected)), a(ll) [f] -s, --servers=FILE use FILE as list of servers to test [%s] -t, --stacktrace print a stack trace on each unexpected failure -T, --always-stacktrace print a stack trace on any failure """ % (sys.argv[0], DEFAULT_SERVERS_FILE), sys.exit (0) def methodUsage (): sys.stdout = sys.stderr print "Methods are specified by number. Multiple methods can be " \ "specified using a\ncomma-separated list of numbers or ranges. " \ "For example 1,4-6,8 specifies\nmethods 1, 4, 5, 6, and 8.\n" print "The available methods are:\n" half = (len (DEFAULT_METHODS) + 1) / 2 for i in range (half): print "%4d. %-25s" % (i + 1, DEFAULT_METHODS[i]), if i + half < len (DEFAULT_METHODS): print "%4d. %-25s" % (i + 1 + half, DEFAULT_METHODS[i + half]), print sys.exit (0) # as borrowed from jake.soapware.org for float compares. def nearlyeq (a, b, prec = 1e-7): return abs (a - b) <= abs (a) * prec def readServers (file): servers = [] names = {} cur = None f = fileinput.input(file) for line in f: if line[0] == '#': continue if line == '' or line[0] == '\n': cur = None continue if cur == None: cur = {'nonfunctional': {}, '_line': f.filelineno(), '_file': f.filename()} tag = None servers.append (cur) if line[0] in string.whitespace: if tag == 'nonfunctional': value = method + ' ' + cur[tag][method] else: value = cur[tag] value += ' ' + line.strip () elif line[0] == '_': raise ValueError, \ "%s, line %d: can't have a tag starting with `_'" % \ (f.filename(), f.filelineno()) else: tag, value = line.split (':', 1) tag = tag.strip ().lower () value = value.strip () if value[0] == '"' and value[-1] == '"': value = value[1:-1] if tag == 'typed': if value.lower() in ('0', 'no', 'false'): value = 0 elif value.lower() in ('1', 'yes', 'false'): value = 1 else: raise ValueError, \ "%s, line %d: unknown typed value `%s'" % \ (f.filename(), f.filelineno(), value) elif tag == 'name': if names.has_key(value): old = names[value] raise ValueError, \ "%s, line %d: already saw a server named `%s' " \ "(on line %d of %s)" % \ (f.filename(), f.filelineno(), value, old['_line'], old['_file']) names[value] = cur if tag == 'nonfunctional': value = value.split (' ', 1) + [''] method = value[0] cur[tag][method] = value[1] elif tag == 'functional': try: del cur['nonfunctional'][value] except: raise ValueError, \ "%s, line %d: `%s' not marked nonfunctional" % \ (f.filename(), f.filelineno(), value) elif tag == 'like': try: new = copy.deepcopy(names[value]) except: raise ValueError, \ "%s, line %d: don't know about a server named `%s'" % \ (f.filename(), f.filelineno(), value) # This is so we don't lose the nonfunctional methods in new or # in cur new['nonfunctional'].update(cur['nonfunctional']) del cur['nonfunctional'] new.update(cur) # This is because servers and possibly names has a reference to # cur, so we have to keep working with cur so changes are # reflected in servers and names. cur.update(new) else: cur[tag] = value return servers def str2list (s): l = {} for i in s.split (','): if i.find ('-') != -1: i = i.split ('-') for i in range (int (i[0]),int (i[1]) + 1): l[i] = 1 else: l[int (i)] = 1 l = l.keys () l.sort () return l def testActorShouldPass (server, action, harsh): test = 42 server = server._sa (action % {'methodname': 'echoInteger'}) hd = SOAP.headerType () hd.InteropTestHeader = SOAP.stringType ("This shouldn't fault because " "the mustUnderstand attribute is 0") hd.InteropTestHeader._setMustUnderstand (0) hd.InteropTestHeader._setActor ( 'http://schemas.xmlsoap.org/soap/actor/next') server = server._hd (hd) result = server.echoInteger (inputInteger = test) if not SOAP.Config.typed: result = int (result) if result != test: raise Exception, "expected %s, got %s" % (test, result) def testActorShouldFail (server, action, harsh): test = 42 server = server._sa (action % {'methodname': 'echoInteger'}) hd = SOAP.headerType () hd.InteropTestHeader = SOAP.stringType ("This should fault because " "the mustUnderstand attribute is 1") hd.InteropTestHeader._setMustUnderstand (1) hd.InteropTestHeader._setActor ( 'http://schemas.xmlsoap.org/soap/actor/next') server = server._hd (hd) try: result = server.echoInteger (inputInteger = test) except SOAP.faultType, e: if harsh and e.faultcode != 'SOAP-ENV:MustUnderstand': raise AttributeError, "unexpected faultcode %s" % e.faultcode return raise Exception, "should fail, succeeded with %s" % result def testEchoFloat (server, action, harsh): server = server._sa (action % {'methodname': 'echoFloat'}) for test in (0.0, 1.0, -1.0, 3853.33333333): result = server.echoFloat (inputFloat = test) if not SOAP.Config.typed: result = float (result) if not nearlyeq (result, test): raise Exception, "expected %.8f, got %.8f" % (test, result) def testEchoFloatArray (server, action, harsh): test = [0.0, 1.0, -1.0, 3853.33333333] server = server._sa (action % {'methodname': 'echoFloatArray'}) result = server.echoFloatArray (inputFloatArray = test) for i in range (len (test)): if not SOAP.Config.typed: result[i] = float (result[i]) if not nearlyeq (result[i], test[i]): raise Exception, "@ %d expected %s, got %s" % \ (i, repr (test), repr (result)) def testEchoFloatINF (server, action, harsh): try: test = float ('INF') except: test = float (1e300**2) server = server._sa (action % {'methodname': 'echoFloat'}) result = server.echoFloat (inputFloat = test) if not SOAP.Config.typed: result = float (result) if result != test: raise Exception, "expected %.8f, got %.8f" % (test, result) def testEchoFloatNaN (server, action, harsh): try: test = float ('NaN') except: test = float (0.0) server = server._sa (action % {'methodname': 'echoFloat'}) result = server.echoFloat (inputFloat = test) if not SOAP.Config.typed: result = float (result) if result != test: raise Exception, "expected %.8f, got %.8f" % (test, result) def testEchoFloatNegINF (server, action, harsh): try: test = float ('-INF') except: test = float (-1e300**2) server = server._sa (action % {'methodname': 'echoFloat'}) result = server.echoFloat (inputFloat = test) if not SOAP.Config.typed: result = float (result) if result != test: raise Exception, "expected %.8f, got %.8f" % (test, result) def testEchoFloatNegZero (server, action, harsh): test = float ('-0.0') server = server._sa (action % {'methodname': 'echoFloat'}) result = server.echoFloat (inputFloat = test) if not SOAP.Config.typed: result = float (result) if result != test: raise Exception, "expected %.8f, got %.8f" % (test, result) def testEchoInteger (server, action, harsh): server = server._sa (action % {'methodname': 'echoInteger'}) for test in (0, 1, -1, 3853): result = server.echoInteger (inputInteger = test) if not SOAP.Config.typed: result = int (result) if result != test: raise Exception, "expected %.8f, got %.8f" % (test, result) def testEchoIntegerArray (server, action, harsh): test = [0, 1, -1, 3853] server = server._sa (action % {'methodname': 'echoIntegerArray'}) result = server.echoIntegerArray (inputIntegerArray = test) for i in range (len (test)): if not SOAP.Config.typed: result[i] = int (result[i]) if result[i] != test[i]: raise Exception, "@ %d expected %s, got %s" % \ (i, repr (test), repr (result)) relaxedStringTests = ['', 'Hello', '\'<&>"',] relaxedStringTests = ['Hello', '\'<&>"',] harshStringTests = ['', 'Hello', '\'<&>"', u'\u0041', u'\u00a2', u'\u0141', u'\u2342', u'\'<\u0041&>"', u'\'<\u00a2&>"', u'\'<\u0141&>"', u'\'<\u2342&>"',] def testEchoString (server, action, harsh): if harsh: test = harshStringTests else: test = relaxedStringTests server = server._sa (action % {'methodname': 'echoString'}) for test in test: result = server.echoString (inputString = test) if result != test: raise Exception, "expected %s, got %s" % \ (repr (test), repr (result)) def testEchoStringArray (server, action, harsh): if harsh: test = harshStringTests else: test = relaxedStringTests server = server._sa (action % {'methodname': 'echoStringArray'}) result = server.echoStringArray (inputStringArray = test) if result != test: raise Exception, "expected %s, got %s" % (repr (test), repr (result)) def testEchoStruct (server, action, harsh): test = {'varFloat': 2.256, 'varInt': 474, 'varString': 'Utah'} server = server._sa (action % {'methodname': 'echoStruct'}) result = server.echoStruct (inputStruct = test) if not SOAP.Config.typed: result.varFloat = float (result.varFloat) result.varInt = int (result.varInt) if not nearlyeq (test['varFloat'], result.varFloat): raise Exception, ".varFloat expected %s, got %s" % \ (i, repr (test['varFloat']), repr (result.varFloat)) for i in test.keys (): if i == 'varFloat': continue if test[i] != getattr (result, i): raise Exception, ".%s expected %s, got %s" % \ (i, repr (test[i]), repr (getattr (result, i))) def testEchoStructArray (server, action, harsh): test = [{'varFloat': -5.398, 'varInt': -546, 'varString': 'West Virginia'}, {'varFloat': -9.351, 'varInt': -641, 'varString': 'New Mexico'}, {'varFloat': 1.495, 'varInt': -819, 'varString': 'Missouri'}] server = server._sa (action % {'methodname': 'echoStructArray'}) result = server.echoStructArray (inputStructArray = test) for s in range (len (test)): if not SOAP.Config.typed: result[s].varFloat = float (result[s].varFloat) result[s].varInt = int (result[s].varInt) if not nearlyeq (test[s]['varFloat'], result[s].varFloat): raise Exception, \ "@ %d.varFloat expected %s, got %s" % \ (s, repr (test[s]['varFloat']), repr (result[s].varFloat)) for i in test[s].keys (): if i == 'varFloat': continue if test[s][i] != getattr (result[s], i): raise Exception, "@ %d.%s expected %s, got %s" % \ (s, i, repr (test[s][i]), repr (getattr (result[s], i))) def testEchoVeryLargeFloat (server, action, harsh): test = 2.2535e29 server = server._sa (action % {'methodname': 'echoFloat'}) result = server.echoFloat (inputFloat = test) if not SOAP.Config.typed: result = float (result) if not nearlyeq (result, test): raise Exception, "expected %s, got %s" % (repr (test), repr (result)) def testEchoVerySmallFloat (server, action, harsh): test = 2.2535e29 server = server._sa (action % {'methodname': 'echoFloat'}) result = server.echoFloat (inputFloat = test) if not SOAP.Config.typed: result = float (result) if not nearlyeq (result, test): raise Exception, "expected %s, got %s" % (repr (test), repr (result)) def testEchoVoid (server, action, harsh): server = server._sa (action % {'methodname': 'echoVoid'}) result = server.echoVoid () for k in result.__dict__.keys (): if k[0] != '_': raise Exception, "expected an empty structType, got %s" % \ repr (result.__dict__) def testMustUnderstandEqualsOne (server, action, harsh): test = 42 server = server._sa (action % {'methodname': 'echoInteger'}) hd = SOAP.headerType () hd.MustUnderstandThis = SOAP.stringType ("This should fault because " "the mustUnderstand attribute is 1") hd.MustUnderstandThis._setMustUnderstand (1) server = server._hd (hd) try: result = server.echoInteger (inputInteger = test) except SOAP.faultType, e: if harsh and e.faultcode != 'SOAP-ENV:MustUnderstand': raise AttributeError, "unexpected faultcode %s" % e.faultcode return raise Exception, "should fail, succeeded with %s" % result def testMustUnderstandEqualsZero (server, action, harsh): test = 42 server = server._sa (action % {'methodname': 'echoInteger'}) hd = SOAP.headerType () hd.MustUnderstandThis = SOAP.stringType ("This shouldn't fault because " "the mustUnderstand attribute is 0") hd.MustUnderstandThis._setMustUnderstand (0) server = server._hd (hd) result = server.echoInteger (inputInteger = test) if not SOAP.Config.typed: result = int (result) if result != test: raise Exception, "expected %s, got %s" % (test, result) def testEchoDate (server, action, harsh): test = time.gmtime (time.time ()) server = server._sa (action % {'methodname': 'echoDate'}) if SOAP.Config.namespaceStyle == '1999': result = server.echoDate (inputDate = SOAP.timeInstantType (test)) else: result = server.echoDate (inputDate = SOAP.dateTimeType (test)) if not SOAP.Config.typed and type (result) in (type (''), type (u'')): p = SOAP.SOAPParser() result = p.convertDateTime(result, 'timeInstant') if result != test[:6]: raise Exception, "expected %s, got %s" % (repr (test), repr (result)) def testEchoBase64 (server, action, harsh): test = '\x00\x10\x20\x30\x40\x50\x60\x70\x80\x90\xa0\xb0\xc0\xd0\xe0\xf0' server = server._sa (action % {'methodname': 'echoBase64'}) result = server.echoBase64 (inputBase64 = SOAP.base64Type (test)) if not SOAP.Config.typed: import base64 result = base64.decodestring(result) if result != test: raise Exception, "expected %s, got %s" % (repr (test), repr (result)) def main (): stats = 1 total = 0 fail = 0 failok = 0 succeed = 0 exitonfailure = 0 harsh = 0 invert = 0 printtrace = 0 methodnums = None notimp = 0 output = 'f' servers = DEFAULT_SERVERS_FILE started = time.time () try: opts, args = getopt.getopt (sys.argv[1:], '?dehim:nNo:s:tT', ['help', 'debug', 'exit-on-failure', 'harsh', 'invert', 'method', 'no-stats', 'no-statistics', 'no-boring-statistics', 'no-boring-stats', 'output', 'servers=', 'stacktrace', 'always-stacktrace']) for opt, arg in opts: if opt in ('-?', '--help'): usage () elif opt in ('-d', '--debug'): SOAP.Config.debug = 1 elif opt in ('-h', '--harsh'): harsh = 1 elif opt in ('-i', '--invert'): invert = 1 elif opt in ('-e', '--exit-on-failure'): exitonfailure = 1 elif opt in ('-m', '--method'): if arg == '?': methodUsage () methodnums = str2list (arg) elif opt in ('-n', '--no-stats', '--no-statistics'): stats = 0 elif opt in ('-N', '--no-boring-stats', '--no-boring-statistics'): stats = -1 elif opt in ('-o', '--output'): output = arg elif opt in ('-s', '--servers'): servers = arg elif opt in ('-t', '--stacktrace'): printtrace = 1 elif opt in ('-T', '--always-stacktrace'): printtrace = 2 else: raise AttributeError, \ "Recognized but unimplemented option `%s'" % opt except SystemExit: raise except: usage (sys.exc_info ()[1]) if 'a' in output: output = 'fFns' servers = readServers (servers) if methodnums == None: methodnums = range (1, len (DEFAULT_METHODS) + 1) limitre = re.compile ('|'.join (args), re.IGNORECASE) for s in servers: if (not not limitre.match (s['name'])) == invert: continue try: typed = s['typed'] except: typed = 1 try: style = s['style'] except: style = 1999 SOAP.Config.typed = typed SOAP.Config.namespaceStyle = style server = SOAP.SOAPProxy (s['endpoint'], ("m", s['namespace'])) for num in (methodnums): if num > len (DEFAULT_METHODS): break total += 1 name = DEFAULT_METHODS[num - 1] title = '%s: %s (#%d)' % (s['name'], name, num) if SOAP.Config.debug: print "%s:" % title try: fn = globals ()['test' + name[0].upper () + name[1:]] except KeyboardInterrupt: raise except: if 'n' in output: print title, "test not yet implemented" notimp += 1 continue try: fn (server, s['soapaction'], harsh) if s['nonfunctional'].has_key (name): print title, \ "succeeded despite being marked nonfunctional" if 's' in output: print title, "succeeded" succeed += 1 except KeyboardInterrupt: raise except: fault = str (sys.exc_info ()[1]) if fault[-1] == '\n': fault = fault[:-1] if s['nonfunctional'].has_key (name): if 'F' in output: t = 'as expected' if s['nonfunctional'][name] != '': t += ', ' + s['nonfunctional'][name] print title, "failed (%s) -" % t, fault if printtrace > 1: traceback.print_exc () failok += 1 else: if 'f' in output: print title, "failed -", fault if printtrace: traceback.print_exc () fail += 1 if exitonfailure: return -1 if stats: print " Tests started at:", time.ctime (started) if stats > 0: print " Total tests: %d" % total print " Successes: %d (%3.2f%%)" % \ (succeed, 100.0 * succeed / total) if stats > 0 or fail > 0: print "Failed unexpectedly: %d (%3.2f%%)" % \ (fail, 100.0 * fail / total) if stats > 0: print " Failed as expected: %d (%3.2f%%)" % \ (failok, 100.0 * failok / total) if stats > 0 or notimp > 0: print " Not implemented: %d (%3.2f%%)" % \ (notimp, 100.0 * notimp / total) return fail + notimp if __name__ == '__main__': try: sys.exit (main ()) except KeyboardInterrupt: sys.exit (0) SOAPpy-0.12.22/validate/silabserver.py000077500000000000000000000066751235077700100175000ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2001 actzero, inc. All rights reserved. # This is a server for the XMethods matrix # (http://jake.soapware.org/currentXmethodsResults). import getopt import sys sys.path.insert (1, '..') from SOAPpy import SOAP if SOAP.Config.SSLserver: from M2Crypto import SSL ident = '$Id: silabserver.py 98 2003-03-08 05:10:01Z warnes $' def echoFloat (inputFloat): return inputFloat def echoFloatArray (inputFloatArray): return inputFloatArray def echoInteger (inputInteger): return inputInteger def echoIntegerArray (inputIntegerArray): return inputIntegerArray def echoString (inputString): return inputString def echoStringArray (inputStringArray): return inputStringArray def echoStruct (inputStruct): return inputStruct def echoStructArray (inputStructArray): return inputStructArray def echoVoid (): return SOAP.voidType() def echoDate (inputDate): return SOAP.dateTimeType (inputDate) def echoBase64 (inputBase64): return SOAP.binaryType (inputBase64) namespace = 'http://soapinterop.org/' DEFAULT_HOST = 'localhost' DEFAULT_HTTP_PORT = 8080 DEFAULT_HTTPS_PORT = 8443 def usage (error = None): sys.stdout = sys.stderr if error != None: print error print """usage: %s [options] If a long option shows an argument is mandatory, it's mandatory for the equivalent short option also. The default (if any) is shown in brackets. -?, --help display this usage -h, --host=HOST use HOST in the address to listen on [%s] -p, --port=PORT listen on PORT [%d] """ % (sys.argv[0], DEFAULT_HOST, DEFAULT_HTTP_PORT), if SOAP.Config.SSLserver: print " -s, --ssl serve using SSL" sys.exit (0) def main (): host = DEFAULT_HOST port = None ssl = 0 try: opts = '?h:p:' args = ['help', 'host', 'port'] if SOAP.Config.SSLserver: opts += 's' args += ['ssl'] opts, args = getopt.getopt (sys.argv[1:], opts, args) for opt, arg in opts: if opt in ('-?', '--help'): usage () elif opt in ('-h', '--host'): host = arg elif opt in ('-p', '--port'): port = int (arg) elif opt in ('-s', '--ssl'): ssl = 1 else: raise AttributeError, \ "Recognized but unimplemented option `%s'" % opt except SystemExit: raise except: usage (sys.exc_info ()[1]) if port == None: port = [DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT][ssl] if ssl: ssl_context = SSL.Context() ssl_context.load_cert('server.pem') else: ssl_context = None server = SOAP.SOAPServer ((host, port), namespace = namespace, ssl_context = ssl_context) server.registerFunction (echoFloat) server.registerFunction (echoFloatArray) server.registerFunction (echoInteger) server.registerFunction (echoIntegerArray) server.registerFunction (echoString) server.registerFunction (echoStringArray) server.registerFunction (echoStruct) server.registerFunction (echoStructArray) server.registerFunction (echoVoid) server.registerFunction (echoDate) server.registerFunction (echoBase64) server.serve_forever() if __name__ == '__main__': try: sys.exit (main ()) except KeyboardInterrupt: sys.exit (0) SOAPpy-0.12.22/validate/soapware.py000077500000000000000000000062621235077700100167700ustar00rootroot00000000000000#!/usr/bin/env python # This server validates as of 4/23/01 when run with UserLand's SOAP validator # (http://validator.soapware.org/). import getopt import sys sys.path.insert (1, '..') from SOAPpy import SOAP ident = '$Id: soapware.py 98 2003-03-08 05:10:01Z warnes $' def whichToolkit (): return SOAP.SOAPUserAgent () def countTheEntities (s): counts = {'ctLeftAngleBrackets': 0, 'ctRightAngleBrackets': 0, 'ctAmpersands': 0, 'ctApostrophes': 0, 'ctQuotes': 0} for i in s: if i == '<': counts['ctLeftAngleBrackets'] += 1 elif i == '>': counts['ctRightAngleBrackets'] += 1 elif i == '&': counts['ctAmpersands'] += 1 elif i == "'": counts['ctApostrophes'] += 1 elif i == '"': counts['ctQuotes'] += 1 return counts def easyStructTest (stooges): return stooges['larry'] + stooges['moe'] + stooges['curly'] def echoStructTest (myStruct): return myStruct def manyTypesTest (num, bool, state, doub, dat, bin): return [num, SOAP.booleanType (bool), state, doub, SOAP.dateTimeType (dat), bin] def moderateSizeArrayCheck (myArray): return myArray[0] + myArray[-1] def nestedStructTest (myStruct): return easyStructTest (myStruct.year2000.month04.day01) def simpleStructReturnTest (myNumber): return {'times10': myNumber * 10, 'times100': myNumber * 100, 'times1000': myNumber * 1000} namespace = 'http://www.soapware.org/' DEFAULT_HOST = 'localhost' DEFAULT_PORT = 8080 def usage (error = None): sys.stdout = sys.stderr if error != None: print error print """usage: %s [options] If a long option shows an argument is mandatory, it's mandatory for the equivalent short option also. The default (if any) is shown in brackets. -?, --help display this usage -h, --host=HOST use HOST in the address to listen on [%s] -p, --port=PORT listen on PORT [%d] """ % (sys.argv[0], DEFAULT_HOST, DEFAULT_PORT), sys.exit (0) def main (): host = DEFAULT_HOST port = DEFAULT_PORT try: opts, args = getopt.getopt (sys.argv[1:], '?h:p:', ['help', 'host', 'port']) for opt, arg in opts: if opt in ('-?', '--help'): usage () elif opt in ('-h', '--host'): host = arg elif opt in ('-p', '--port'): port = int (arg) else: raise AttributeError, \ "Recognized but unimplemented option `%s'" % opt except SystemExit: raise except: usage (sys.exc_info ()[1]) server = SOAP.SOAPServer ((host, port)) server.registerFunction (whichToolkit, namespace) server.registerFunction (countTheEntities) server.registerFunction (easyStructTest) server.registerFunction (echoStructTest) server.registerFunction (manyTypesTest) server.registerFunction (moderateSizeArrayCheck) server.registerFunction (nestedStructTest) server.registerFunction (simpleStructReturnTest) server.serve_forever() if __name__ == '__main__': try: sys.exit (main ()) except KeyboardInterrupt: sys.exit (0) SOAPpy-0.12.22/vul_ok.txt000066400000000000000000000011741235077700100150360ustar00rootroot00000000000000POST / HTTP/1.0 Host: localhost:8080 User-agent: SOAPpy 0.12.0 (pywebsvcs.sf.net) Content-type: text/xml; charset="UTF-8" Content-length: 484 SOAPAction: "echo" Hello world SOAPpy-0.12.22/zope/000077500000000000000000000000001235077700100137505ustar00rootroot00000000000000SOAPpy-0.12.22/zope/README000066400000000000000000000017661235077700100146420ustar00rootroot00000000000000Using SOAP with ZOPE -------------------- We can use Zope to provide web services. The first is to support SOAP like XML-RPC. There are two patches for Zope 2.5.0 version and for Zope 2.6.2 version. To apply the path, you only need to do: $ cd $ patch -p1 < //zope-2.6.2-soappy.diff You need to install SOAPpy and fpconst. You can download this two packages from here: http://sourceforge.net/projects/pywebsvcs http://software.biostat.washington.edu/statsoft/snake/fpconst/ If you are using the precompiled version of Zope, you need to add the path to the PYTHONPATH environment variable to specify where this packages lives. To do this, add a line like this to your start script: export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.3/site-packages/ Note: This can be dangerous because in your machine you are using several versions of python. [NB: The contents of this directory contributed by Antonio Beamud Montero ] SOAPpy-0.12.22/zope/zope-2.5.0-soappy.diff000066400000000000000000000142201235077700100175270ustar00rootroot00000000000000diff -urN Zope-2.5.0-linux2-x86/lib/python/ZPublisher/HTTPRequest.py Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py --- Zope-2.5.0-linux2-x86/lib/python/ZPublisher/HTTPRequest.py 2002-01-03 20:41:05.000000000 +0100 +++ Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2003-11-12 13:17:57.000000000 +0100 @@ -21,6 +21,7 @@ from Converters import get_converter from maybe_lock import allocate_lock xmlrpc=None # Placeholder for module that we'll import if we have to. +soap=None #cgi hotfix: if not hasattr(cgi, 'valid_boundary'): @@ -347,18 +348,28 @@ meth=None fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1) if not hasattr(fs,'list') or fs.list is None: - # Hm, maybe it's an XML-RPC - if (fs.headers.has_key('content-type') and - fs.headers['content-type'] == 'text/xml' and + # Hm, maybe it's an XML-RPC or SOAP + if (fs.headers.has_key('content-type') and + fs.headers['content-type'][:8] == 'text/xml' and method == 'POST'): - # Ye haaa, XML-RPC! - global xmlrpc - if xmlrpc is None: import xmlrpc - meth, self.args = xmlrpc.parse_input(fs.value) - response=xmlrpc.response(response) - other['RESPONSE']=self.response=response - other['REQUEST_METHOD']='' # We don't want index_html! - self.maybe_webdav_client = 0 + if environ.has_key('HTTP_SOAPACTION'): + # this is a SOAP request + global soap + if soap is None: + import soap + meth, self.args = soap.parse_input(fs.value) + response = soap.response(response) + other['RESPONSE'] = self.response = response + other['REQUEST_METHOD'] = '' + else: + # Ye haaa, XML-RPC! + global xmlrpc + if xmlrpc is None: import xmlrpc + meth, self.args = xmlrpc.parse_input(fs.value) + response=xmlrpc.response(response) + other['RESPONSE']=self.response=response + other['REQUEST_METHOD']='' # We don't want index_html! + self.maybe_webdav_client = 0 else: self._file=fs.file else: 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 --- Zope-2.5.0-linux2-x86/lib/python/ZPublisher/soap.py 1970-01-01 01:00:00.000000000 +0100 +++ Zope-2.5.0-linux2-x86.1/lib/python/ZPublisher/soap.py 2003-11-12 13:20:39.000000000 +0100 @@ -0,0 +1,108 @@ +"""SOAP support module + +by Antonio Beamud Montero + +Based on the XML-RPC Zope support module written by Eric Kidd at UserLand +software and the modifications made by Petru Paler, with much help +from Jim Fulton at DC. + +This code hooks Zope up to SOAPpy library. +""" + +import sys +from string import replace +from HTTPResponse import HTTPResponse +from SOAPpy import * +from zLOG import LOG, PROBLEM, ERROR, DEBUG, INFO,TRACE + +Config.specialArgs=0. + +def parse_input(data): + """Parse input data and return a method path and argument tuple + + The data is a string. + """ + obj = Parser.parseSOAPRPC(data) + method = obj._name + args = tuple(obj._aslist) + + # Translate '.' to '/' in meth to represent object traversal. + method = replace(method, '.', '/') + return method, args + +####################################################################### +# New Object response based on SOAPpy +# +class SOAPResponse: + def __init__(self, real): self.__dict__['_real']=real + def __getattr__(self, name): return getattr(self._real, name) + def __setattr__(self, name, v): return setattr(self._real, name, v) + def __delattr__(self, name): return delattr(self._real, name) + + def setBody(self, body, title='', is_error=0, bogus_str_search=None): + # Marshall our body as an SOAP response. Strings will be sent + # strings, integers as integers, etc. We do *not* convert + # everything to a string first. + status = 200 + if isinstance(body, Types.faultType): + status = 500 + # Convert Fault object to SOAP response. + soapbody = Types.faulType("%s:Server" % NS.ENV_T, body) + body = buildSOAP(soapbody,encoding=None) + else: + try: + body = buildSOAP((body,),encoding=None) + except Exception,e: + self.exception() + return self + + t = 'text/xml' + # Set our body to the XML-RPC message, and fix our MIME type. + self._real.setBody(body) + self._real.setHeader('content-type', t) + self._real.setHeader("content-length", str(len(body))) + self._real.setStatus(status) + return self + + def exception(self, fatal=0, info=None, + absuri_match=None, tag_search=None): + # Fetch our exception info. t is type, v is value and tb is the + # traceback object. + + if type(info) is type(()) and len(info)==3: t,v,tb = info + else: t,v,tb = sys.exc_info() + LOG('SOAPException', TRACE, tb) + # Create an appropriate Fault object. Unfortunately, we throw away + # most of the debugging information. More useful error reporting is + # left as an exercise for the reader. + Fault=Types.faultType + f=None + try: + if isinstance(v, Fault): + f=v + elif isinstance(v, Exception): + f=Fault("%s:Server" % NS.ENV_T, + "Unexpected Zope exception: %s"%str(v)) + else: + f=Fault("%s:Server" % NS.ENV_T, + "Unexpected Zope error value: %s"%str(v)) + except: + f=Fault("%s:Server" % NS.ENV_T, + "Unknown Zope fault type") + + # Do the damage. + body = buildSOAP(f) + self._real.setBody(body) + self._real.setHeader('content-type', 'text/xml') + self._real.setStatus(500) + return tb + +response=SOAPResponse + + + + + + + + SOAPpy-0.12.22/zope/zope-2.6.2-soappy.diff000066400000000000000000000147501235077700100175420ustar00rootroot00000000000000diff -urN Zope-2.6.2-linux2-x86/lib/python/ZPublisher/HTTPRequest.py Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py --- Zope-2.6.2-linux2-x86/lib/python/ZPublisher/HTTPRequest.py 2003-04-09 16:00:27.000000000 +0200 +++ Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/HTTPRequest.py 2003-11-12 14:51:01.000000000 +0100 @@ -24,6 +24,7 @@ from TaintedString import TaintedString from maybe_lock import allocate_lock xmlrpc=None # Placeholder for module that we'll import if we have to. +soap=None # Placeholder for module that we'll import if we have to. #cgi hotfix: if not hasattr(cgi, 'valid_boundary'): @@ -369,16 +370,26 @@ meth=None fs=FieldStorage(fp=fp,environ=environ,keep_blank_values=1) if not hasattr(fs,'list') or fs.list is None: - # Hm, maybe it's an XML-RPC + # Hm, maybe it's an XML-RPC or SOAP if (fs.headers.has_key('content-type') and - fs.headers['content-type'] == 'text/xml' and + fs.headers['content-type'][:8] == 'text/xml' and method == 'POST'): - # Ye haaa, XML-RPC! - global xmlrpc - if xmlrpc is None: import xmlrpc - meth, self.args = xmlrpc.parse_input(fs.value) - response=xmlrpc.response(response) - other['RESPONSE']=self.response=response + if environ.has_key('HTTP_SOAPACTION'): + # this is a SOAP request + global soap + if soap is None: + import soap + meth, self.args = soap.parse_input(fs.value) + response = soap.response(response) + other['RESPONSE'] = self.response = response + other['REQUEST_METHOD'] = '' + else: + # Ye haaa, XML-RPC! + global xmlrpc + if xmlrpc is None: import xmlrpc + meth, self.args = xmlrpc.parse_input(fs.value) + response=xmlrpc.response(response) + other['RESPONSE']=self.response=response self.maybe_webdav_client = 0 else: self._file=fs.file 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 --- Zope-2.6.2-linux2-x86/lib/python/ZPublisher/soap.py 1970-01-01 01:00:00.000000000 +0100 +++ Zope-2.6.2-linux2-x86.1/lib/python/ZPublisher/soap.py 2003-11-12 14:51:01.000000000 +0100 @@ -0,0 +1,125 @@ +"""SOAP support module + +by Antonio Beamud Montero + +Based on the XML-RPC Zope support module written by Eric Kidd at UserLand +software and the modifications made by Petru Paler, with much help +from Jim Fulton at DC. + +This code hooks Zope up to SOAPpy library. +""" + +import sys +from string import replace +from HTTPResponse import HTTPResponse +from SOAPpy import * +from zLOG import LOG, PROBLEM, ERROR, DEBUG, INFO,TRACE + +Config.specialArgs=0. + +def parse_input(data): + """Parse input data and return a method path and argument tuple + + The data is a string. + """ + obj = Parser.parseSOAPRPC(data) + method = obj._name + args = tuple(obj._aslist) + + # Translate '.' to '/' in meth to represent object traversal. + method = replace(method, '.', '/') + return method, args + +# See below +# +# def response(anHTTPResponse): +# """Return a valid ZPublisher response object +# +# Use data already gathered by the existing response. +# The new response will replace the existing response. +# """ +# # As a first cut, lets just clone the response and +# # put all of the logic in our refined response class below. +# r=Response() +# r.__dict__.update(anHTTPResponse.__dict__) +# return r + + + + +####################################################################### +# New Object response based on SoapPy +# +class SOAPResponse: + def __init__(self, real): self.__dict__['_real']=real + def __getattr__(self, name): return getattr(self._real, name) + def __setattr__(self, name, v): return setattr(self._real, name, v) + def __delattr__(self, name): return delattr(self._real, name) + + def setBody(self, body, title='', is_error=0, bogus_str_search=None): + # Marshall our body as an SOAP response. Strings will be sent + # strings, integers as integers, etc. We do *not* convert + # everything to a string first. + status = 200 + if isinstance(body, Types.faultType): + status = 500 + # Convert Fault object to SOAP response. + soapbody = Types.faulType("%s:Server" % NS.ENV_T, body) + body = buildSOAP(soapbody,encoding=None) + else: + try: + body = buildSOAP((body,),encoding=None) + except Exception,e: + self.exception() + return self + + t = 'text/xml' + # Set our body to the XML-RPC message, and fix our MIME type. + self._real.setBody(body) + self._real.setHeader('content-type', t) + self._real.setHeader("content-length", str(len(body))) + self._real.setStatus(status) + return self + + def exception(self, fatal=0, info=None, + absuri_match=None, tag_search=None): + # Fetch our exception info. t is type, v is value and tb is the + # traceback object. + + if type(info) is type(()) and len(info)==3: t,v,tb = info + else: t,v,tb = sys.exc_info() + LOG('SOAPException', TRACE, tb) + # Create an appropriate Fault object. Unfortunately, we throw away + # most of the debugging information. More useful error reporting is + # left as an exercise for the reader. + Fault=Types.faultType + f=None + try: + if isinstance(v, Fault): + f=v + elif isinstance(v, Exception): + f=Fault("%s:Server" % NS.ENV_T, + "Unexpected Zope exception: %s"%str(v)) + else: + f=Fault("%s:Server" % NS.ENV_T, + "Unexpected Zope error value: %s"%str(v)) + except: + f=Fault("%s:Server" % NS.ENV_T, + "Unknown Zope fault type") + + # Do the damage. + body = buildSOAP(f) + self._real.setBody(body) + self._real.setHeader('content-type', 'text/xml') + self._real.setStatus(500) + return tb + +response=SOAPResponse + + + + + + + + SOAPpy-0.12.22/zope/zope-soap-client.py000066400000000000000000000006711235077700100175170ustar00rootroot00000000000000#!/usr/bin/env python import sys from SOAPpy import SOAP # Uncomment to see outgoing HTTP headers and SOAP and incoming SOAP. SOAP.Config.debug = 1 SOAP.Config.BuildWithNoType = 0 SOAP.Config.BuildWithNoNamespacePrefix = 0 if len(sys.argv) > 1 and sys.argv[1] == '-s': server = SOAP.SOAPProxy("https://localhost:8080") else: server = SOAP.SOAPProxy("http://admin:pw3340@localhost:8080/",encoding=None) x = server.sopa() print x