Browse Source

fixes for version 0.4, replaced prints with logger.debug() and pep8

main
Sorin Sbarnea 12 years ago
parent
commit
4d2ca35862
19 changed files with 1139 additions and 1014 deletions
  1. +1
    -0
      .gitignore
  2. +3
    -4
      CHANGES.txt
  3. +2
    -2
      MANIFEST.in
  4. +11
    -11
      setup.py
  5. +8
    -9
      src/wstools/MIMEAttachment.py
  6. +81
    -73
      src/wstools/Namespaces.py
  7. +31
    -20
      src/wstools/TimeoutSocket.py
  8. +43
    -20
      src/wstools/UserTuple.py
  9. +114
    -111
      src/wstools/Utility.py
  10. +114
    -93
      src/wstools/WSDLTools.py
  11. +499
    -493
      src/wstools/XMLSchema.py
  12. +39
    -31
      src/wstools/XMLname.py
  13. +0
    -1
      src/wstools/__init__.py
  14. +82
    -73
      src/wstools/c14n.py
  15. +73
    -49
      src/wstools/logging.py
  16. +4
    -3
      src/wstools/tests/test_t1.py
  17. +19
    -12
      src/wstools/tests/test_wsdl.py
  18. +11
    -6
      src/wstools/tests/test_wstools.py
  19. +4
    -3
      src/wstools/tests/test_wstools_net.py

+ 1
- 0
.gitignore View File

@@ -1,2 +1,3 @@
dist
*.egg-info *.egg-info
*.pyc *.pyc

+ 3
- 4
CHANGES.txt View File

@@ -1,12 +1,11 @@
CHANGELOG CHANGELOG
=========== ===========


0.4 (unreleased)
0.4 (2012-06-26)
---------------- ----------------


- Nothing changed yet.


- Replaced print() with logging.debug() or warn() in order to allow users to change verbosity.
- Added release.sh script which runs tests, pep8 and allow you to release only when these are passing.


0.3 (2011-02-21) 0.3 (2011-02-21)
---------------- ----------------


+ 2
- 2
MANIFEST.in View File

@@ -1,5 +1,5 @@
include README.txt include README.txt
include CHANGES.txt include CHANGES.txt
include README
recursive-include src *.txt *.py *.tar.gz
recursive-include docs *.*
recursive-include src *.txt *.py *.tar.gz README



+ 11
- 11
setup.py View File

@@ -2,21 +2,22 @@
# #
# $Id: setup.py,v 1.11 2005/02/15 16:32:22 warnes Exp $ # $Id: setup.py,v 1.11 2005/02/15 16:32:22 warnes Exp $


import os,re
import os
import re
from setuptools import setup, find_packages from setuptools import setup, find_packages


__version__ = '0.3'
__version__ = '0.4'




url="https://github.com/kiorky/wstools.git"
url = "https://github.com/pycontribs/wstools.git"




def read(*rnames): def read(*rnames):
return "\n"+ open(
return "\n" + open(
os.path.join('.', *rnames) os.path.join('.', *rnames)
).read() ).read()


long_description="""WSDL parsing services package for Web Services for Python. see """ + url \
long_description = """WSDL parsing services package for Web Services for Python. see """ + url \
+ read('README.txt')\ + read('README.txt')\
+ read('CHANGES.txt')\ + read('CHANGES.txt')\


@@ -25,13 +26,12 @@ setup(
name="wstools", name="wstools",
version=__version__, version=__version__,
description="wstools", description="wstools",
maintainer="Gregory Warnes, kiorky",
maintainer_email="Gregory.R.Warnes@Pfizer.com, kiorky@cryptelium.net",
url = url,
maintainer="Gregory Warnes, kiorky, sorin",
maintainer_email="Gregory.R.Warnes@Pfizer.com, kiorky@cryptelium.net, sorin.sbarnea@gmail.com",
url=url,
long_description=long_description, long_description=long_description,
packages=find_packages('src'), packages=find_packages('src'),
package_dir = {'': 'src'},
include_package_data=True,
package_dir={'': 'src'},
include_package_data=True,
install_requires=[] install_requires=[]
) )


+ 8
- 9
src/wstools/MIMEAttachment.py View File

@@ -12,11 +12,12 @@ import sys




#new line #new line
NL='\r\n'
NL = '\r\n'


_width = len(repr(sys.maxint-1))
_width = len(repr(sys.maxint - 1))
_fmt = '%%0%dd' % _width _fmt = '%%0%dd' % _width



class MIMEMessage: class MIMEMessage:


def __init__(self): def __init__(self):
@@ -26,19 +27,18 @@ class MIMEMessage:
self._boundary = "" self._boundary = ""


def makeBoundary(self): def makeBoundary(self):
#create the boundary
#create the boundary
msgparts = [] msgparts = []
msgparts.append(self._xmlMessage) msgparts.append(self._xmlMessage)
for i in self._files: for i in self._files:
msgparts.append(i.read()) msgparts.append(i.read())
#this sucks, all in memory #this sucks, all in memory
alltext = NL.join(msgparts) alltext = NL.join(msgparts)
self._boundary = _make_boundary(alltext)
self._boundary = _make_boundary(alltext)
#maybe I can save some memory #maybe I can save some memory
del alltext del alltext
del msgparts del msgparts
self._startCID = "<" + (_fmt % random.randrange(sys.maxint)) + (_fmt % random.randrange(sys.maxint)) + ">"

self._startCID = "<" + (_fmt % random.randrange(sys.maxint)) + (_fmt % random.randrange(sys.maxint)) + ">"


def toString(self): def toString(self):
'''it return a string with the MIME message''' '''it return a string with the MIME message'''
@@ -61,7 +61,7 @@ class MIMEMessage:
file.seek(0) file.seek(0)
returnstr += file.read() + NL returnstr += file.read() + NL
#closing boundary #closing boundary
returnstr += "--" + self._boundary + "--" + NL
returnstr += "--" + self._boundary + "--" + NL
return returnstr return returnstr


def attachFile(self, file): def attachFile(self, file):
@@ -78,7 +78,7 @@ class MIMEMessage:


def getBoundary(self): def getBoundary(self):
''' '''
this function returns the string used in the mime message as a
this function returns the string used in the mime message as a
boundary. First the write method as to be called boundary. First the write method as to be called
''' '''
return self._boundary return self._boundary
@@ -107,4 +107,3 @@ def _make_boundary(text=None):
b = boundary + '.' + str(counter) b = boundary + '.' + str(counter)
counter += 1 counter += 1
return b return b


+ 81
- 73
src/wstools/Namespaces.py View File

@@ -6,76 +6,76 @@
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE. # FOR A PARTICULAR PURPOSE.
"""Namespace module, so you don't need PyXML
"""Namespace module, so you don't need PyXML
""" """


ident = "$Id$" ident = "$Id$"
try: try:
from xml.ns import SOAP, SCHEMA, WSDL, XMLNS, DSIG, ENCRYPTION from xml.ns import SOAP, SCHEMA, WSDL, XMLNS, DSIG, ENCRYPTION
DSIG.C14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
DSIG.C14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
except: except:
class SOAP: class SOAP:
ENV = "http://schemas.xmlsoap.org/soap/envelope/"
ENC = "http://schemas.xmlsoap.org/soap/encoding/"
ACTOR_NEXT = "http://schemas.xmlsoap.org/soap/actor/next"
ENV = "http://schemas.xmlsoap.org/soap/envelope/"
ENC = "http://schemas.xmlsoap.org/soap/encoding/"
ACTOR_NEXT = "http://schemas.xmlsoap.org/soap/actor/next"


class SCHEMA: class SCHEMA:
XSD1 = "http://www.w3.org/1999/XMLSchema"
XSD2 = "http://www.w3.org/2000/10/XMLSchema"
XSD3 = "http://www.w3.org/2001/XMLSchema"
XSD_LIST = [ XSD1, XSD2, XSD3]
XSI1 = "http://www.w3.org/1999/XMLSchema-instance"
XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance"
XSI3 = "http://www.w3.org/2001/XMLSchema-instance"
XSI_LIST = [ XSI1, XSI2, XSI3 ]
BASE = XSD3
XSD1 = "http://www.w3.org/1999/XMLSchema"
XSD2 = "http://www.w3.org/2000/10/XMLSchema"
XSD3 = "http://www.w3.org/2001/XMLSchema"
XSD_LIST = [XSD1, XSD2, XSD3]
XSI1 = "http://www.w3.org/1999/XMLSchema-instance"
XSI2 = "http://www.w3.org/2000/10/XMLSchema-instance"
XSI3 = "http://www.w3.org/2001/XMLSchema-instance"
XSI_LIST = [XSI1, XSI2, XSI3]
BASE = XSD3


class WSDL: class WSDL:
BASE = "http://schemas.xmlsoap.org/wsdl/"
BIND_HTTP = "http://schemas.xmlsoap.org/wsdl/http/"
BIND_MIME = "http://schemas.xmlsoap.org/wsdl/mime/"
BIND_SOAP = "http://schemas.xmlsoap.org/wsdl/soap/"
BASE = "http://schemas.xmlsoap.org/wsdl/"
BIND_HTTP = "http://schemas.xmlsoap.org/wsdl/http/"
BIND_MIME = "http://schemas.xmlsoap.org/wsdl/mime/"
BIND_SOAP = "http://schemas.xmlsoap.org/wsdl/soap/"
BIND_SOAP12 = "http://schemas.xmlsoap.org/wsdl/soap12/" BIND_SOAP12 = "http://schemas.xmlsoap.org/wsdl/soap12/"


class XMLNS: class XMLNS:
BASE = "http://www.w3.org/2000/xmlns/"
XML = "http://www.w3.org/XML/1998/namespace"
HTML = "http://www.w3.org/TR/REC-html40"
BASE = "http://www.w3.org/2000/xmlns/"
XML = "http://www.w3.org/XML/1998/namespace"
HTML = "http://www.w3.org/TR/REC-html40"


class DSIG: class DSIG:
BASE = "http://www.w3.org/2000/09/xmldsig#"
C14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
C14N_COMM = "http://www.w3.org/TR/2000/CR-xml-c14n-20010315#WithComments"
C14N_EXCL = "http://www.w3.org/2001/10/xml-exc-c14n#"
DIGEST_MD2 = "http://www.w3.org/2000/09/xmldsig#md2"
DIGEST_MD5 = "http://www.w3.org/2000/09/xmldsig#md5"
DIGEST_SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1"
ENC_BASE64 = "http://www.w3.org/2000/09/xmldsig#base64"
ENVELOPED = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
HMAC_SHA1 = "http://www.w3.org/2000/09/xmldsig#hmac-sha1"
BASE = "http://www.w3.org/2000/09/xmldsig#"
C14N = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
C14N_COMM = "http://www.w3.org/TR/2000/CR-xml-c14n-20010315#WithComments"
C14N_EXCL = "http://www.w3.org/2001/10/xml-exc-c14n#"
DIGEST_MD2 = "http://www.w3.org/2000/09/xmldsig#md2"
DIGEST_MD5 = "http://www.w3.org/2000/09/xmldsig#md5"
DIGEST_SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1"
ENC_BASE64 = "http://www.w3.org/2000/09/xmldsig#base64"
ENVELOPED = "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
HMAC_SHA1 = "http://www.w3.org/2000/09/xmldsig#hmac-sha1"
SIG_DSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#dsa-sha1" SIG_DSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#dsa-sha1"
SIG_RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" SIG_RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
XPATH = "http://www.w3.org/TR/1999/REC-xpath-19991116"
XSLT = "http://www.w3.org/TR/1999/REC-xslt-19991116"
XPATH = "http://www.w3.org/TR/1999/REC-xpath-19991116"
XSLT = "http://www.w3.org/TR/1999/REC-xslt-19991116"


class ENCRYPTION: class ENCRYPTION:
BASE = "http://www.w3.org/2001/04/xmlenc#"
BLOCK_3DES = "http://www.w3.org/2001/04/xmlenc#des-cbc"
BLOCK_AES128 = "http://www.w3.org/2001/04/xmlenc#aes128-cbc"
BLOCK_AES192 = "http://www.w3.org/2001/04/xmlenc#aes192-cbc"
BLOCK_AES256 = "http://www.w3.org/2001/04/xmlenc#aes256-cbc"
DIGEST_RIPEMD160 = "http://www.w3.org/2001/04/xmlenc#ripemd160"
DIGEST_SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256"
DIGEST_SHA512 = "http://www.w3.org/2001/04/xmlenc#sha512"
KA_DH = "http://www.w3.org/2001/04/xmlenc#dh"
KT_RSA_1_5 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
KT_RSA_OAEP = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
STREAM_ARCFOUR = "http://www.w3.org/2001/04/xmlenc#arcfour"
WRAP_3DES = "http://www.w3.org/2001/04/xmlenc#kw-3des"
WRAP_AES128 = "http://www.w3.org/2001/04/xmlenc#kw-aes128"
WRAP_AES192 = "http://www.w3.org/2001/04/xmlenc#kw-aes192"
WRAP_AES256 = "http://www.w3.org/2001/04/xmlenc#kw-aes256"
BASE = "http://www.w3.org/2001/04/xmlenc#"
BLOCK_3DES = "http://www.w3.org/2001/04/xmlenc#des-cbc"
BLOCK_AES128 = "http://www.w3.org/2001/04/xmlenc#aes128-cbc"
BLOCK_AES192 = "http://www.w3.org/2001/04/xmlenc#aes192-cbc"
BLOCK_AES256 = "http://www.w3.org/2001/04/xmlenc#aes256-cbc"
DIGEST_RIPEMD160 = "http://www.w3.org/2001/04/xmlenc#ripemd160"
DIGEST_SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256"
DIGEST_SHA512 = "http://www.w3.org/2001/04/xmlenc#sha512"
KA_DH = "http://www.w3.org/2001/04/xmlenc#dh"
KT_RSA_1_5 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
KT_RSA_OAEP = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
STREAM_ARCFOUR = "http://www.w3.org/2001/04/xmlenc#arcfour"
WRAP_3DES = "http://www.w3.org/2001/04/xmlenc#kw-3des"
WRAP_AES128 = "http://www.w3.org/2001/04/xmlenc#kw-aes128"
WRAP_AES192 = "http://www.w3.org/2001/04/xmlenc#kw-aes192"
WRAP_AES256 = "http://www.w3.org/2001/04/xmlenc#kw-aes256"




class WSRF_V1_2: class WSRF_V1_2:
@@ -123,9 +123,9 @@ WSRFLIST = (WSRF_V1_2,)
class OASIS: class OASIS:
'''URLs for Oasis specifications '''URLs for Oasis specifications
''' '''
WSSE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
WSSE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
UTILITY = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" UTILITY = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
class X509TOKEN: class X509TOKEN:
Base64Binary = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" Base64Binary = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
STRTransform = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0" STRTransform = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0"
@@ -133,7 +133,7 @@ class OASIS:
X509 = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509" X509 = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509"
X509PKIPathv1 = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1" X509PKIPathv1 = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"
X509v3SubjectKeyIdentifier = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3SubjectKeyIdentifier" X509v3SubjectKeyIdentifier = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3SubjectKeyIdentifier"
LIFETIME = WSRF_V1_2.LIFETIME.XSD_DRAFT1 LIFETIME = WSRF_V1_2.LIFETIME.XSD_DRAFT1
PROPERTIES = WSRF_V1_2.PROPERTIES.XSD_DRAFT1 PROPERTIES = WSRF_V1_2.PROPERTIES.XSD_DRAFT1
BASENOTIFICATION = WSRF_V1_2.BASENOTIFICATION.XSD_DRAFT1 BASENOTIFICATION = WSRF_V1_2.BASENOTIFICATION.XSD_DRAFT1
@@ -151,45 +151,50 @@ class WSTRUST:
BASE = "http://schemas.xmlsoap.org/ws/2004/04/trust" BASE = "http://schemas.xmlsoap.org/ws/2004/04/trust"
ISSUE = "http://schemas.xmlsoap.org/ws/2004/04/trust/Issue" ISSUE = "http://schemas.xmlsoap.org/ws/2004/04/trust/Issue"



class WSSE: class WSSE:
BASE = "http://schemas.xmlsoap.org/ws/2002/04/secext"
TRUST = WSTRUST.BASE
BASE = "http://schemas.xmlsoap.org/ws/2002/04/secext"
TRUST = WSTRUST.BASE




class WSU: class WSU:
BASE = "http://schemas.xmlsoap.org/ws/2002/04/utility"
BASE = "http://schemas.xmlsoap.org/ws/2002/04/utility"
UTILITY = "http://schemas.xmlsoap.org/ws/2002/07/utility" UTILITY = "http://schemas.xmlsoap.org/ws/2002/07/utility"




class WSR: class WSR:
PROPERTIES = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties" PROPERTIES = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties"
LIFETIME = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime"
LIFETIME = "http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime"




class WSA200508: class WSA200508:
ADDRESS = "http://www.w3.org/2005/08/addressing"
ANONYMOUS = "%s/anonymous" %ADDRESS
FAULT = "%s/fault" %ADDRESS
ADDRESS = "http://www.w3.org/2005/08/addressing"
ANONYMOUS = "%s/anonymous" % ADDRESS
FAULT = "%s/fault" % ADDRESS



class WSA200408: class WSA200408:
ADDRESS = "http://schemas.xmlsoap.org/ws/2004/08/addressing"
ANONYMOUS = "%s/role/anonymous" %ADDRESS
FAULT = "%s/fault" %ADDRESS
ADDRESS = "http://schemas.xmlsoap.org/ws/2004/08/addressing"
ANONYMOUS = "%s/role/anonymous" % ADDRESS
FAULT = "%s/fault" % ADDRESS



class WSA200403: class WSA200403:
ADDRESS = "http://schemas.xmlsoap.org/ws/2004/03/addressing"
ANONYMOUS = "%s/role/anonymous" %ADDRESS
FAULT = "%s/fault" %ADDRESS
ADDRESS = "http://schemas.xmlsoap.org/ws/2004/03/addressing"
ANONYMOUS = "%s/role/anonymous" % ADDRESS
FAULT = "%s/fault" % ADDRESS



class WSA200303: class WSA200303:
ADDRESS = "http://schemas.xmlsoap.org/ws/2003/03/addressing"
ANONYMOUS = "%s/role/anonymous" %ADDRESS
FAULT = None
ADDRESS = "http://schemas.xmlsoap.org/ws/2003/03/addressing"
ANONYMOUS = "%s/role/anonymous" % ADDRESS
FAULT = None




WSA = WSA200408 WSA = WSA200408
WSA_LIST = (WSA200508, WSA200408, WSA200403, WSA200303) WSA_LIST = (WSA200508, WSA200408, WSA200403, WSA200303)



class _WSAW(str): class _WSAW(str):
""" Define ADDRESS attribute to be compatible with WSA* layout """ """ Define ADDRESS attribute to be compatible with WSA* layout """
ADDRESS = property(lambda s: s) ADDRESS = property(lambda s: s)
@@ -197,18 +202,21 @@ class _WSAW(str):
WSAW200605 = _WSAW("http://www.w3.org/2006/05/addressing/wsdl") WSAW200605 = _WSAW("http://www.w3.org/2006/05/addressing/wsdl")


WSAW_LIST = (WSAW200605,) WSAW_LIST = (WSAW200605,)


class WSP: class WSP:
POLICY = "http://schemas.xmlsoap.org/ws/2002/12/policy" POLICY = "http://schemas.xmlsoap.org/ws/2002/12/policy"



class BEA: class BEA:
SECCONV = "http://schemas.xmlsoap.org/ws/2004/04/sc" SECCONV = "http://schemas.xmlsoap.org/ws/2004/04/sc"
SCTOKEN = "http://schemas.xmlsoap.org/ws/2004/04/security/sc/sct" SCTOKEN = "http://schemas.xmlsoap.org/ws/2004/04/security/sc/sct"



class GLOBUS: class GLOBUS:
SECCONV = "http://wsrf.globus.org/core/2004/07/security/secconv" SECCONV = "http://wsrf.globus.org/core/2004/07/security/secconv"
CORE = "http://www.globus.org/namespaces/2004/06/core"
SIG = "http://www.globus.org/2002/04/xmlenc#gssapi-sign"
TOKEN = "http://www.globus.org/ws/2004/09/security/sc#GSSAPI_GSI_TOKEN"
CORE = "http://www.globus.org/namespaces/2004/06/core"
SIG = "http://www.globus.org/2002/04/xmlenc#gssapi-sign"
TOKEN = "http://www.globus.org/ws/2004/09/security/sc#GSSAPI_GSI_TOKEN"


ZSI_SCHEMA_URI = 'http://www.zolera.com/schemas/ZSI/' ZSI_SCHEMA_URI = 'http://www.zolera.com/schemas/ZSI/'

+ 31
- 20
src/wstools/TimeoutSocket.py View File

@@ -6,16 +6,19 @@


The original timeout_socket is by: The original timeout_socket is by:


Scott Cotton <scott@chronis.pobox.com>
Lloyd Zusman <ljz@asfast.com>
Phil Mayes <pmayes@olivebr.com>
Piers Lauder <piers@cs.su.oz.au>
Radovan Garabik <garabik@melkor.dnp.fmph.uniba.sk>
Scott Cotton <scott@chronis.pobox.com>
Lloyd Zusman <ljz@asfast.com>
Phil Mayes <pmayes@olivebr.com>
Piers Lauder <piers@cs.su.oz.au>
Radovan Garabik <garabik@melkor.dnp.fmph.uniba.sk>
""" """


ident = "$Id$" ident = "$Id$"


import string, socket, select, errno
import string
import socket
import select
import errno


WSAEINVAL = getattr(errno, 'WSAEINVAL', 10022) WSAEINVAL = getattr(errno, 'WSAEINVAL', 10022)


@@ -46,7 +49,7 @@ class TimeoutSocket:
apply(sock.connect, addr) apply(sock.connect, addr)
sock.setblocking(timeout != 0) sock.setblocking(timeout != 0)
return 1 return 1
except socket.error,why:
except socket.error, why:
if not timeout: if not timeout:
raise raise
sock.setblocking(1) sock.setblocking(1)
@@ -58,12 +61,12 @@ class TimeoutSocket:
errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK
): ):
raise raise
r,w,e = select.select([],[sock],[],timeout)
r, w, e = select.select([], [sock], [], timeout)
if w: if w:
try: try:
apply(sock.connect, addr) apply(sock.connect, addr)
return 1 return 1
except socket.error,why:
except socket.error, why:
if len(why.args) == 1: if len(why.args) == 1:
code = 0 code = 0
else: else:
@@ -77,7 +80,7 @@ class TimeoutSocket:
total = len(data) total = len(data)
next = 0 next = 0
while 1: while 1:
r, w, e = select.select([],[self.sock], [], self.timeout)
r, w, e = select.select([], [self.sock], [], self.timeout)
if w: if w:
buff = data[next:next + 8192] buff = data[next:next + 8192]
sent = self.sock.send(buff, flags) sent = self.sock.send(buff, flags)
@@ -119,7 +122,8 @@ class TimeoutSocket:
self._rbuf = "" self._rbuf = ""
while n > 0: while n > 0:
new = self.recv(max(n, self.buffsize)) new = self.recv(max(n, self.buffsize))
if not new: break
if not new:
break
k = len(new) k = len(new)
if k > n: if k > n:
L.append(new[:n]) L.append(new[:n])
@@ -133,9 +137,10 @@ class TimeoutSocket:
self._rbuf = "" self._rbuf = ""
while 1: while 1:
new = self.recv(k) new = self.recv(k)
if not new: break
if not new:
break
L.append(new) L.append(new)
k = min(k*2, 1024**2)
k = min(k * 2, 1024 ** 2)
return "".join(L) return "".join(L)


def readline(self, limit=-1): def readline(self, limit=-1):
@@ -143,22 +148,28 @@ class TimeoutSocket:
i = self._rbuf.find('\n') i = self._rbuf.find('\n')
while i < 0 and not (0 < limit <= len(self._rbuf)): while i < 0 and not (0 < limit <= len(self._rbuf)):
new = self.recv(self.buffsize) new = self.recv(self.buffsize)
if not new: break
if not new:
break
i = new.find('\n') i = new.find('\n')
if i >= 0: i = i + len(self._rbuf)
if i >= 0:
i = i + len(self._rbuf)
self._rbuf = self._rbuf + new self._rbuf = self._rbuf + new
if i < 0: i = len(self._rbuf)
else: i = i+1
if 0 <= limit < len(self._rbuf): i = limit
if i < 0:
i = len(self._rbuf)
else:
i = i + 1
if 0 <= limit < len(self._rbuf):
i = limit
data, self._rbuf = self._rbuf[:i], self._rbuf[i:] data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
return data return data


def readlines(self, sizehint = 0):
def readlines(self, sizehint=0):
total = 0 total = 0
list = [] list = []
while 1: while 1:
line = self.readline() line = self.readline()
if not line: break
if not line:
break
list.append(line) list.append(line)
total += len(line) total += len(line)
if sizehint and total >= sizehint: if sizehint and total >= sizehint:


+ 43
- 20
src/wstools/UserTuple.py View File

@@ -8,7 +8,7 @@ Taken from Stefan Schwarzer's ftputil library, available at






Copyright (C) 1999, Stefan Schwarzer
Copyright (C) 1999, Stefan Schwarzer
All rights reserved. All rights reserved.


Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@@ -42,15 +42,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
""" """






# $Id$ # $Id$

#XXX tuple instances (in Python 2.2) contain also: #XXX tuple instances (in Python 2.2) contain also:
# __class__, __delattr__, __getattribute__, __hash__, __new__, # __class__, __delattr__, __getattribute__, __hash__, __new__,
# __reduce__, __setattr__, __str__ # __reduce__, __setattr__, __str__
# What about these? # What about these?

class UserTuple: class UserTuple:
def __init__(self, inittuple=None): def __init__(self, inittuple=None):
self.data = () self.data = ()
@@ -67,24 +63,51 @@ class UserTuple:
else: else:
# the same applies here; (t is tuple(t)) == 1 # the same applies here; (t is tuple(t)) == 1
self.data = tuple(inittuple) self.data = tuple(inittuple)
def __repr__(self): return repr(self.data)
def __lt__(self, other): return self.data < self.__cast(other)
def __le__(self, other): return self.data <= self.__cast(other)
def __eq__(self, other): return self.data == self.__cast(other)
def __ne__(self, other): return self.data != self.__cast(other)
def __gt__(self, other): return self.data > self.__cast(other)
def __ge__(self, other): return self.data >= self.__cast(other)

def __repr__(self):
return repr(self.data)

def __lt__(self, other):
return self.data < self.__cast(other)

def __le__(self, other):
return self.data <= self.__cast(other)

def __eq__(self, other):
return self.data == self.__cast(other)

def __ne__(self, other):
return self.data != self.__cast(other)

def __gt__(self, other):
return self.data > self.__cast(other)

def __ge__(self, other):
return self.data >= self.__cast(other)

def __cast(self, other): def __cast(self, other):
if isinstance(other, UserTuple): return other.data
else: return other
if isinstance(other, UserTuple):
return other.data
else:
return other

def __cmp__(self, other): def __cmp__(self, other):
return cmp(self.data, self.__cast(other)) return cmp(self.data, self.__cast(other))
def __contains__(self, item): return item in self.data
def __len__(self): return len(self.data)
def __getitem__(self, i): return self.data[i]

def __contains__(self, item):
return item in self.data

def __len__(self):
return len(self.data)

def __getitem__(self, i):
return self.data[i]

def __getslice__(self, i, j): def __getslice__(self, i, j):
i = max(i, 0); j = max(j, 0)
i = max(i, 0)
j = max(j, 0)
return self.__class__(self.data[i:j]) return self.__class__(self.data[i:j])

def __add__(self, other): def __add__(self, other):
if isinstance(other, UserTuple): if isinstance(other, UserTuple):
return self.__class__(self.data + other.data) return self.__class__(self.data + other.data)
@@ -93,7 +116,7 @@ class UserTuple:
else: else:
return self.__class__(self.data + tuple(other)) return self.__class__(self.data + tuple(other))
# dir( () ) contains no __radd__ (at least in Python 2.2) # dir( () ) contains no __radd__ (at least in Python 2.2)

def __mul__(self, n): def __mul__(self, n):
return self.__class__(self.data*n)
return self.__class__(self.data * n)
__rmul__ = __mul__ __rmul__ = __mul__


+ 114
- 111
src/wstools/Utility.py View File

@@ -1,7 +1,8 @@
#!/usr/bin/env python
# Copyright (c) 2003, The Regents of the University of California, # Copyright (c) 2003, The Regents of the University of California,
# through Lawrence Berkeley National Laboratory (subject to receipt of # through Lawrence Berkeley National Laboratory (subject to receipt of
# any required approvals from the U.S. Dept. of Energy). All rights # any required approvals from the U.S. Dept. of Energy). All rights
# reserved.
# reserved.
# #
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
# #
@@ -14,7 +15,12 @@


ident = "$Id$" ident = "$Id$"


import sys, types, httplib, urllib, socket, weakref
import sys
import types
import httplib
import urllib
import socket
import weakref
from os.path import isfile from os.path import isfile
from string import join, strip, split from string import join, strip, split
from UserDict import UserDict from UserDict import UserDict
@@ -48,17 +54,17 @@ try:
except: except:
def SplitQName(qname): def SplitQName(qname):
'''SplitQName(qname) -> (string, string) '''SplitQName(qname) -> (string, string)
Split Qualified Name into a tuple of len 2, consisting
of the prefix and the local name.
Split Qualified Name into a tuple of len 2, consisting
of the prefix and the local name.
(prefix, localName) (prefix, localName)
Special Cases: Special Cases:
xmlns -- (localName, 'xmlns') xmlns -- (localName, 'xmlns')
None -- (None, localName) None -- (None, localName)
''' '''
l = qname.split(':') l = qname.split(':')
if len(l) == 1: if len(l) == 1:
l.insert(0, None) l.insert(0, None)
@@ -77,10 +83,12 @@ basejoin = urllib.basejoin
if sys.version_info[0:2] < (2, 4, 0, 'final', 0)[0:2]: if sys.version_info[0:2] < (2, 4, 0, 'final', 0)[0:2]:
#basejoin = lambda base,url: urllib.basejoin(base,url.lstrip('./')) #basejoin = lambda base,url: urllib.basejoin(base,url.lstrip('./'))
token = './' token = './'
def basejoin(base, url):

def basejoin(base, url):
if url.startswith(token) is True: if url.startswith(token) is True:
return urllib.basejoin(base,url[2:])
return urllib.basejoin(base,url)
return urllib.basejoin(base, url[2:])
return urllib.basejoin(base, url)



class NamespaceError(Exception): class NamespaceError(Exception):
"""Used to indicate a Namespace Error.""" """Used to indicate a Namespace Error."""
@@ -101,7 +109,7 @@ class DOMException(Exception):
class Base: class Base:
"""Base class for instance level Logging""" """Base class for instance level Logging"""
def __init__(self, module=__name__): def __init__(self, module=__name__):
self.logger = logging.getLogger('%s-%s(%s)' %(module, self.__class__, _get_idstr(self)))
self.logger = logging.getLogger('%s-%s(%s)' % (module, self.__class__, _get_idstr(self)))




class HTTPResponse: class HTTPResponse:
@@ -114,6 +122,7 @@ class HTTPResponse:
self.body = response.read() or None self.body = response.read() or None
response.close() response.close()



class TimeoutHTTP(HTTPConnection): class TimeoutHTTP(HTTPConnection):
"""A custom http connection object that supports socket timeout.""" """A custom http connection object that supports socket timeout."""
def __init__(self, host, port=None, timeout=20): def __init__(self, host, port=None, timeout=20):
@@ -151,9 +160,12 @@ def urlopen(url, timeout=20, redirects=None):


if not scheme in ('http', 'https'): if not scheme in ('http', 'https'):
return urllib.urlopen(url) return urllib.urlopen(url)
if params: path = '%s;%s' % (path, params)
if query: path = '%s?%s' % (path, query)
if frag: path = '%s#%s' % (path, frag)
if params:
path = '%s;%s' % (path, params)
if query:
path = '%s?%s' % (path, query)
if frag:
path = '%s#%s' % (path, frag)


if scheme == 'https': if scheme == 'https':
# If ssl is not compiled into Python, you will not get an exception # If ssl is not compiled into Python, you will not get an exception
@@ -163,7 +175,7 @@ def urlopen(url, timeout=20, redirects=None):
import M2Crypto import M2Crypto
except ImportError: except ImportError:
if not hasattr(socket, 'ssl'): if not hasattr(socket, 'ssl'):
raise RuntimeError, 'no built-in SSL Support'
raise RuntimeError('no built-in SSL Support')


conn = TimeoutHTTPS(host, None, timeout) conn = TimeoutHTTPS(host, None, timeout)
else: else:
@@ -193,7 +205,7 @@ def urlopen(url, timeout=20, redirects=None):
location = response.msg.getheader('location') location = response.msg.getheader('location')
if location is not None: if location is not None:
response.close() response.close()
if redirects is not None and redirects.has_key(location):
if redirects is not None and location in redirects:
raise RecursionError( raise RecursionError(
'Circular HTTP redirection detected.' 'Circular HTTP redirection detected.'
) )
@@ -210,14 +222,15 @@ def urlopen(url, timeout=20, redirects=None):
response.close() response.close()
return body return body



class DOM: class DOM:
"""The DOM singleton defines a number of XML related constants and """The DOM singleton defines a number of XML related constants and
provides a number of utility methods for DOM related tasks. It provides a number of utility methods for DOM related tasks. It
also provides some basic abstractions so that the rest of the also provides some basic abstractions so that the rest of the
package need not care about actual DOM implementation in use.""" package need not care about actual DOM implementation in use."""


looseNamespaces = False # if can't find a referenced namespace, try the default one
looseNamespaces = False # if can't find a referenced namespace, try the default one
# Namespace stuff related to the SOAP specification. # Namespace stuff related to the SOAP specification.


NS_SOAP_ENV_1_1 = 'http://schemas.xmlsoap.org/soap/envelope/' NS_SOAP_ENV_1_1 = 'http://schemas.xmlsoap.org/soap/envelope/'
@@ -233,14 +246,14 @@ class DOM:
NS_SOAP_ENC = NS_SOAP_ENC_1_1 NS_SOAP_ENC = NS_SOAP_ENC_1_1


_soap_uri_mapping = { _soap_uri_mapping = {
NS_SOAP_ENV_1_1 : '1.1',
NS_SOAP_ENV_1_2 : '1.2',
NS_SOAP_ENV_1_1: '1.1',
NS_SOAP_ENV_1_2: '1.2',
} }


SOAP_ACTOR_NEXT_1_1 = 'http://schemas.xmlsoap.org/soap/actor/next' SOAP_ACTOR_NEXT_1_1 = 'http://schemas.xmlsoap.org/soap/actor/next'
SOAP_ACTOR_NEXT_1_2 = 'http://www.w3.org/2001/06/soap-envelope/actor/next' SOAP_ACTOR_NEXT_1_2 = 'http://www.w3.org/2001/06/soap-envelope/actor/next'
SOAP_ACTOR_NEXT_ALL = (SOAP_ACTOR_NEXT_1_1, SOAP_ACTOR_NEXT_1_2) SOAP_ACTOR_NEXT_ALL = (SOAP_ACTOR_NEXT_1_1, SOAP_ACTOR_NEXT_1_2)
def SOAPUriToVersion(self, uri): def SOAPUriToVersion(self, uri):
"""Return the SOAP version related to an envelope uri.""" """Return the SOAP version related to an envelope uri."""
value = self._soap_uri_mapping.get(uri) value = self._soap_uri_mapping.get(uri)
@@ -283,14 +296,12 @@ class DOM:
'Unsupported SOAP version: %s' % version 'Unsupported SOAP version: %s' % version
) )



# Namespace stuff related to XML Schema. # Namespace stuff related to XML Schema.

NS_XSD_99 = 'http://www.w3.org/1999/XMLSchema' NS_XSD_99 = 'http://www.w3.org/1999/XMLSchema'
NS_XSI_99 = 'http://www.w3.org/1999/XMLSchema-instance'
NS_XSI_99 = 'http://www.w3.org/1999/XMLSchema-instance'


NS_XSD_00 = 'http://www.w3.org/2000/10/XMLSchema' NS_XSD_00 = 'http://www.w3.org/2000/10/XMLSchema'
NS_XSI_00 = 'http://www.w3.org/2000/10/XMLSchema-instance'
NS_XSI_00 = 'http://www.w3.org/2000/10/XMLSchema-instance'


NS_XSD_01 = 'http://www.w3.org/2001/XMLSchema' NS_XSD_01 = 'http://www.w3.org/2001/XMLSchema'
NS_XSI_01 = 'http://www.w3.org/2001/XMLSchema-instance' NS_XSI_01 = 'http://www.w3.org/2001/XMLSchema-instance'
@@ -302,15 +313,14 @@ class DOM:
NS_XSI = NS_XSI_01 NS_XSI = NS_XSI_01


_xsd_uri_mapping = { _xsd_uri_mapping = {
NS_XSD_99 : NS_XSI_99,
NS_XSD_00 : NS_XSI_00,
NS_XSD_01 : NS_XSI_01,
NS_XSD_99: NS_XSI_99,
NS_XSD_00: NS_XSI_00,
NS_XSD_01: NS_XSI_01,
} }


for key, value in _xsd_uri_mapping.items(): for key, value in _xsd_uri_mapping.items():
_xsd_uri_mapping[value] = key _xsd_uri_mapping[value] = key



def InstanceUriForSchemaUri(self, uri): def InstanceUriForSchemaUri(self, uri):
"""Return the appropriate matching XML Schema instance uri for """Return the appropriate matching XML Schema instance uri for
the given XML Schema namespace uri.""" the given XML Schema namespace uri."""
@@ -321,9 +331,7 @@ class DOM:
the given XML Schema instance namespace uri.""" the given XML Schema instance namespace uri."""
return self._xsd_uri_mapping.get(uri) return self._xsd_uri_mapping.get(uri)



# Namespace stuff related to WSDL. # Namespace stuff related to WSDL.

NS_WSDL_1_1 = 'http://schemas.xmlsoap.org/wsdl/' NS_WSDL_1_1 = 'http://schemas.xmlsoap.org/wsdl/'
NS_WSDL_ALL = (NS_WSDL_1_1,) NS_WSDL_ALL = (NS_WSDL_1_1,)
NS_WSDL = NS_WSDL_1_1 NS_WSDL = NS_WSDL_1_1
@@ -343,12 +351,11 @@ class DOM:
NS_SOAP_HTTP_1_1 = 'http://schemas.xmlsoap.org/soap/http' NS_SOAP_HTTP_1_1 = 'http://schemas.xmlsoap.org/soap/http'
NS_SOAP_HTTP_ALL = (NS_SOAP_HTTP_1_1,) NS_SOAP_HTTP_ALL = (NS_SOAP_HTTP_1_1,)
NS_SOAP_HTTP = NS_SOAP_HTTP_1_1 NS_SOAP_HTTP = NS_SOAP_HTTP_1_1


_wsdl_uri_mapping = { _wsdl_uri_mapping = {
NS_WSDL_1_1 : '1.1',
NS_WSDL_1_1: '1.1',
} }
def WSDLUriToVersion(self, uri): def WSDLUriToVersion(self, uri):
"""Return the WSDL version related to a WSDL namespace uri.""" """Return the WSDL version related to a WSDL namespace uri."""
value = self._wsdl_uri_mapping.get(uri) value = self._wsdl_uri_mapping.get(uri)
@@ -403,11 +410,8 @@ class DOM:
'Unsupported WSDL version: %s' % version 'Unsupported WSDL version: %s' % version
) )



# Other xml namespace constants. # Other xml namespace constants.
NS_XMLNS = 'http://www.w3.org/2000/xmlns/'


NS_XMLNS = 'http://www.w3.org/2000/xmlns/'


def isElement(self, node, name, nsuri=None): def isElement(self, node, name, nsuri=None):
"""Return true if the given node is an element with the given """Return true if the given node is an element with the given
@@ -430,7 +434,7 @@ class DOM:
return child return child
if default is not join: if default is not join:
return default return default
raise KeyError, name
raise KeyError(name)


def getElementById(self, node, id, default=join): def getElementById(self, node, id, default=join):
"""Return the first child of node matching an id reference.""" """Return the first child of node matching an id reference."""
@@ -442,7 +446,7 @@ class DOM:
return child return child
if default is not join: if default is not join:
return default return default
raise KeyError, name
raise KeyError(name)


def getMappingById(self, document, depth=None, element=None, def getMappingById(self, document, depth=None, element=None,
mapping=None, level=1): mapping=None, level=1):
@@ -461,7 +465,7 @@ class DOM:
for child in element.childNodes: for child in element.childNodes:
if child.nodeType == ELEMENT_NODE: if child.nodeType == ELEMENT_NODE:
self.getMappingById(None, depth, child, mapping, level) self.getMappingById(None, depth, child, mapping, level)
return mapping
return mapping


def getElements(self, node, name, nsuri=None): def getElements(self, node, name, nsuri=None):
"""Return a sequence of the child elements of the given node that """Return a sequence of the child elements of the given node that
@@ -507,10 +511,10 @@ class DOM:
return '' return ''


def getAttrs(self, node): def getAttrs(self, node):
"""Return a Collection of all attributes
"""Return a Collection of all attributes
""" """
attrs = {} attrs = {}
for k,v in node._attrs.items():
for k, v in node._attrs.items():
attrs[k] = v.value attrs[k] = v.value
return attrs return attrs


@@ -647,11 +651,11 @@ class DOM:
else: else:
file = urlopen(url) file = urlopen(url)


try:
try:
result = self.loadDocument(file) result = self.loadDocument(file)
except Exception, ex: except Exception, ex:
file.close() file.close()
raise ParseError(('Failed to load document %s' %url,) + ex.args)
raise ParseError(('Failed to load document %s' % url,) + ex.args)
else: else:
file.close() file.close()
return result return result
@@ -660,7 +664,7 @@ DOM = DOM()




class MessageInterface: class MessageInterface:
'''Higher Level Interface, delegates to DOM singleton, must
'''Higher Level Interface, delegates to DOM singleton, must
be subclassed and implement all methods that throw NotImplementedError. be subclassed and implement all methods that throw NotImplementedError.
''' '''
def __init__(self, sw): def __init__(self, sw):
@@ -685,39 +689,39 @@ class MessageInterface:
def canonicalize(self): def canonicalize(self):
'''canonicalize the underlying DOM, and return as string. '''canonicalize the underlying DOM, and return as string.
''' '''
raise NotImplementedError, ''
raise NotImplementedError('')


def createDocument(self, namespaceURI=SOAP.ENV, localName='Envelope'): def createDocument(self, namespaceURI=SOAP.ENV, localName='Envelope'):
'''create Document '''create Document
''' '''
raise NotImplementedError, ''
raise NotImplementedError('')


def createAppendElement(self, namespaceURI, localName): def createAppendElement(self, namespaceURI, localName):
'''create and append element(namespaceURI,localName), and return '''create and append element(namespaceURI,localName), and return
the node. the node.
''' '''
raise NotImplementedError, ''
raise NotImplementedError('')


def findNamespaceURI(self, qualifiedName): def findNamespaceURI(self, qualifiedName):
raise NotImplementedError, ''
raise NotImplementedError('')


def resolvePrefix(self, prefix): def resolvePrefix(self, prefix):
raise NotImplementedError, ''
raise NotImplementedError('')


def setAttributeNS(self, namespaceURI, localName, value): def setAttributeNS(self, namespaceURI, localName, value):
'''set attribute (namespaceURI, localName)=value '''set attribute (namespaceURI, localName)=value
''' '''
raise NotImplementedError, ''
raise NotImplementedError('')


def setAttributeType(self, namespaceURI, localName): def setAttributeType(self, namespaceURI, localName):
'''set attribute xsi:type=(namespaceURI, localName) '''set attribute xsi:type=(namespaceURI, localName)
''' '''
raise NotImplementedError, ''
raise NotImplementedError('')


def setNamespaceAttribute(self, namespaceURI, prefix): def setNamespaceAttribute(self, namespaceURI, prefix):
'''set namespace attribute xmlns:prefix=namespaceURI
'''set namespace attribute xmlns:prefix=namespaceURI
''' '''
raise NotImplementedError, ''
raise NotImplementedError('')




class ElementProxy(Base, MessageInterface): class ElementProxy(Base, MessageInterface):
@@ -734,27 +738,27 @@ class ElementProxy(Base, MessageInterface):
_soap_env_nsuri = SOAP.ENV _soap_env_nsuri = SOAP.ENV
_soap_enc_nsuri = SOAP.ENC _soap_enc_nsuri = SOAP.ENC
_zsi_nsuri = ZSI_SCHEMA_URI _zsi_nsuri = ZSI_SCHEMA_URI
_xsd_nsuri = SCHEMA.XSD3
_xsd_nsuri = SCHEMA.XSD3
_xsi_nsuri = SCHEMA.XSI3 _xsi_nsuri = SCHEMA.XSI3
_xml_nsuri = XMLNS.XML _xml_nsuri = XMLNS.XML
_xmlns_nsuri = XMLNS.BASE _xmlns_nsuri = XMLNS.BASE


standard_ns = {\ standard_ns = {\
_xml_prefix:_xml_nsuri,
_xmlns_prefix:_xmlns_nsuri
_xml_prefix: _xml_nsuri,
_xmlns_prefix: _xmlns_nsuri
} }
reserved_ns = {\ reserved_ns = {\
_soap_env_prefix:_soap_env_nsuri,
_soap_enc_prefix:_soap_enc_nsuri,
_zsi_prefix:_zsi_nsuri,
_xsd_prefix:_xsd_nsuri,
_xsi_prefix:_xsi_nsuri,
_soap_env_prefix: _soap_env_nsuri,
_soap_enc_prefix: _soap_enc_nsuri,
_zsi_prefix: _zsi_nsuri,
_xsd_prefix: _xsd_nsuri,
_xsi_prefix: _xsi_nsuri,
} }
name = None name = None
namespaceURI = None namespaceURI = None


def __init__(self, sw, message=None): def __init__(self, sw, message=None):
'''Initialize.
'''Initialize.
sw -- SoapWriter sw -- SoapWriter
''' '''
self._indx = 0 self._indx = 0
@@ -762,7 +766,7 @@ class ElementProxy(Base, MessageInterface):
Base.__init__(self) Base.__init__(self)
self._dom = DOM self._dom = DOM
self.node = None self.node = None
if type(message) in (types.StringType,types.UnicodeType):
if type(message) in (types.StringType, types.UnicodeType):
self.loadFromString(message) self.loadFromString(message)
elif isinstance(message, ElementProxy): elif isinstance(message, ElementProxy):
self.node = message._getNode() self.node = message._getNode()
@@ -783,11 +787,11 @@ class ElementProxy(Base, MessageInterface):
else: else:
context = XPath.Context.Context(self.node, processorNss=processorNss) context = XPath.Context.Context(self.node, processorNss=processorNss)
nodes = expression.evaluate(context) nodes = expression.evaluate(context)
return map(lambda node: ElementProxy(self.sw,node), nodes)
return map(lambda node: ElementProxy(self.sw, node), nodes)


############################################# #############################################
# Methods for checking/setting the # Methods for checking/setting the
# classes (namespaceURI,name) node.
# classes (namespaceURI,name) node.
############################################# #############################################
def checkNode(self, namespaceURI=None, localName=None): def checkNode(self, namespaceURI=None, localName=None):
''' '''
@@ -800,7 +804,7 @@ class ElementProxy(Base, MessageInterface):
if localName and self.node: if localName and self.node:
check = self._dom.isElement(self.node, localName, namespaceURI) check = self._dom.isElement(self.node, localName, namespaceURI)
if not check: if not check:
raise NamespaceError, 'unexpected node type %s, expecting %s' %(self.node, localName)
raise NamespaceError('unexpected node type %s, expecting %s' % (self.node, localName))


def setNode(self, node=None): def setNode(self, node=None):
if node: if node:
@@ -811,12 +815,12 @@ class ElementProxy(Base, MessageInterface):
elif self.node: elif self.node:
node = self._dom.getElement(self.node, self.name, self.namespaceURI, default=None) node = self._dom.getElement(self.node, self.name, self.namespaceURI, default=None)
if not node: if not node:
raise NamespaceError, 'cant find element (%s,%s)' %(self.namespaceURI,self.name)
raise NamespaceError('cant find element (%s, %s)' % (self.namespaceURI, self.name))
self.node = node self.node = node
else: else:
#self.node = self._dom.create(self.node, self.name, self.namespaceURI, default=None) #self.node = self._dom.create(self.node, self.name, self.namespaceURI, default=None)
self.createDocument(self.namespaceURI, localName=self.name, doctype=None) self.createDocument(self.namespaceURI, localName=self.name, doctype=None)
self.checkNode() self.checkNode()


############################################# #############################################
@@ -833,12 +837,12 @@ class ElementProxy(Base, MessageInterface):


def _getUniquePrefix(self): def _getUniquePrefix(self):
'''I guess we need to resolve all potential prefixes '''I guess we need to resolve all potential prefixes
because when the current node is attached it copies the
because when the current node is attached it copies the
namespaces into the parent node. namespaces into the parent node.
''' '''
while 1: while 1:
self._indx += 1 self._indx += 1
prefix = 'ns%d' %self._indx
prefix = 'ns%d' % self._indx
try: try:
self._dom.findNamespaceURI(prefix, self._getNode()) self._dom.findNamespaceURI(prefix, self._getNode())
except DOMException, ex: except DOMException, ex:
@@ -867,7 +871,7 @@ class ElementProxy(Base, MessageInterface):
else: else:
if node.parentNode: if node.parentNode:
return self._getPrefix(node.parentNode, nsuri) return self._getPrefix(node.parentNode, nsuri)
raise NamespaceError, 'namespaceURI "%s" is not defined' %nsuri
raise NamespaceError('namespaceURI "%s" is not defined' % nsuri)


def _appendChild(self, node): def _appendChild(self, node):
''' '''
@@ -875,14 +879,14 @@ class ElementProxy(Base, MessageInterface):
node -- DOM Element Node node -- DOM Element Node
''' '''
if node is None: if node is None:
raise TypeError, 'node is None'
raise TypeError('node is None')
self.node.appendChild(node) self.node.appendChild(node)


def _insertBefore(self, newChild, refChild): def _insertBefore(self, newChild, refChild):
''' '''
Keyword arguments: Keyword arguments:
child -- DOM Element Node to insert child -- DOM Element Node to insert
refChild -- DOM Element Node
refChild -- DOM Element Node
''' '''
self.node.insertBefore(newChild, refChild) self.node.insertBefore(newChild, refChild)


@@ -907,7 +911,7 @@ class ElementProxy(Base, MessageInterface):
try: try:
prefix = self._getPrefix(node=self.node, nsuri=namespaceURI) prefix = self._getPrefix(node=self.node, nsuri=namespaceURI)
except NamespaceError, ex: except NamespaceError, ex:
prefix = self._getUniquePrefix()
prefix = self._getUniquePrefix()
self.setNamespaceAttribute(prefix, namespaceURI) self.setNamespaceAttribute(prefix, namespaceURI)
return prefix return prefix


@@ -943,20 +947,20 @@ class ElementProxy(Base, MessageInterface):
prefix = self._soap_env_prefix prefix = self._soap_env_prefix


if namespaceURI == self.reserved_ns[prefix]: if namespaceURI == self.reserved_ns[prefix]:
qualifiedName = '%s:%s' %(prefix,localName)
qualifiedName = '%s:%s' % (prefix, localName)
elif namespaceURI is localName is None: elif namespaceURI is localName is None:
self.node = self._dom.createDocument(None,None,None)
self.node = self._dom.createDocument(None, None, None)
return return
else: else:
raise KeyError, 'only support creation of document in %s' %self.reserved_ns[prefix]
raise KeyError('only support creation of document in %s' % self.reserved_ns[prefix])


document = self._dom.createDocument(nsuri=namespaceURI, qname=qualifiedName, doctype=doctype) document = self._dom.createDocument(nsuri=namespaceURI, qname=qualifiedName, doctype=doctype)
self.node = document.childNodes[0] self.node = document.childNodes[0]


#set up reserved namespace attributes #set up reserved namespace attributes
for prefix,nsuri in self.reserved_ns.items():
self._setAttributeNS(namespaceURI=self._xmlns_nsuri,
qualifiedName='%s:%s' %(self._xmlns_prefix,prefix),
for prefix, nsuri in self.reserved_ns.items():
self._setAttributeNS(namespaceURI=self._xmlns_nsuri,
qualifiedName='%s:%s' % (self._xmlns_prefix, prefix),
value=nsuri) value=nsuri)


############################################# #############################################
@@ -975,10 +979,10 @@ class ElementProxy(Base, MessageInterface):
self.logger.debug('setAttributeType: (%s,%s)', namespaceURI, localName) self.logger.debug('setAttributeType: (%s,%s)', namespaceURI, localName)
value = localName value = localName
if namespaceURI: if namespaceURI:
value = '%s:%s' %(self.getPrefix(namespaceURI),localName)
value = '%s:%s' % (self.getPrefix(namespaceURI), localName)


xsi_prefix = self.getPrefix(self._xsi_nsuri) xsi_prefix = self.getPrefix(self._xsi_nsuri)
self._setAttributeNS(self._xsi_nsuri, '%s:type' %xsi_prefix, value)
self._setAttributeNS(self._xsi_nsuri, '%s:type' % xsi_prefix, value)


def createAttributeNS(self, namespace, name, value): def createAttributeNS(self, namespace, name, value):
document = self._getOwnerDocument() document = self._getOwnerDocument()
@@ -992,7 +996,7 @@ class ElementProxy(Base, MessageInterface):
attributes in no namespace. attributes in no namespace.
localName -- local name of new attribute localName -- local name of new attribute
value -- value of new attribute value -- value of new attribute
'''
'''
prefix = None prefix = None
if namespaceURI: if namespaceURI:
try: try:
@@ -1002,7 +1006,7 @@ class ElementProxy(Base, MessageInterface):
self.setNamespaceAttribute(prefix, namespaceURI) self.setNamespaceAttribute(prefix, namespaceURI)
qualifiedName = localName qualifiedName = localName
if prefix: if prefix:
qualifiedName = '%s:%s' %(prefix, localName)
qualifiedName = '%s:%s' % (prefix, localName)
self._setAttributeNS(namespaceURI, qualifiedName, value) self._setAttributeNS(namespaceURI, qualifiedName, value)


def setNamespaceAttribute(self, prefix, namespaceURI): def setNamespaceAttribute(self, prefix, namespaceURI):
@@ -1011,7 +1015,7 @@ class ElementProxy(Base, MessageInterface):
prefix -- xmlns prefix prefix -- xmlns prefix
namespaceURI -- value of prefix namespaceURI -- value of prefix
''' '''
self._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI)
self._setAttributeNS(XMLNS.BASE, 'xmlns:%s' % prefix, namespaceURI)


############################################# #############################################
#Methods for elements #Methods for elements
@@ -1036,7 +1040,7 @@ class ElementProxy(Base, MessageInterface):
to 'ns1' if left unspecified. to 'ns1' if left unspecified.
''' '''
node = self.createAppendElement(namespaceURI, localName, prefix=None) node = self.createAppendElement(namespaceURI, localName, prefix=None)
node=node._getNode()
node = node._getNode()
self._setNode(node._getNode()) self._setNode(node._getNode())


def createAppendElement(self, namespaceURI, localName, prefix=None): def createAppendElement(self, namespaceURI, localName, prefix=None):
@@ -1056,19 +1060,19 @@ class ElementProxy(Base, MessageInterface):
except: except:
declare = True declare = True
prefix = prefix or self._getUniquePrefix() prefix = prefix or self._getUniquePrefix()
if prefix:
qualifiedName = '%s:%s' %(prefix, localName)
if prefix:
qualifiedName = '%s:%s' % (prefix, localName)
node = self.createElementNS(namespaceURI, qualifiedName) node = self.createElementNS(namespaceURI, qualifiedName)
if declare: if declare:
node._setAttributeNS(XMLNS.BASE, 'xmlns:%s' %prefix, namespaceURI)
node._setAttributeNS(XMLNS.BASE, 'xmlns:%s' % prefix, namespaceURI)
self._appendChild(node=node._getNode()) self._appendChild(node=node._getNode())
return node return node


def createInsertBefore(self, namespaceURI, localName, refChild): def createInsertBefore(self, namespaceURI, localName, refChild):
qualifiedName = localName qualifiedName = localName
prefix = self.getPrefix(namespaceURI) prefix = self.getPrefix(namespaceURI)
if prefix:
qualifiedName = '%s:%s' %(prefix, localName)
if prefix:
qualifiedName = '%s:%s' % (prefix, localName)
node = self.createElementNS(namespaceURI, qualifiedName) node = self.createElementNS(namespaceURI, qualifiedName)
self._insertBefore(newChild=node._getNode(), refChild=refChild._getNode()) self._insertBefore(newChild=node._getNode(), refChild=refChild._getNode())
return node return node
@@ -1091,12 +1095,12 @@ class ElementProxy(Base, MessageInterface):
localName -- local name of attribute localName -- local name of attribute
''' '''
if self.hasAttribute(namespaceURI, localName): if self.hasAttribute(namespaceURI, localName):
attr = self.node.getAttributeNodeNS(namespaceURI,localName)
attr = self.node.getAttributeNodeNS(namespaceURI, localName)
return attr.value return attr.value
return None return None


def getValue(self): def getValue(self):
return self._dom.getElementText(self.node, preserve_ws=True)
return self._dom.getElementText(self.node, preserve_ws=True)


############################################# #############################################
#Methods for text nodes #Methods for text nodes
@@ -1132,10 +1136,10 @@ class ElementProxy(Base, MessageInterface):
return not self.node return not self.node





class Collection(UserDict): class Collection(UserDict):
"""Helper class for maintaining ordered named collections.""" """Helper class for maintaining ordered named collections."""
default = lambda self,k: k.name
default = lambda self, k: k.name

def __init__(self, parent, key=None): def __init__(self, parent, key=None):
UserDict.__init__(self) UserDict.__init__(self)
self.parent = weakref.ref(parent) self.parent = weakref.ref(parent)
@@ -1143,7 +1147,8 @@ class Collection(UserDict):
self._func = key or self.default self._func = key or self.default


def __getitem__(self, key): def __getitem__(self, key):
if type(key) is type(1):
NumberTypes = (types.IntType, types.LongType, types.FloatType, types.ComplexType)
if isinstance(key, NumberTypes):
return self.list[key] return self.list[key]
return self.data[key] return self.data[key]


@@ -1164,7 +1169,8 @@ class Collection(UserDict):


class CollectionNS(UserDict): class CollectionNS(UserDict):
"""Helper class for maintaining ordered named collections.""" """Helper class for maintaining ordered named collections."""
default = lambda self,k: k.name
default = lambda self, k: k.name

def __init__(self, parent, key=None): def __init__(self, parent, key=None):
UserDict.__init__(self) UserDict.__init__(self)
self.parent = weakref.ref(parent) self.parent = weakref.ref(parent)
@@ -1174,10 +1180,10 @@ class CollectionNS(UserDict):


def __getitem__(self, key): def __getitem__(self, key):
self.targetNamespace = self.parent().targetNamespace self.targetNamespace = self.parent().targetNamespace
if type(key) is types.IntType:
if isinstance(key, types.IntType):
return self.list[key] return self.list[key]
elif self.__isSequence(key): elif self.__isSequence(key):
nsuri,name = key
nsuri, name = key
return self.data[nsuri][name] return self.data[nsuri][name]
return self.data[self.parent().targetNamespace][key] return self.data[self.parent().targetNamespace][key]


@@ -1185,17 +1191,17 @@ class CollectionNS(UserDict):
item.parent = weakref.ref(self) item.parent = weakref.ref(self)
self.list.append(item) self.list.append(item)
targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace) targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace)
if not self.data.has_key(targetNamespace):
if not targetNamespace in self.data:
self.data[targetNamespace] = {} self.data[targetNamespace] = {}
self.data[targetNamespace][key] = item self.data[targetNamespace][key] = item


def __isSequence(self, key): def __isSequence(self, key):
return (type(key) in (types.TupleType,types.ListType) and len(key) == 2)
return (type(key) in (types.TupleType, types.ListType) and len(key) == 2)


def keys(self): def keys(self):
keys = [] keys = []
for tns in self.data.keys(): for tns in self.data.keys():
keys.append(map(lambda i: (tns,self._func(i)), self.data[tns].values()))
keys.append(map(lambda i: (tns, self._func(i)), self.data[tns].values()))
return keys return keys


def items(self): def items(self):
@@ -1205,12 +1211,10 @@ class CollectionNS(UserDict):
return self.list return self.list





# This is a runtime guerilla patch for pulldom (used by minidom) so # This is a runtime guerilla patch for pulldom (used by minidom) so
# that xml namespace declaration attributes are not lost in parsing. # that xml namespace declaration attributes are not lost in parsing.
# We need them to do correct QName linking for XML Schema and WSDL. # We need them to do correct QName linking for XML Schema and WSDL.
# The patch has been submitted to SF for the next Python version. # The patch has been submitted to SF for the next Python version.

from xml.dom.pulldom import PullDOM, START_ELEMENT from xml.dom.pulldom import PullDOM, START_ELEMENT
if 1: if 1:
def startPrefixMapping(self, prefix, uri): def startPrefixMapping(self, prefix, uri):
@@ -1222,7 +1226,7 @@ if 1:


PullDOM.startPrefixMapping = startPrefixMapping PullDOM.startPrefixMapping = startPrefixMapping


def startElementNS(self, name, tagName , attrs):
def startElementNS(self, name, tagName, attrs):
# Retrieve xml namespace declaration attributes. # Retrieve xml namespace declaration attributes.
xmlns_uri = 'http://www.w3.org/2000/xmlns/' xmlns_uri = 'http://www.w3.org/2000/xmlns/'
xmlns_attrs = getattr(self, '_xmlns_attrs', None) xmlns_attrs = getattr(self, '_xmlns_attrs', None)
@@ -1253,7 +1257,7 @@ if 1:
else: else:
node = self.buildDocument(None, localname) node = self.buildDocument(None, localname)


for aname,value in attrs.items():
for aname, value in attrs.items():
a_uri, a_localname = aname a_uri, a_localname = aname
if a_uri == xmlns_uri: if a_uri == xmlns_uri:
if a_localname == 'xmlns': if a_localname == 'xmlns':
@@ -1294,7 +1298,7 @@ if 1:
# ('http://www.w3.org/2000/xmlns/', 'xmlns') <xml.dom.minidom.Attr instance at 0x8414b3c> # ('http://www.w3.org/2000/xmlns/', 'xmlns') <xml.dom.minidom.Attr instance at 0x8414b3c>
# #
# xml.dom.minidom.Attr.nodeName = xmlns:xsd # xml.dom.minidom.Attr.nodeName = xmlns:xsd
# xml.dom.minidom.Attr.value = = http://www.w3.org/2001/XMLSchema
# xml.dom.minidom.Attr.value = = http://www.w3.org/2001/XMLSchema


if 1: if 1:
def _clone_node(node, deep, newOwnerDocument): def _clone_node(node, deep, newOwnerDocument):
@@ -1385,4 +1389,3 @@ if 1:
return clone return clone


xml.dom.minidom._clone_node = _clone_node xml.dom.minidom._clone_node = _clone_node


+ 114
- 93
src/wstools/WSDLTools.py View File

@@ -20,7 +20,7 @@ class WSDLReader:
"""A WSDLReader creates WSDL instances from urls and xml data.""" """A WSDLReader creates WSDL instances from urls and xml data."""


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


def loadFromStream(self, stream, name=None): def loadFromStream(self, stream, name=None):
@@ -55,6 +55,7 @@ class WSDLReader:
file.close() file.close()
return wsdl return wsdl



class WSDL: class WSDL:
"""A WSDL object models a WSDL service description. WSDL objects """A WSDL object models a WSDL service description. WSDL objects
may be created manually or loaded from an xml representation may be created manually or loaded from an xml representation
@@ -82,7 +83,7 @@ class WSDL:
version = '1.1' version = '1.1'


def addService(self, name, documentation='', targetNamespace=None): def addService(self, name, documentation='', targetNamespace=None):
if self.services.has_key(name):
if name in self.services:
raise WSDLError( raise WSDLError(
'Duplicate service element: %s' % name 'Duplicate service element: %s' % name
) )
@@ -93,7 +94,7 @@ class WSDL:
return item return item


def addMessage(self, name, documentation='', targetNamespace=None): def addMessage(self, name, documentation='', targetNamespace=None):
if self.messages.has_key(name):
if name in self.messages:
raise WSDLError( raise WSDLError(
'Duplicate message element: %s.' % name 'Duplicate message element: %s.' % name
) )
@@ -104,7 +105,7 @@ class WSDL:
return item return item


def addPortType(self, name, documentation='', targetNamespace=None): def addPortType(self, name, documentation='', targetNamespace=None):
if self.portTypes.has_key(name):
if name in self.portTypes:
raise WSDLError( raise WSDLError(
'Duplicate portType element: name' 'Duplicate portType element: name'
) )
@@ -115,7 +116,7 @@ class WSDL:
return item return item


def addBinding(self, name, type, documentation='', targetNamespace=None): def addBinding(self, name, type, documentation='', targetNamespace=None):
if self.bindings.has_key(name):
if name in self.bindings:
raise WSDLError( raise WSDLError(
'Duplicate binding element: %s' % name 'Duplicate binding element: %s' % name
) )
@@ -133,11 +134,11 @@ class WSDL:
def toDom(self): def toDom(self):
""" Generate a DOM representation of the WSDL instance. """ Generate a DOM representation of the WSDL instance.
Not dealing with generating XML Schema, thus the targetNamespace Not dealing with generating XML Schema, thus the targetNamespace
of all XML Schema elements or types used by WSDL message parts
of all XML Schema elements or types used by WSDL message parts
needs to be specified via import information items. needs to be specified via import information items.
""" """
namespaceURI = DOM.GetWSDLUri(self.version) namespaceURI = DOM.GetWSDLUri(self.version)
self.document = DOM.createDocument(namespaceURI ,'wsdl:definitions')
self.document = DOM.createDocument(namespaceURI, 'wsdl:definitions')


# Set up a couple prefixes for easy reading. # Set up a couple prefixes for easy reading.
child = DOM.getElement(self.document, None) child = DOM.getElement(self.document, None)
@@ -146,12 +147,12 @@ class WSDL:
child.setAttributeNS(XMLNS.BASE, 'xmlns:xsd', 'http://www.w3.org/1999/XMLSchema') child.setAttributeNS(XMLNS.BASE, 'xmlns:xsd', 'http://www.w3.org/1999/XMLSchema')
child.setAttributeNS(XMLNS.BASE, 'xmlns:soap', 'http://schemas.xmlsoap.org/wsdl/soap/') child.setAttributeNS(XMLNS.BASE, 'xmlns:soap', 'http://schemas.xmlsoap.org/wsdl/soap/')
child.setAttributeNS(XMLNS.BASE, 'xmlns:tns', self.targetNamespace) child.setAttributeNS(XMLNS.BASE, 'xmlns:tns', self.targetNamespace)
if self.name: if self.name:
child.setAttributeNS(None, 'name', self.name) child.setAttributeNS(None, 'name', self.name)


# wsdl:import # wsdl:import
for item in self.imports:
for item in self.imports:
item.toDom() item.toDom()
# wsdl:message # wsdl:message
for item in self.messages: for item in self.messages:
@@ -186,13 +187,13 @@ class WSDL:
self.name = DOM.getAttr(definitions, 'name', None, None) self.name = DOM.getAttr(definitions, 'name', None, None)
self.documentation = GetDocumentation(definitions) self.documentation = GetDocumentation(definitions)


#
#
# Retrieve all <wsdl:import>'s, append all children of imported # Retrieve all <wsdl:import>'s, append all children of imported
# document to main document. First iteration grab all original
# <wsdl:import>'s from document, second iteration grab all
# "imported" <wsdl:imports> from document, etc break out when
# document to main document. First iteration grab all original
# <wsdl:import>'s from document, second iteration grab all
# "imported" <wsdl:imports> from document, etc break out when
# no more <wsdl:import>'s. # no more <wsdl:import>'s.
#
#
imported = [] imported = []
base_location = self.location base_location = self.location
do_it = True do_it = True
@@ -203,7 +204,7 @@ class WSDL:


if base_location is not None: if base_location is not None:
location = basejoin(base_location, location) location = basejoin(base_location, location)
if location not in imported: if location not in imported:
do_it = True do_it = True
self._import(document, element, base_location) self._import(document, element, base_location)
@@ -213,10 +214,10 @@ class WSDL:


base_location = None base_location = None


#
# No more <wsdl:import>'s, now load up all other
#
# No more <wsdl:import>'s, now load up all other
# WSDL information items. # WSDL information items.
#
#
for element in DOM.getElements(definitions, None, None): for element in DOM.getElements(definitions, None, None):
targetNamespace = DOM.getAttr(element, 'targetNamespace') targetNamespace = DOM.getAttr(element, 'targetNamespace')
localName = element.localName localName = element.localName
@@ -296,15 +297,15 @@ class WSDL:


def _import(self, document, element, base_location=None): def _import(self, document, element, base_location=None):
'''Algo take <import> element's children, clone them, '''Algo take <import> element's children, clone them,
and add them to the main document. Support for relative
and add them to the main document. Support for relative
locations is a bit complicated. The orig document context locations is a bit complicated. The orig document context
is lost, so we need to store base location in DOM elements is lost, so we need to store base location in DOM elements
representing <types>, by creating a special temporary
representing <types>, by creating a special temporary
"base-location" attribute, and <import>, by resolving "base-location" attribute, and <import>, by resolving
the relative "location" and storing it as "location". the relative "location" and storing it as "location".
document -- document we are loading document -- document we are loading
element -- DOM Element representing <import>
element -- DOM Element representing <import>
base_location -- location of document from which this base_location -- location of document from which this
<import> was gleaned. <import> was gleaned.
''' '''
@@ -344,7 +345,7 @@ class WSDL:
parent = element.parentNode parent = element.parentNode


parent.removeChild(element) parent.removeChild(element)
for node in imported_nodes: for node in imported_nodes:
if node.nodeType != node.ELEMENT_NODE: if node.nodeType != node.ELEMENT_NODE:
continue continue
@@ -369,6 +370,7 @@ class WSDL:
importdoc.unlink() importdoc.unlink()
return location return location



class Element: class Element:
"""A class that provides common functions for WSDL element classes.""" """A class that provides common functions for WSDL element classes."""
def __init__(self, name=None, documentation=''): def __init__(self, name=None, documentation=''):
@@ -379,7 +381,7 @@ class Element:
def addExtension(self, item): def addExtension(self, item):
item.parent = weakref.ref(self) item.parent = weakref.ref(self)
self.extensions.append(item) self.extensions.append(item)
def getWSDL(self): def getWSDL(self):
"""Return the WSDL object that contains this information item.""" """Return the WSDL object that contains this information item."""
parent = self parent = self
@@ -387,9 +389,11 @@ class Element:
# skip any collections # skip any collections
if isinstance(parent, WSDL): if isinstance(parent, WSDL):
return parent return parent
try: parent = parent.parent()
except: break
try:
parent = parent.parent()
except:
break

return None return None




@@ -413,7 +417,8 @@ class ImportElement(Element):




class Types(Collection): class Types(Collection):
default = lambda self,k: k.targetNamespace
default = lambda self, k: k.targetNamespace

def __init__(self, parent): def __init__(self, parent):
Collection.__init__(self, parent) Collection.__init__(self, parent)
self.documentation = '' self.documentation = ''
@@ -434,7 +439,7 @@ class Message(Element):
self.parts = Collection(self) self.parts = Collection(self)


def addPart(self, name, type=None, element=None): def addPart(self, name, type=None, element=None):
if self.parts.has_key(name):
if name in self.parts:
raise WSDLError( raise WSDLError(
'Duplicate message part element: %s' % name 'Duplicate message part element: %s' % name
) )
@@ -510,13 +515,13 @@ class MessagePart(Element):


def getTypeDefinition(self): def getTypeDefinition(self):
wsdl = self.getWSDL() wsdl = self.getWSDL()
nsuri,name = self.type
nsuri, name = self.type
schema = wsdl.types.get(nsuri, {}) schema = wsdl.types.get(nsuri, {})
return schema.get(name) return schema.get(name)


def getElementDeclaration(self): def getElementDeclaration(self):
wsdl = self.getWSDL() wsdl = self.getWSDL()
nsuri,name = self.element
nsuri, name = self.element
schema = wsdl.types.get(nsuri, {}) schema = wsdl.types.get(nsuri, {})
return schema.get(name) return schema.get(name)


@@ -528,13 +533,13 @@ class MessagePart(Element):
epc.setAttributeNS(None, 'name', self.name) epc.setAttributeNS(None, 'name', self.name)


if self.element is not None: if self.element is not None:
ns,name = self.element
ns, name = self.element
prefix = epc.getPrefix(ns) prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'element', '%s:%s'%(prefix,name))
epc.setAttributeNS(None, 'element', '%s:%s' % (prefix, name))
elif self.type is not None: elif self.type is not None:
ns,name = self.type
ns, name = self.type
prefix = epc.getPrefix(ns) prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'type', '%s:%s'%(prefix,name))
epc.setAttributeNS(None, 'type', '%s:%s' % (prefix, name))




class PortType(Element): class PortType(Element):
@@ -598,7 +603,8 @@ class PortType(Element):
message = ParseQName(msgref, item) message = ParseQName(msgref, item)
for WSA in WSA_LIST + WSAW_LIST: for WSA in WSA_LIST + WSAW_LIST:
action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None) action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None)
if action: break
if action:
break
operation.setInput(message, name, docs, action) operation.setInput(message, name, docs, action)


item = DOM.getElement(element, 'output', None, None) item = DOM.getElement(element, 'output', None, None)
@@ -609,7 +615,8 @@ class PortType(Element):
message = ParseQName(msgref, item) message = ParseQName(msgref, item)
for WSA in WSA_LIST + WSAW_LIST: for WSA in WSA_LIST + WSAW_LIST:
action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None) action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None)
if action: break
if action:
break
operation.setOutput(message, name, docs, action) operation.setOutput(message, name, docs, action)


for item in DOM.getElements(element, 'fault', None): for item in DOM.getElements(element, 'fault', None):
@@ -619,9 +626,10 @@ class PortType(Element):
message = ParseQName(msgref, item) message = ParseQName(msgref, item)
for WSA in WSA_LIST + WSAW_LIST: for WSA in WSA_LIST + WSAW_LIST:
action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None) action = DOM.getAttr(item, 'Action', WSA.ADDRESS, None)
if action: break
if action:
break
operation.addFault(message, name, docs, action) operation.addFault(message, name, docs, action)
def toDom(self): def toDom(self):
wsdl = self.getWSDL() wsdl = self.getWSDL()


@@ -629,16 +637,15 @@ class PortType(Element):
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'portType') epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'portType')
epc.setAttributeNS(None, 'name', self.name) epc.setAttributeNS(None, 'name', self.name)
if self.resourceProperties: if self.resourceProperties:
ns,name = self.resourceProperties
ns, name = self.resourceProperties
prefix = epc.getPrefix(ns) prefix = epc.getPrefix(ns)
epc.setAttributeNS(WSRF.PROPERTIES.LATEST, 'ResourceProperties',
'%s:%s'%(prefix,name))
epc.setAttributeNS(WSRF.PROPERTIES.LATEST, 'ResourceProperties',
'%s:%s' % (prefix, name))


for op in self.operations: for op in self.operations:
op.toDom(epc._getNode()) op.toDom(epc._getNode())





class Operation(Element): class Operation(Element):
def __init__(self, name, documentation='', parameterOrder=None): def __init__(self, name, documentation='', parameterOrder=None):
Element.__init__(self, name, documentation) Element.__init__(self, name, documentation)
@@ -683,7 +690,7 @@ class Operation(Element):
return wsdl.messages[self.faults[name].message] return wsdl.messages[self.faults[name].message]


def addFault(self, message, name, documentation='', action=None): def addFault(self, message, name, documentation='', action=None):
if self.faults.has_key(name):
if name in self.faults:
raise WSDLError( raise WSDLError(
'Duplicate fault element: %s' % name 'Duplicate fault element: %s' % name
) )
@@ -709,11 +716,11 @@ class Operation(Element):
epc.setAttributeNS(None, 'name', self.name) epc.setAttributeNS(None, 'name', self.name)
node = epc._getNode() node = epc._getNode()
if self.input: if self.input:
self.input.toDom(node)
self.input.toDom(node)
if self.output: if self.output:
self.output.toDom(node)
self.output.toDom(node)
for fault in self.faults: for fault in self.faults:
fault.toDom(node)
fault.toDom(node)




class MessageRole(Element): class MessageRole(Element):
@@ -722,7 +729,7 @@ class MessageRole(Element):
self.message = message self.message = message
self.type = type self.type = type
self.action = action self.action = action
def getWSDL(self): def getWSDL(self):
"""Return the WSDL object that contains this information item.""" """Return the WSDL object that contains this information item."""
parent = self parent = self
@@ -730,13 +737,15 @@ class MessageRole(Element):
# skip any collections # skip any collections
if isinstance(parent, WSDL): if isinstance(parent, WSDL):
return parent return parent
try: parent = parent.parent()
except: break
try:
parent = parent.parent()
except:
break

return None return None


def getMessage(self): def getMessage(self):
"""Return the WSDL object that represents the attribute message
"""Return the WSDL object that represents the attribute message
(namespaceURI, name) tuple (namespaceURI, name) tuple
""" """
wsdl = self.getWSDL() wsdl = self.getWSDL()
@@ -748,18 +757,18 @@ class MessageRole(Element):
ep = ElementProxy(None, node) ep = ElementProxy(None, node)
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type) epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), self.type)
if not isinstance(self.message, basestring) and len(self.message) == 2: if not isinstance(self.message, basestring) and len(self.message) == 2:
ns,name = self.message
ns, name = self.message
prefix = epc.getPrefix(ns) prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'message', '%s:%s' %(prefix,name))
epc.setAttributeNS(None, 'message', '%s:%s' % (prefix, name))
else: else:
epc.setAttributeNS(None, 'message', self.message) epc.setAttributeNS(None, 'message', self.message)


if self.action: if self.action:
epc.setAttributeNS(WSA.ADDRESS, 'Action', self.action) epc.setAttributeNS(WSA.ADDRESS, 'Action', self.action)
if self.name: if self.name:
epc.setAttributeNS(None, 'name', self.name) epc.setAttributeNS(None, 'name', self.name)


class Binding(Element): class Binding(Element):
def __init__(self, name, type, documentation=''): def __init__(self, name, type, documentation=''):
@@ -782,7 +791,7 @@ class Binding(Element):
return None return None


def findBindings(self, kind): def findBindings(self, kind):
return [ item for item in self.extensions if isinstance(item, kind) ]
return [item for item in self.extensions if isinstance(item, kind)]


def addOperationBinding(self, name, documentation=''): def addOperationBinding(self, name, documentation=''):
item = OperationBinding(name, documentation) item = OperationBinding(name, documentation)
@@ -844,9 +853,9 @@ class Binding(Element):
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'binding') epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'binding')
epc.setAttributeNS(None, 'name', self.name) epc.setAttributeNS(None, 'name', self.name)


ns,name = self.type
ns, name = self.type
prefix = epc.getPrefix(ns) prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'type', '%s:%s' %(prefix,name))
epc.setAttributeNS(None, 'type', '%s:%s' % (prefix, name))


node = epc._getNode() node = epc._getNode()
for ext in self.extensions: for ext in self.extensions:
@@ -866,7 +875,6 @@ class OperationBinding(Element):
# """Return the WSDL object that contains this binding.""" # """Return the WSDL object that contains this binding."""
# return self.parent().parent().parent().parent() # return self.parent().parent().parent().parent()



def getBinding(self): def getBinding(self):
"""Return the parent Binding object of the operation binding.""" """Return the parent Binding object of the operation binding."""
return self.parent().parent() return self.parent().parent()
@@ -874,7 +882,7 @@ class OperationBinding(Element):
def getOperation(self): def getOperation(self):
"""Return the abstract Operation associated with this binding.""" """Return the abstract Operation associated with this binding."""
return self.getBinding().getPortType().operations[self.name] return self.getBinding().getPortType().operations[self.name]
def findBinding(self, kind): def findBinding(self, kind):
for item in self.extensions: for item in self.extensions:
if isinstance(item, kind): if isinstance(item, kind):
@@ -882,7 +890,7 @@ class OperationBinding(Element):
return None return None


def findBindings(self, kind): def findBindings(self, kind):
return [ item for item in self.extensions if isinstance(item, kind) ]
return [item for item in self.extensions if isinstance(item, kind)]


def addInputBinding(self, binding): def addInputBinding(self, binding):
if self.input is None: if self.input is None:
@@ -951,7 +959,7 @@ class MessageRoleBinding(Element):
return None return None


def findBindings(self, kind): def findBindings(self, kind):
return [ item for item in self.extensions if isinstance(item, kind) ]
return [item for item in self.extensions if isinstance(item, kind)]


def load_ex(self, elements): def load_ex(self, elements):
for e in elements: for e in elements:
@@ -1038,7 +1046,8 @@ class MessageRoleBinding(Element):


node = epc._getNode() node = epc._getNode()
for item in self.extensions: for item in self.extensions:
if item: item.toDom(node)
if item:
item.toDom(node)




class Service(Element): class Service(Element):
@@ -1138,9 +1147,9 @@ class Port(Element):
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "port") epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), "port")
epc.setAttributeNS(None, "name", self.name) epc.setAttributeNS(None, "name", self.name)


ns,name = self.binding
ns, name = self.binding
prefix = epc.getPrefix(ns) prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, "binding", "%s:%s" %(prefix,name))
epc.setAttributeNS(None, "binding", "%s:%s" % (prefix, name))


node = epc._getNode() node = epc._getNode()
for ext in self.extensions: for ext in self.extensions:
@@ -1164,6 +1173,7 @@ class SoapBinding:
if self.style: if self.style:
epc.setAttributeNS(None, "style", self.style) epc.setAttributeNS(None, "style", self.style)



class SoapAddressBinding: class SoapAddressBinding:
def __init__(self, location): def __init__(self, location):
self.location = location self.location = location
@@ -1230,10 +1240,10 @@ class SoapFaultBinding:
self.namespace = namespace self.namespace = namespace
self.name = name self.name = name
self.use = use self.use = use
def getWSDL(self): def getWSDL(self):
return self.parent().getWSDL() return self.parent().getWSDL()
def toDom(self, node): def toDom(self, node):
wsdl = self.getWSDL() wsdl = self.getWSDL()
ep = ElementProxy(None, node) ep = ElementProxy(None, node)
@@ -1260,6 +1270,7 @@ class SoapHeaderBinding:


tagname = 'header' tagname = 'header'



class SoapHeaderFaultBinding(SoapHeaderBinding): class SoapHeaderFaultBinding(SoapHeaderBinding):
tagname = 'headerfault' tagname = 'headerfault'


@@ -1268,6 +1279,7 @@ class HttpBinding:
def __init__(self, verb): def __init__(self, verb):
self.verb = verb self.verb = verb



class HttpAddressBinding: class HttpAddressBinding:
def __init__(self, location): def __init__(self, location):
self.location = location self.location = location
@@ -1277,6 +1289,7 @@ class HttpOperationBinding:
def __init__(self, location): def __init__(self, location):
self.location = location self.location = location



class HttpUrlReplacementBinding: class HttpUrlReplacementBinding:
pass pass


@@ -1346,12 +1359,12 @@ class WSDLError(Exception):
pass pass





def DeclareNSPrefix(writer, prefix, nsuri): def DeclareNSPrefix(writer, prefix, nsuri):
if writer.hasNSPrefix(nsuri): if writer.hasNSPrefix(nsuri):
return return
writer.declareNSPrefix(prefix, nsuri) writer.declareNSPrefix(prefix, nsuri)



def ParseTypeRef(value, element): def ParseTypeRef(value, element):
parts = value.split(':', 1) parts = value.split(':', 1)
if len(parts) == 1: if len(parts) == 1:
@@ -1359,6 +1372,7 @@ def ParseTypeRef(value, element):
nsuri = DOM.findNamespaceURI(parts[0], element) nsuri = DOM.findNamespaceURI(parts[0], element)
return (nsuri, parts[1]) return (nsuri, parts[1])



def ParseQName(value, element): def ParseQName(value, element):
nameref = value.split(':', 1) nameref = value.split(':', 1)
if len(nameref) == 2: if len(nameref) == 2:
@@ -1366,18 +1380,21 @@ def ParseQName(value, element):
name = nameref[-1] name = nameref[-1]
else: else:
nsuri = DOM.findTargetNS(element) nsuri = DOM.findTargetNS(element)
name = nameref[-1]
name = nameref[-1]
return nsuri, name return nsuri, name



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



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



def GetWSAActionFault(operation, name): def GetWSAActionFault(operation, name):
"""Find wsa:Action attribute, and return value or WSA.FAULT """Find wsa:Action attribute, and return value or WSA.FAULT
@@ -1388,6 +1405,7 @@ def GetWSAActionFault(operation, name):
return attr return attr
return WSA.FAULT return WSA.FAULT



def GetWSAActionInput(operation): def GetWSAActionInput(operation):
"""Find wsa:Action attribute, and return value or the default.""" """Find wsa:Action attribute, and return value or the default."""
attr = operation.input.action attr = operation.input.action
@@ -1400,8 +1418,9 @@ def GetWSAActionInput(operation):
if not msgName: if not msgName:
msgName = operation.name + 'Request' msgName = operation.name + 'Request'
if targetNamespace.endswith('/'): if targetNamespace.endswith('/'):
return '%s%s/%s' %(targetNamespace, ptName, msgName)
return '%s/%s/%s' %(targetNamespace, ptName, msgName)
return '%s%s/%s' % (targetNamespace, ptName, msgName)
return '%s/%s/%s' % (targetNamespace, ptName, msgName)



def GetWSAActionOutput(operation): def GetWSAActionOutput(operation):
"""Find wsa:Action attribute, and return value or the default.""" """Find wsa:Action attribute, and return value or the default."""
@@ -1414,26 +1433,28 @@ def GetWSAActionOutput(operation):
if not msgName: if not msgName:
msgName = operation.name + 'Response' msgName = operation.name + 'Response'
if targetNamespace.endswith('/'): if targetNamespace.endswith('/'):
return '%s%s/%s' %(targetNamespace, ptName, msgName)
return '%s/%s/%s' %(targetNamespace, ptName, msgName)
return '%s%s/%s' % (targetNamespace, ptName, msgName)
return '%s/%s/%s' % (targetNamespace, ptName, msgName)



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



def FindExtension(object, kind, t_type=type(())): def FindExtension(object, kind, t_type=type(())):
if isinstance(kind, t_type): if isinstance(kind, t_type):
namespaceURI, name = kind namespaceURI, name = kind
for item in object.extensions: for item in object.extensions:
if hasattr(item, 'nodeType') \ if hasattr(item, 'nodeType') \
and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \
and item.name == name:
and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \
and item.name == name:
return item return item
else: else:
for item in object.extensions: for item in object.extensions:
@@ -1443,7 +1464,7 @@ def FindExtension(object, kind, t_type=type(())):




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


@@ -1557,12 +1578,12 @@ def callInfoFromWSDL(port, name):


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


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


@@ -1579,7 +1600,7 @@ def callInfoFromWSDL(port, name):


mime = msgrole.findBinding(MimeMultipartRelatedBinding) mime = msgrole.findBinding(MimeMultipartRelatedBinding)
if mime is not None: if mime is not None:
raise ValueError, 'Mime bindings are not supported.'
raise ValueError('Mime bindings are not supported.')
else: else:
for item in msgrole.findBindings(SoapHeaderBinding): for item in msgrole.findBindings(SoapHeaderBinding):
part = messages[item.message].parts[item.part] part = messages[item.message].parts[item.part]
@@ -1587,13 +1608,13 @@ def callInfoFromWSDL(port, name):
part.name, part.name,
part.element or part.type, part.element or part.type,
item.namespace, item.namespace,
element_type = part.element and 1 or 0
element_type=part.element and 1 or 0
) )
header.encodingStyle = item.encodingStyle header.encodingStyle = item.encodingStyle


body = msgrole.findBinding(SoapBodyBinding) body = msgrole.findBinding(SoapBodyBinding)
if body is None: if body is None:
raise ValueError, 'Missing soap:body binding.'
raise ValueError('Missing soap:body binding.')
callinfo.encodingStyle = body.encodingStyle callinfo.encodingStyle = body.encodingStyle
callinfo.namespace = body.namespace callinfo.namespace = body.namespace
callinfo.use = body.use callinfo.use = body.use
@@ -1609,7 +1630,7 @@ def callInfoFromWSDL(port, name):
callinfo.addInParameter( callinfo.addInParameter(
part.name, part.name,
part.element or part.type, part.element or part.type,
element_type = part.element and 1 or 0
element_type=part.element and 1 or 0
) )


if operation.output is not None: if operation.output is not None:
@@ -1626,12 +1647,12 @@ def callInfoFromWSDL(port, name):
"Recieved message not defined in the WSDL schema.", \ "Recieved message not defined in the WSDL schema.", \
"Adding it." "Adding it."
print "Message:", operation.output.message print "Message:", operation.output.message
msgrole = opbinding.output msgrole = opbinding.output


mime = msgrole.findBinding(MimeMultipartRelatedBinding) mime = msgrole.findBinding(MimeMultipartRelatedBinding)
if mime is not None: if mime is not None:
raise ValueError, 'Mime bindings are not supported.'
raise ValueError('Mime bindings are not supported.')
else: else:
for item in msgrole.findBindings(SoapHeaderBinding): for item in msgrole.findBindings(SoapHeaderBinding):
part = messages[item.message].parts[item.part] part = messages[item.message].parts[item.part]
@@ -1639,13 +1660,13 @@ def callInfoFromWSDL(port, name):
part.name, part.name,
part.element or part.type, part.element or part.type,
item.namespace, item.namespace,
element_type = part.element and 1 or 0
element_type=part.element and 1 or 0
) )
header.encodingStyle = item.encodingStyle header.encodingStyle = item.encodingStyle


body = msgrole.findBinding(SoapBodyBinding) body = msgrole.findBinding(SoapBodyBinding)
if body is None: if body is None:
raise ValueError, 'Missing soap:body binding.'
raise ValueError('Missing soap:body binding.')
callinfo.encodingStyle = body.encodingStyle callinfo.encodingStyle = body.encodingStyle
callinfo.namespace = body.namespace callinfo.namespace = body.namespace
callinfo.use = body.use callinfo.use = body.use
@@ -1662,7 +1683,7 @@ def callInfoFromWSDL(port, name):
callinfo.addOutParameter( callinfo.addOutParameter(
part.name, part.name,
part.element or part.type, part.element or part.type,
element_type = part.element and 1 or 0
element_type=part.element and 1 or 0
) )


return callinfo return callinfo

+ 499
- 493
src/wstools/XMLSchema.py
File diff suppressed because it is too large
View File


+ 39
- 31
src/wstools/XMLname.py View File

@@ -19,59 +19,68 @@ from re import *




def _NCNameChar(x): def _NCNameChar(x):
return x.isalpha() or x.isdigit() or x=="." or x=='-' or x=="_"
return x.isalpha() or x.isdigit() or x == "." or x == '-' or x == "_"




def _NCNameStartChar(x): def _NCNameStartChar(x):
return x.isalpha() or x=="_"
return x.isalpha() or x == "_"




def _toUnicodeHex(x): def _toUnicodeHex(x):
hexval = hex(ord(x[0]))[2:] hexval = hex(ord(x[0]))[2:]
hexlen = len(hexval) hexlen = len(hexval)
# Make hexval have either 4 or 8 digits by prepending 0's # Make hexval have either 4 or 8 digits by prepending 0's
if (hexlen==1): hexval = "000" + hexval
elif (hexlen==2): hexval = "00" + hexval
elif (hexlen==3): hexval = "0" + hexval
elif (hexlen==4): hexval = "" + hexval
elif (hexlen==5): hexval = "000" + hexval
elif (hexlen==6): hexval = "00" + hexval
elif (hexlen==7): hexval = "0" + hexval
elif (hexlen==8): hexval = "" + hexval
else: raise Exception, "Illegal Value returned from hex(ord(x))"
return "_x"+ hexval + "_"
if (hexlen == 1):
hexval = "000" + hexval
elif (hexlen == 2):
hexval = "00" + hexval
elif (hexlen == 3):
hexval = "0" + hexval
elif (hexlen == 4):
hexval = "" + hexval
elif (hexlen == 5):
hexval = "000" + hexval
elif (hexlen == 6):
hexval = "00" + hexval
elif (hexlen == 7):
hexval = "0" + hexval
elif (hexlen == 8):
hexval = "" + hexval
else:
raise Exception("Illegal Value returned from hex(ord(x))")

return "_x" + hexval + "_"




def _fromUnicodeHex(x): def _fromUnicodeHex(x):
return eval( r'u"\u'+x[2:-1]+'"' )
return eval(r'u"\u' + x[2:-1] + '"')




def toXMLname(string): def toXMLname(string):
"""Convert string to a XML name.""" """Convert string to a XML name."""
if string.find(':') != -1 :
(prefix, localname) = string.split(':',1)
if string.find(':') != -1:
(prefix, localname) = string.split(':', 1)
else: else:
prefix = None prefix = None
localname = string localname = string
T = unicode(localname) T = unicode(localname)


N = len(localname) N = len(localname)
X = [];
for i in range(N) :
if i< N-1 and T[i]==u'_' and T[i+1]==u'x':
X = []
for i in range(N):
if i < N - 1 and T[i] == u'_' and T[i + 1] == u'x':
X.append(u'_x005F_') X.append(u'_x005F_')
elif i==0 and N >= 3 and \
( T[0]==u'x' or T[0]==u'X' ) and \
( T[1]==u'm' or T[1]==u'M' ) and \
( T[2]==u'l' or T[2]==u'L' ):
elif i == 0 and N >= 3 and \
(T[0] == u'x' or T[0] == u'X') and \
(T[1] == u'm' or T[1] == u'M') and \
(T[2] == u'l' or T[2] == u'L'):
X.append(u'_xFFFF_' + T[0]) X.append(u'_xFFFF_' + T[0])
elif (not _NCNameChar(T[i])) or (i==0 and not _NCNameStartChar(T[i])):
elif (not _NCNameChar(T[i])) or (i == 0 and not _NCNameStartChar(T[i])):
X.append(_toUnicodeHex(T[i])) X.append(_toUnicodeHex(T[i]))
else: else:
X.append(T[i]) X.append(T[i])
if prefix: if prefix:
return "%s:%s" % (prefix, u''.join(X)) return "%s:%s" % (prefix, u''.join(X))
return u''.join(X) return u''.join(X)
@@ -80,12 +89,11 @@ def toXMLname(string):
def fromXMLname(string): def fromXMLname(string):
"""Convert XML name to unicode string.""" """Convert XML name to unicode string."""


retval = sub(r'_xFFFF_','', string )
retval = sub(r'_xFFFF_', '', string)


def fun( matchobj ):
return _fromUnicodeHex( matchobj.group(0) )
def fun(matchobj):
return _fromUnicodeHex(matchobj.group(0))


retval = sub(r'_x[0-9A-Fa-f]{4}_', fun, retval)


retval = sub(r'_x[0-9A-Fa-f]{4}_', fun, retval )
return retval return retval

+ 0
- 1
src/wstools/__init__.py View File

@@ -6,4 +6,3 @@ ident = "$Id$"
import WSDLTools import WSDLTools
import XMLname import XMLname
import logging import logging


+ 82
- 73
src/wstools/c14n.py View File

@@ -5,10 +5,10 @@ Patches Applied to xml.dom.ext.c14n:
http://sourceforge.net/projects/pyxml/ http://sourceforge.net/projects/pyxml/


[ 1444526 ] c14n.py: http://www.w3.org/TR/xml-exc-c14n/ fix [ 1444526 ] c14n.py: http://www.w3.org/TR/xml-exc-c14n/ fix
-- includes [ 829905 ] c14n.py fix for bug #825115,
-- includes [ 829905 ] c14n.py fix for bug #825115,
Date Submitted: 2003-10-24 23:43 Date Submitted: 2003-10-24 23:43
-- include dependent namespace declarations declared in ancestor nodes
(checking attributes and tags),
-- include dependent namespace declarations declared in ancestor nodes
(checking attributes and tags),
-- handle InclusiveNamespaces PrefixList parameter -- handle InclusiveNamespaces PrefixList parameter


This module generates canonical XML of a document or element. This module generates canonical XML of a document or element.
@@ -64,30 +64,35 @@ except ImportError:
_attrs = lambda E: (E.attributes and E.attributes.values()) or [] _attrs = lambda E: (E.attributes and E.attributes.values()) or []
_children = lambda E: E.childNodes or [] _children = lambda E: E.childNodes or []
_IN_XML_NS = lambda n: n.name.startswith("xmlns") _IN_XML_NS = lambda n: n.name.startswith("xmlns")
_inclusive = lambda n: n.unsuppressedPrefixes == None
_inclusive = lambda n: n.unsuppressedPrefixes is None




# Does a document/PI has lesser/greater document order than the # Does a document/PI has lesser/greater document order than the
# first element? # first element?
_LesserElement, _Element, _GreaterElement = range(3) _LesserElement, _Element, _GreaterElement = range(3)


def _sorter(n1,n2):

def _sorter(n1, n2):
'''_sorter(n1,n2) -> int '''_sorter(n1,n2) -> int
Sorting predicate for non-NS attributes.''' Sorting predicate for non-NS attributes.'''


i = cmp(n1.namespaceURI, n2.namespaceURI) i = cmp(n1.namespaceURI, n2.namespaceURI)
if i: return i
if i:
return i
return cmp(n1.localName, n2.localName) return cmp(n1.localName, n2.localName)




def _sorter_ns(n1,n2):
def _sorter_ns(n1, n2):
'''_sorter_ns((n,v),(n,v)) -> int '''_sorter_ns((n,v),(n,v)) -> int
"(an empty namespace URI is lexicographically least)."''' "(an empty namespace URI is lexicographically least)."'''


if n1[0] == 'xmlns': return -1
if n2[0] == 'xmlns': return 1
if n1[0] == 'xmlns':
return -1
if n2[0] == 'xmlns':
return 1
return cmp(n1[0], n2[0]) return cmp(n1[0], n2[0])



def _utilized(n, node, other_attrs, unsuppressedPrefixes): def _utilized(n, node, other_attrs, unsuppressedPrefixes):
'''_utilized(n, node, other_attrs, unsuppressedPrefixes) -> boolean '''_utilized(n, node, other_attrs, unsuppressedPrefixes) -> boolean
Return true if that nodespace is utilized within the node''' Return true if that nodespace is utilized within the node'''
@@ -95,32 +100,35 @@ def _utilized(n, node, other_attrs, unsuppressedPrefixes):
n = n[6:] n = n[6:]
elif n.startswith('xmlns'): elif n.startswith('xmlns'):
n = n[5:] n = n[5:]
if (n=="" and node.prefix in ["#default", None]) or \
n == node.prefix or n in unsuppressedPrefixes:
if (n == "" and node.prefix in ["#default", None]) or \
n == node.prefix or n in unsuppressedPrefixes:
return 1 return 1
for attr in other_attrs: for attr in other_attrs:
if n == attr.prefix: return 1
if n == attr.prefix:
return 1
# For exclusive need to look at attributes # For exclusive need to look at attributes
if unsuppressedPrefixes is not None: if unsuppressedPrefixes is not None:
for attr in _attrs(node): for attr in _attrs(node):
if n == attr.prefix: return 1
if n == attr.prefix:
return 1

return 0 return 0




def _inclusiveNamespacePrefixes(node, context, unsuppressedPrefixes): def _inclusiveNamespacePrefixes(node, context, unsuppressedPrefixes):
'''http://www.w3.org/TR/xml-exc-c14n/
InclusiveNamespaces PrefixList parameter, which lists namespace prefixes that
'''http://www.w3.org/TR/xml-exc-c14n/
InclusiveNamespaces PrefixList parameter, which lists namespace prefixes that
are handled in the manner described by the Canonical XML Recommendation''' are handled in the manner described by the Canonical XML Recommendation'''
inclusive = [] inclusive = []
if node.prefix: if node.prefix:
usedPrefixes = ['xmlns:%s' %node.prefix]
usedPrefixes = ['xmlns:%s' % node.prefix]
else: else:
usedPrefixes = ['xmlns'] usedPrefixes = ['xmlns']


for a in _attrs(node): for a in _attrs(node):
if a.nodeName.startswith('xmlns') or not a.prefix: continue
usedPrefixes.append('xmlns:%s' %a.prefix)
if a.nodeName.startswith('xmlns') or not a.prefix:
continue
usedPrefixes.append('xmlns:%s' % a.prefix)


unused_namespace_dict = {} unused_namespace_dict = {}
for attr in context: for attr in context:
@@ -139,7 +147,7 @@ def _inclusiveNamespacePrefixes(node, context, unsuppressedPrefixes):
return inclusive, unused_namespace_dict return inclusive, unused_namespace_dict


#_in_subset = lambda subset, node: not subset or node in subset #_in_subset = lambda subset, node: not subset or node in subset
_in_subset = lambda subset, node: subset is None or node in subset # rich's tweak
_in_subset = lambda subset, node: subset is None or node in subset # rich's tweak




class _implementation: class _implementation:
@@ -155,17 +163,17 @@ class _implementation:
self.subset = kw.get('subset') self.subset = kw.get('subset')
self.comments = kw.get('comments', 0) self.comments = kw.get('comments', 0)
self.unsuppressedPrefixes = kw.get('unsuppressedPrefixes') self.unsuppressedPrefixes = kw.get('unsuppressedPrefixes')
nsdict = kw.get('nsdict', { 'xml': XMLNS.XML, 'xmlns': XMLNS.BASE })
nsdict = kw.get('nsdict', {'xml': XMLNS.XML, 'xmlns': XMLNS.BASE})
# Processing state. # Processing state.
self.state = (nsdict, {'xml':''}, {}, {}) #0422
self.state = (nsdict, {'xml': ''}, {}, {}) # 0422
if node.nodeType == Node.DOCUMENT_NODE: if node.nodeType == Node.DOCUMENT_NODE:
self._do_document(node) self._do_document(node)
elif node.nodeType == Node.ELEMENT_NODE: elif node.nodeType == Node.ELEMENT_NODE:
self.documentOrder = _Element # At document element self.documentOrder = _Element # At document element
if not _inclusive(self): if not _inclusive(self):
inherited,unused = _inclusiveNamespacePrefixes(node, self._inherit_context(node),
inherited, unused = _inclusiveNamespacePrefixes(node, self._inherit_context(node),
self.unsuppressedPrefixes) self.unsuppressedPrefixes)
self._do_element(node, inherited, unused=unused) self._do_element(node, inherited, unused=unused)
else: else:
@@ -174,8 +182,7 @@ class _implementation:
elif node.nodeType == Node.DOCUMENT_TYPE_NODE: elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
pass pass
else: else:
raise TypeError, str(node)

raise TypeError(str(node))


def _inherit_context(self, node): def _inherit_context(self, node):
'''_inherit_context(self, node) -> list '''_inherit_context(self, node) -> list
@@ -197,7 +204,6 @@ class _implementation:
parent = parent.parentNode parent = parent.parentNode
return inherited return inherited



def _do_document(self, node): def _do_document(self, node):
'''_do_document(self, node) -> None '''_do_document(self, node) -> None
Process a document node. documentOrder holds whether the document Process a document node. documentOrder holds whether the document
@@ -209,7 +215,7 @@ class _implementation:
if child.nodeType == Node.ELEMENT_NODE: if child.nodeType == Node.ELEMENT_NODE:
self.documentOrder = _Element # At document element self.documentOrder = _Element # At document element
self._do_element(child) self._do_element(child)
self.documentOrder = _GreaterElement # After document element
self.documentOrder = _GreaterElement # After document element
elif child.nodeType == Node.PROCESSING_INSTRUCTION_NODE: elif child.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
self._do_pi(child) self._do_pi(child)
elif child.nodeType == Node.COMMENT_NODE: elif child.nodeType == Node.COMMENT_NODE:
@@ -217,33 +223,35 @@ class _implementation:
elif child.nodeType == Node.DOCUMENT_TYPE_NODE: elif child.nodeType == Node.DOCUMENT_TYPE_NODE:
pass pass
else: else:
raise TypeError, str(child)
raise TypeError(str(child))
handlers[Node.DOCUMENT_NODE] = _do_document handlers[Node.DOCUMENT_NODE] = _do_document



def _do_text(self, node): def _do_text(self, node):
'''_do_text(self, node) -> None '''_do_text(self, node) -> None
Process a text or CDATA node. Render various special characters Process a text or CDATA node. Render various special characters
as their C14N entity representations.''' as their C14N entity representations.'''
if not _in_subset(self.subset, node): return
if not _in_subset(self.subset, node):
return
s = string.replace(node.data, "&", "&amp;") s = string.replace(node.data, "&", "&amp;")
s = string.replace(s, "<", "&lt;") s = string.replace(s, "<", "&lt;")
s = string.replace(s, ">", "&gt;") s = string.replace(s, ">", "&gt;")
s = string.replace(s, "\015", "&#xD;") s = string.replace(s, "\015", "&#xD;")
if s: self.write(s)
if s:
self.write(s)
handlers[Node.TEXT_NODE] = _do_text handlers[Node.TEXT_NODE] = _do_text
handlers[Node.CDATA_SECTION_NODE] = _do_text handlers[Node.CDATA_SECTION_NODE] = _do_text



def _do_pi(self, node): def _do_pi(self, node):
'''_do_pi(self, node) -> None '''_do_pi(self, node) -> None
Process a PI node. Render a leading or trailing #xA if the Process a PI node. Render a leading or trailing #xA if the
document order of the PI is greater or lesser (respectively) document order of the PI is greater or lesser (respectively)
than the document element. than the document element.
''' '''
if not _in_subset(self.subset, node): return
if not _in_subset(self.subset, node):
return
W = self.write W = self.write
if self.documentOrder == _GreaterElement: W('\n')
if self.documentOrder == _GreaterElement:
W('\n')
W('<?') W('<?')
W(node.nodeName) W(node.nodeName)
s = node.data s = node.data
@@ -251,27 +259,29 @@ class _implementation:
W(' ') W(' ')
W(s) W(s)
W('?>') W('?>')
if self.documentOrder == _LesserElement: W('\n')
if self.documentOrder == _LesserElement:
W('\n')
handlers[Node.PROCESSING_INSTRUCTION_NODE] = _do_pi handlers[Node.PROCESSING_INSTRUCTION_NODE] = _do_pi



def _do_comment(self, node): def _do_comment(self, node):
'''_do_comment(self, node) -> None '''_do_comment(self, node) -> None
Process a comment node. Render a leading or trailing #xA if the Process a comment node. Render a leading or trailing #xA if the
document order of the comment is greater or lesser (respectively) document order of the comment is greater or lesser (respectively)
than the document element. than the document element.
''' '''
if not _in_subset(self.subset, node): return
if not _in_subset(self.subset, node):
return
if self.comments: if self.comments:
W = self.write W = self.write
if self.documentOrder == _GreaterElement: W('\n')
if self.documentOrder == _GreaterElement:
W('\n')
W('<!--') W('<!--')
W(node.data) W(node.data)
W('-->') W('-->')
if self.documentOrder == _LesserElement: W('\n')
if self.documentOrder == _LesserElement:
W('\n')
handlers[Node.COMMENT_NODE] = _do_comment handlers[Node.COMMENT_NODE] = _do_comment



def _do_attr(self, n, value): def _do_attr(self, n, value):
''''_do_attr(self, node) -> None ''''_do_attr(self, node) -> None
Process an attribute.''' Process an attribute.'''
@@ -289,8 +299,7 @@ class _implementation:
W(s) W(s)
W('"') W('"')



def _do_element(self, node, initial_other_attrs = [], unused = None):
def _do_element(self, node, initial_other_attrs=[], unused=None):
'''_do_element(self, node, initial_other_attrs = [], unused = {}) -> None '''_do_element(self, node, initial_other_attrs = [], unused = {}) -> None
Process an element (and its children).''' Process an element (and its children).'''


@@ -300,14 +309,14 @@ class _implementation:
# ns_local -- NS declarations relevant to this element # ns_local -- NS declarations relevant to this element
# xml_attrs -- Attributes in XML namespace from parent # xml_attrs -- Attributes in XML namespace from parent
# xml_attrs_local -- Local attributes in XML namespace. # xml_attrs_local -- Local attributes in XML namespace.
# ns_unused_inherited -- not rendered namespaces, used for exclusive
# ns_unused_inherited -- not rendered namespaces, used for exclusive
ns_parent, ns_rendered, xml_attrs = \ ns_parent, ns_rendered, xml_attrs = \
self.state[0], self.state[1].copy(), self.state[2].copy() #0422
self.state[0], self.state[1].copy(), self.state[2].copy() # 0422
ns_unused_inherited = unused ns_unused_inherited = unused
if unused is None: if unused is None:
ns_unused_inherited = self.state[3].copy() ns_unused_inherited = self.state[3].copy()
ns_local = ns_parent.copy() ns_local = ns_parent.copy()
inclusive = _inclusive(self) inclusive = _inclusive(self)
xml_attrs_local = {} xml_attrs_local = {}
@@ -318,15 +327,16 @@ class _implementation:
for a in initial_other_attrs + _attrs(node): for a in initial_other_attrs + _attrs(node):
if a.namespaceURI == XMLNS.BASE: if a.namespaceURI == XMLNS.BASE:
n = a.nodeName n = a.nodeName
if n == "xmlns:": n = "xmlns" # DOM bug workaround
if n == "xmlns:":
n = "xmlns" # DOM bug workaround
ns_local[n] = a.nodeValue ns_local[n] = a.nodeValue
elif a.namespaceURI == XMLNS.XML: elif a.namespaceURI == XMLNS.XML:
if inclusive or (in_subset and _in_subset(self.subset, a)): #020925 Test to see if attribute node in subset
xml_attrs_local[a.nodeName] = a #0426
if inclusive or (in_subset and _in_subset(self.subset, a)): # 020925 Test to see if attribute node in subset
xml_attrs_local[a.nodeName] = a # 0426
else: else:
if _in_subset(self.subset, a): #020925 Test to see if attribute node in subset
if _in_subset(self.subset, a): # 020925 Test to see if attribute node in subset
other_attrs.append(a) other_attrs.append(a)
# # TODO: exclusive, might need to define xmlns:prefix here # # TODO: exclusive, might need to define xmlns:prefix here
# if not inclusive and a.prefix is not None and not ns_rendered.has_key('xmlns:%s' %a.prefix): # if not inclusive and a.prefix is not None and not ns_rendered.has_key('xmlns:%s' %a.prefix):
# ns_local['xmlns:%s' %a.prefix] = ?? # ns_local['xmlns:%s' %a.prefix] = ??
@@ -336,47 +346,45 @@ class _implementation:


# Render the node # Render the node
W, name = self.write, None W, name = self.write, None
if in_subset:
if in_subset:
name = node.nodeName name = node.nodeName
if not inclusive: if not inclusive:
if node.prefix is not None: if node.prefix is not None:
prefix = 'xmlns:%s' %node.prefix
prefix = 'xmlns:%s' % node.prefix
else: else:
prefix = 'xmlns' prefix = 'xmlns'
if not ns_rendered.has_key(prefix) and not ns_local.has_key(prefix):
if not ns_unused_inherited.has_key(prefix):
raise RuntimeError,\
'For exclusive c14n, unable to map prefix "%s" in %s' %(
prefix, node)

if prefix not in ns_rendered and prefix not in ns_local:
if not prefix in ns_unused_inherited:
raise RuntimeError('For exclusive c14n, unable to map prefix "%s" in %s' % (
prefix, node))

ns_local[prefix] = ns_unused_inherited[prefix] ns_local[prefix] = ns_unused_inherited[prefix]
del ns_unused_inherited[prefix] del ns_unused_inherited[prefix]
W('<') W('<')
W(name) W(name)


# Create list of NS attributes to render. # Create list of NS attributes to render.
ns_to_render = [] ns_to_render = []
for n,v in ns_local.items():
for n, v in ns_local.items():


# If default namespace is XMLNS.BASE or empty, # If default namespace is XMLNS.BASE or empty,
# and if an ancestor was the same # and if an ancestor was the same
if n == "xmlns" and v in [ XMLNS.BASE, '' ] \
and ns_rendered.get('xmlns') in [ XMLNS.BASE, '', None ]:
if n == "xmlns" and v in [XMLNS.BASE, ''] \
and ns_rendered.get('xmlns') in [XMLNS.BASE, '', None]:
continue continue


# "omit namespace node with local name xml, which defines # "omit namespace node with local name xml, which defines
# the xml prefix, if its string value is # the xml prefix, if its string value is
# http://www.w3.org/XML/1998/namespace." # http://www.w3.org/XML/1998/namespace."
if n in ["xmlns:xml", "xml"] \ if n in ["xmlns:xml", "xml"] \
and v in [ 'http://www.w3.org/XML/1998/namespace' ]:
and v in ['http://www.w3.org/XML/1998/namespace']:
continue continue



# If not previously rendered # If not previously rendered
# and it's inclusive or utilized # and it's inclusive or utilized
if (n,v) not in ns_rendered.items():
if (n, v) not in ns_rendered.items():
if inclusive or _utilized(n, node, other_attrs, self.unsuppressedPrefixes): if inclusive or _utilized(n, node, other_attrs, self.unsuppressedPrefixes):
ns_to_render.append((n, v)) ns_to_render.append((n, v))
elif not inclusive: elif not inclusive:
@@ -384,14 +392,14 @@ class _implementation:


# Sort and render the ns, marking what was rendered. # Sort and render the ns, marking what was rendered.
ns_to_render.sort(_sorter_ns) ns_to_render.sort(_sorter_ns)
for n,v in ns_to_render:
for n, v in ns_to_render:
self._do_attr(n, v) self._do_attr(n, v)
ns_rendered[n]=v #0417
ns_rendered[n] = v # 0417


# If exclusive or the parent is in the subset, add the local xml attributes # If exclusive or the parent is in the subset, add the local xml attributes
# Else, add all local and ancestor xml attributes # Else, add all local and ancestor xml attributes
# Sort and render the attributes. # Sort and render the attributes.
if not inclusive or _in_subset(self.subset,node.parentNode): #0426
if not inclusive or _in_subset(self.subset, node.parentNode): # 0426
other_attrs.extend(xml_attrs_local.values()) other_attrs.extend(xml_attrs_local.values())
else: else:
other_attrs.extend(xml_attrs.values()) other_attrs.extend(xml_attrs.values())
@@ -406,7 +414,8 @@ class _implementation:
_implementation.handlers[c.nodeType](self, c) _implementation.handlers[c.nodeType](self, c)
self.state = state self.state = state


if name: W('</%s>' % name)
if name:
W('</%s>' % name)
handlers[Node.ELEMENT_NODE] = _do_element handlers[Node.ELEMENT_NODE] = _do_element






+ 73
- 49
src/wstools/logging.py View File

@@ -1,11 +1,12 @@
# Copyright (c) 2003, The Regents of the University of California, # Copyright (c) 2003, The Regents of the University of California,
# through Lawrence Berkeley National Laboratory (subject to receipt of # through Lawrence Berkeley National Laboratory (subject to receipt of
# any required approvals from the U.S. Dept. of Energy). All rights # any required approvals from the U.S. Dept. of Energy). All rights
# reserved.
# reserved.
# #
"""Logging""" """Logging"""
ident = "$Id$" ident = "$Id$"
import os, sys
import os
import sys


WARN = 1 WARN = 1
DEBUG = 2 DEBUG = 2
@@ -16,80 +17,92 @@ class ILogger:
will be used and logging calls are no-ops. will be used and logging calls are no-ops.
''' '''
level = 0 level = 0

def __init__(self, msg): def __init__(self, msg):
return return

def warning(self, *args, **kw): def warning(self, *args, **kw):
return return

def debug(self, *args, **kw): def debug(self, *args, **kw):
return return

def error(self, *args, **kw): def error(self, *args, **kw):
return return

def setLevel(cls, level): def setLevel(cls, level):
cls.level = level cls.level = level
setLevel = classmethod(setLevel) setLevel = classmethod(setLevel)
debugOn = lambda self: self.level >= DEBUG debugOn = lambda self: self.level >= DEBUG
warnOn = lambda self: self.level >= WARN warnOn = lambda self: self.level >= WARN


class BasicLogger(ILogger): class BasicLogger(ILogger):
last = '' last = ''
def __init__(self, msg, out=sys.stdout): def __init__(self, msg, out=sys.stdout):
self.msg, self.out = msg, out self.msg, self.out = msg, out


def warning(self, msg, *args, **kw): def warning(self, msg, *args, **kw):
if self.warnOn() is False: return
if self.warnOn() is False:
return
if BasicLogger.last != self.msg: if BasicLogger.last != self.msg:
BasicLogger.last = self.msg BasicLogger.last = self.msg
print >>self, "---- ", self.msg, " ----" print >>self, "---- ", self.msg, " ----"
print >>self, " %s " %self.WARN,
print >>self, msg %args
print >>self, " %s " % self.WARN,
print >>self, msg % args
WARN = '[WARN]' WARN = '[WARN]'

def debug(self, msg, *args, **kw): def debug(self, msg, *args, **kw):
if self.debugOn() is False: return
if self.debugOn() is False:
return
if BasicLogger.last != self.msg: if BasicLogger.last != self.msg:
BasicLogger.last = self.msg BasicLogger.last = self.msg
print >>self, "---- ", self.msg, " ----" print >>self, "---- ", self.msg, " ----"
print >>self, " %s " %self.DEBUG,
print >>self, msg %args
print >>self, " %s " % self.DEBUG,
print >>self, msg % args
DEBUG = '[DEBUG]' DEBUG = '[DEBUG]'

def error(self, msg, *args, **kw): def error(self, msg, *args, **kw):
if BasicLogger.last != self.msg: if BasicLogger.last != self.msg:
BasicLogger.last = self.msg BasicLogger.last = self.msg
print >>self, "---- ", self.msg, " ----" print >>self, "---- ", self.msg, " ----"
print >>self, " %s " %self.ERROR,
print >>self, msg %args
print >>self, " %s " % self.ERROR,
print >>self, msg % args
ERROR = '[ERROR]' ERROR = '[ERROR]'


def write(self, *args): def write(self, *args):
'''Write convenience function; writes strings. '''Write convenience function; writes strings.
''' '''
for s in args: self.out.write(s)
for s in args:
self.out.write(s)
event = ''.join(*args) event = ''.join(*args)




_LoggerClass = BasicLogger _LoggerClass = BasicLogger



class GridLogger(ILogger): class GridLogger(ILogger):
def debug(self, msg, *args, **kw): def debug(self, msg, *args, **kw):
kw['component'] = self.msg kw['component'] = self.msg
gridLog(event=msg %args, level='DEBUG', **kw)
gridLog(event=msg % args, level='DEBUG', **kw)


def warning(self, msg, *args, **kw): def warning(self, msg, *args, **kw):
kw['component'] = self.msg kw['component'] = self.msg
gridLog(event=msg %args, level='WARNING', **kw)
gridLog(event=msg % args, level='WARNING', **kw)


def error(self, msg, *args, **kw): def error(self, msg, *args, **kw):
kw['component'] = self.msg kw['component'] = self.msg
gridLog(event=msg %args, level='ERROR', **kw)
gridLog(event=msg % args, level='ERROR', **kw)




#
#
# Registry of send functions for gridLog # Registry of send functions for gridLog
#
#
GLRegistry = {} GLRegistry = {}



class GLRecord(dict): class GLRecord(dict):
"""Grid Logging Best Practices Record, Distributed Logging Utilities """Grid Logging Best Practices Record, Distributed Logging Utilities


@@ -97,8 +110,8 @@ class GLRecord(dict):


event -- log event name event -- log event name
Below is EBNF for the event name part of a log message. Below is EBNF for the event name part of a log message.
name = <nodot> ( "." <name> )?
nodot = {RFC3896-chars except "."}
name = <nodot> ( "." <name> )?
nodot = {RFC3896-chars except "."}


Suffixes: Suffixes:
start: Immediately before the first action in a task. start: Immediately before the first action in a task.
@@ -108,14 +121,14 @@ class GLRecord(dict):
ts -- timestamp ts -- timestamp
level -- logging level (see levels below) level -- logging level (see levels below)
status -- integer status code status -- integer status code
gid -- global grid identifier
gid -- global grid identifier
gid, cgid -- parent/child identifiers gid, cgid -- parent/child identifiers
prog -- program name prog -- program name




More info: http://www.cedps.net/wiki/index.php/LoggingBestPractices#Python More info: http://www.cedps.net/wiki/index.php/LoggingBestPractices#Python


reserved -- list of reserved names,
reserved -- list of reserved names,
omitname -- list of reserved names, output only values ('ts', 'event',) omitname -- list of reserved names, output only values ('ts', 'event',)
levels -- dict of levels and description levels -- dict of levels and description
""" """
@@ -129,8 +142,7 @@ class GLRecord(dict):
NOTICE='Normal but significant condition.', NOTICE='Normal but significant condition.',
INFO='Informational messages that would be useful to a deployer or administrator.', INFO='Informational messages that would be useful to a deployer or administrator.',
DEBUG='Lower level information concerning program logic decisions, internal state, etc.', DEBUG='Lower level information concerning program logic decisions, internal state, etc.',
TRACE='Finest granularity, similar to "stepping through" the component or system.',
)
TRACE='Finest granularity, similar to "stepping through" the component or system.',)


def __init__(self, date=None, **kw): def __init__(self, date=None, **kw):
kw['ts'] = date or self.GLDate() kw['ts'] = date or self.GLDate()
@@ -141,31 +153,34 @@ class GLRecord(dict):
""" """
""" """
from cStringIO import StringIO from cStringIO import StringIO
s = StringIO(); n = " "
reserved = self.reserved; omitname = self.omitname; levels = self.levels
s = StringIO()
n = " "
reserved = self.reserved
omitname = self.omitname
levels = self.levels


for k in ( list(filter(lambda i: self.has_key(i), reserved)) +
for k in (list(filter(lambda i: i in self, reserved)) +
list(filter(lambda i: i not in reserved, self.keys())) list(filter(lambda i: i not in reserved, self.keys()))
): ):
v = self[k] v = self[k]
if k in omitname:
s.write( "%s " %self.format[type(v)](v) )
if k in omitname:
s.write("%s " % self.format[type(v)](v))
continue continue


if k == reserved[2] and v not in levels: if k == reserved[2] and v not in levels:
pass pass


s.write( "%s=%s " %(k, self.format[type(v)](v) ) )
s.write("%s=%s " % (k, self.format[type(v)](v)))


s.write("\n") s.write("\n")
return s.getvalue() return s.getvalue()


class GLDate(str): class GLDate(str):
"""Grid logging Date Format """Grid logging Date Format
all timestamps should all be in the same time zone (UTC).
all timestamps should all be in the same time zone (UTC).
Grid timestamp value format that is a highly readable variant of the ISO8601 time standard [1]: Grid timestamp value format that is a highly readable variant of the ISO8601 time standard [1]:


YYYY-MM-DDTHH:MM:SS.SSSSSSZ
YYYY-MM-DDTHH:MM:SS.SSSSSSZ


""" """
def __new__(self, args=None): def __new__(self, args=None):
@@ -173,13 +188,13 @@ class GLRecord(dict):
""" """
import datetime import datetime
args = args or datetime.datetime.utcnow() args = args or datetime.datetime.utcnow()
l = (args.year, args.month, args.day, args.hour, args.minute, args.second,
l = (args.year, args.month, args.day, args.hour, args.minute, args.second,
args.microsecond, args.tzinfo or 'Z') args.microsecond, args.tzinfo or 'Z')


return str.__new__(self, "%04d-%02d-%02dT%02d:%02d:%02d.%06d%s" %l)
return str.__new__(self, "%04d-%02d-%02dT%02d:%02d:%02d.%06d%s" % l)


format = { int:str, float:lambda x: "%lf" % x, long:str, str:lambda x:x,
unicode:str, GLDate:str, }
format = {int: str, float: lambda x: "%lf" % x, long: str, str: lambda x: x,
unicode: str, GLDate: str, }




def gridLog(**kw): def gridLog(**kw):
@@ -193,29 +208,32 @@ def gridLog(**kw):
""" """
import os import os


if not bool( int(os.environ.get('GRIDLOG_ON', 0)) ):
if not bool(int(os.environ.get('GRIDLOG_ON', 0))):
return return


url = os.environ.get('GRIDLOG_DEST') url = os.environ.get('GRIDLOG_DEST')
if url is None:
if url is None:
return return


## NOTE: urlparse problem w/customized schemes
## NOTE: urlparse problem w/customized schemes
try: try:
scheme = url[:url.find('://')] scheme = url[:url.find('://')]
send = GLRegistry[scheme] send = GLRegistry[scheme]
send( url, str(GLRecord(**kw)), )
send(url, str(GLRecord(**kw)), )
except Exception, ex: except Exception, ex:
print >>sys.stderr, "*** gridLog failed -- %s" %(str(kw))
print >>sys.stderr, "*** gridLog failed -- %s" % (str(kw))




def sendUDP(url, outputStr): def sendUDP(url, outputStr):
from socket import socket, AF_INET, SOCK_DGRAM from socket import socket, AF_INET, SOCK_DGRAM
idx1 = url.find('://') + 3; idx2 = url.find('/', idx1)
if idx2 < idx1: idx2 = len(url)
idx1 = url.find('://') + 3
idx2 = url.find('/', idx1)
if idx2 < idx1:
idx2 = len(url)
netloc = url[idx1:idx2] netloc = url[idx1:idx2]
host,port = (netloc.split(':')+[80])[0:2]
socket(AF_INET, SOCK_DGRAM).sendto( outputStr, (host,int(port)), )
host, port = (netloc.split(':') + [80])[0:2]
socket(AF_INET, SOCK_DGRAM).sendto(outputStr, (host, int(port)), )



def writeToFile(url, outputStr): def writeToFile(url, outputStr):
print >> open(url.split('://')[1], 'a+'), outputStr print >> open(url.split('://')[1], 'a+'), outputStr
@@ -225,32 +243,37 @@ GLRegistry["file"] = writeToFile




def setBasicLogger(): def setBasicLogger():
'''Use Basic Logger.
'''Use Basic Logger.
''' '''
setLoggerClass(BasicLogger) setLoggerClass(BasicLogger)
BasicLogger.setLevel(0) BasicLogger.setLevel(0)



def setGridLogger(): def setGridLogger():
'''Use GridLogger for all logging events. '''Use GridLogger for all logging events.
''' '''
setLoggerClass(GridLogger) setLoggerClass(GridLogger)



def setBasicLoggerWARN(): def setBasicLoggerWARN():
'''Use Basic Logger. '''Use Basic Logger.
''' '''
setLoggerClass(BasicLogger) setLoggerClass(BasicLogger)
BasicLogger.setLevel(WARN) BasicLogger.setLevel(WARN)



def setBasicLoggerDEBUG(): def setBasicLoggerDEBUG():
'''Use Basic Logger. '''Use Basic Logger.
''' '''
setLoggerClass(BasicLogger) setLoggerClass(BasicLogger)
BasicLogger.setLevel(DEBUG) BasicLogger.setLevel(DEBUG)



def setLoggerClass(loggingClass): def setLoggerClass(loggingClass):
'''Set Logging Class. '''Set Logging Class.
''' '''



def setLoggerClass(loggingClass): def setLoggerClass(loggingClass):
'''Set Logging Class. '''Set Logging Class.
''' '''
@@ -258,17 +281,18 @@ def setLoggerClass(loggingClass):
global _LoggerClass global _LoggerClass
_LoggerClass = loggingClass _LoggerClass = loggingClass



def setLevel(level=0): def setLevel(level=0):
'''Set Global Logging Level. '''Set Global Logging Level.
''' '''
ILogger.level = level ILogger.level = level



def getLevel(): def getLevel():
return ILogger.level return ILogger.level



def getLogger(msg): def getLogger(msg):
'''Return instance of Logging class. '''Return instance of Logging class.
''' '''
return _LoggerClass(msg) return _LoggerClass(msg)



+ 4
- 3
src/wstools/tests/test_t1.py View File

@@ -6,15 +6,16 @@ import unittest
import test_wsdl import test_wsdl
import utils import utils



def makeTestSuite(): def makeTestSuite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(test_wsdl.makeTestSuite("services_by_file")) suite.addTest(test_wsdl.makeTestSuite("services_by_file"))
return suite return suite



def main(): def main():
loader = utils.MatchTestLoader(True, None, "makeTestSuite") loader = utils.MatchTestLoader(True, None, "makeTestSuite")
unittest.main(defaultTest="makeTestSuite", testLoader=loader) unittest.main(defaultTest="makeTestSuite", testLoader=loader)


if __name__ == "__main__" : main()

if __name__ == "__main__":
main()

+ 19
- 12
src/wstools/tests/test_wsdl.py View File

@@ -5,7 +5,8 @@
# See LBNLCopyright for copyright notice! # See LBNLCopyright for copyright notice!
########################################################################### ###########################################################################


import sys, unittest
import sys
import unittest
import ConfigParser import ConfigParser
import os import os
from wstools.Utility import DOM from wstools.Utility import DOM
@@ -15,6 +16,7 @@ from wstools.TimeoutSocket import TimeoutError
from wstools import tests from wstools import tests
cwd = os.path.dirname(tests.__file__) cwd = os.path.dirname(tests.__file__)



class WSDLToolsTestCase(unittest.TestCase): class WSDLToolsTestCase(unittest.TestCase):


def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
@@ -28,7 +30,7 @@ class WSDLToolsTestCase(unittest.TestCase):
def __str__(self): def __str__(self):
teststr = unittest.TestCase.__str__(self) teststr = unittest.TestCase.__str__(self)
if hasattr(self, "path"): if hasattr(self, "path"):
return "%s: %s" % (teststr, self.path )
return "%s: %s" % (teststr, self.path)
else: else:
return "%s" % (teststr) return "%s" % (teststr)


@@ -41,12 +43,12 @@ class WSDLToolsTestCase(unittest.TestCase):
for node in DOM.getElements(definition, tag_name, nspname): for node in DOM.getElements(definition, tag_name, nspname):
name = DOM.getAttr(node, key) name = DOM.getAttr(node, key)
comp = component[name] comp = component[name]
self.failUnlessEqual(eval('comp.%s' %key), name)
self.failUnlessEqual(eval('comp.%s' % key), name)


def checkXSDCollection(self, tag_name, component, node, key='name'): def checkXSDCollection(self, tag_name, component, node, key='name'):
for cnode in DOM.getElements(node, tag_name): for cnode in DOM.getElements(node, tag_name):
name = DOM.getAttr(cnode, key) name = DOM.getAttr(cnode, key)
component[name]
component[name]


def test_all(self): def test_all(self):
try: try:
@@ -88,13 +90,14 @@ class WSDLToolsTestCase(unittest.TestCase):
raise raise


try: try:
self.checkWSDLCollection('import', self.wsdl.imports, key='namespace')
self.checkWSDLCollection('import', self.wsdl.imports, \
key='namespace')
except: except:
self.path = self.path + ": wsdl.imports" self.path = self.path + ": wsdl.imports"
raise raise


try: try:
for key in self.wsdl.types.keys():
for key in self.wsdl.types.keys():
schema = self.wsdl.types[key] schema = self.wsdl.types[key]
self.failUnlessEqual(key, schema.getTargetNamespace()) self.failUnlessEqual(key, schema.getTargetNamespace())


@@ -114,8 +117,9 @@ class WSDLToolsTestCase(unittest.TestCase):
raise raise


if self.wsdl.extensions: if self.wsdl.extensions:
print 'No check for WSDLTools(%s) Extensions:' %(self.wsdl.name)
for ext in self.wsdl.extensions: print '\t', ext
print 'No check for WSDLTools(%s) Extensions:' % (self.wsdl.name)
for ext in self.wsdl.extensions:
print '\t', ext


def schemaAttributesDeclarations(self, schema, node): def schemaAttributesDeclarations(self, schema, node):
self.checkXSDCollection('attribute', schema.attr_decl, node) self.checkXSDCollection('attribute', schema.attr_decl, node)
@@ -133,7 +137,7 @@ class WSDLToolsTestCase(unittest.TestCase):


def setUpOptions(section): def setUpOptions(section):
cp = ConfigParser.ConfigParser() cp = ConfigParser.ConfigParser()
cp.read(cwd+'/config.txt')
cp.read(cwd + '/config.txt')
if not cp.sections(): if not cp.sections():
print 'fatal error: configuration file config.txt not present' print 'fatal error: configuration file config.txt not present'
sys.exit(0) sys.exit(0)
@@ -142,10 +146,12 @@ def setUpOptions(section):
sys.exit(0) sys.exit(0)
return cp, len(cp.options(section)) return cp, len(cp.options(section))



def getOption(cp, section): def getOption(cp, section):
for name, value in cp.items(section): for name, value in cp.items(section):
yield value yield value


def makeTestSuite(section='services_by_file'): def makeTestSuite(section='services_by_file'):
global nameGenerator global nameGenerator


@@ -159,6 +165,7 @@ def makeTestSuite(section='services_by_file'):


def main(): def main():
unittest.main(defaultTest="makeTestSuite") unittest.main(defaultTest="makeTestSuite")


if __name__ == "__main__" : main()

if __name__ == "__main__":
main()

+ 11
- 6
src/wstools/tests/test_wstools.py View File

@@ -5,13 +5,17 @@
# See LBNLCopyright for copyright notice! # See LBNLCopyright for copyright notice!
########################################################################### ###########################################################################


import unittest, tarfile, os, ConfigParser
import unittest
import tarfile
import os
import ConfigParser
import test_wsdl import test_wsdl




SECTION='files'
SECTION = 'files'
CONFIG_FILE = 'config.txt' CONFIG_FILE = 'config.txt'



def extractFiles(section, option): def extractFiles(section, option):
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
config.read(CONFIG_FILE) config.read(CONFIG_FILE)
@@ -20,18 +24,19 @@ def extractFiles(section, option):
for file in archives: for file in archives:
tar = tarfile.open(file) tar = tarfile.open(file)
if not os.access(tar.membernames[0], os.R_OK): if not os.access(tar.membernames[0], os.R_OK):
for i in tar.getnames():
for i in tar.getnames():
tar.extract(i) tar.extract(i)



def makeTestSuite(): def makeTestSuite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(test_wsdl.makeTestSuite("services_by_file")) suite.addTest(test_wsdl.makeTestSuite("services_by_file"))
return suite return suite



def main(): def main():
extractFiles(SECTION, 'archives') extractFiles(SECTION, 'archives')
unittest.main(defaultTest="makeTestSuite") unittest.main(defaultTest="makeTestSuite")


if __name__ == "__main__" : main()

if __name__ == "__main__":
main()

+ 4
- 3
src/wstools/tests/test_wstools_net.py View File

@@ -7,14 +7,15 @@
import unittest import unittest
import test_wsdl import test_wsdl



def makeTestSuite(): def makeTestSuite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(test_wsdl.makeTestSuite("services_by_http")) suite.addTest(test_wsdl.makeTestSuite("services_by_http"))
return suite return suite



def main(): def main():
unittest.main(defaultTest="makeTestSuite") unittest.main(defaultTest="makeTestSuite")


if __name__ == "__main__" : main()

if __name__ == "__main__":
main()

Loading…
Cancel
Save