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
*.pyc

+ 3
- 4
CHANGES.txt View File

@@ -1,12 +1,11 @@
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)
----------------


+ 2
- 2
MANIFEST.in View File

@@ -1,5 +1,5 @@
include README.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 $

import os,re
import os
import re
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):
return "\n"+ open(
return "\n" + open(
os.path.join('.', *rnames)
).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('CHANGES.txt')\

@@ -25,13 +26,12 @@ setup(
name="wstools",
version=__version__,
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,
packages=find_packages('src'),
package_dir = {'': 'src'},
include_package_data=True,
package_dir={'': 'src'},
include_package_data=True,
install_requires=[]
)


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

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


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

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


class MIMEMessage:

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

def makeBoundary(self):
#create the boundary
#create the boundary
msgparts = []
msgparts.append(self._xmlMessage)
for i in self._files:
msgparts.append(i.read())
#this sucks, all in memory
alltext = NL.join(msgparts)
self._boundary = _make_boundary(alltext)
self._boundary = _make_boundary(alltext)
#maybe I can save some memory
del alltext
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):
'''it return a string with the MIME message'''
@@ -61,7 +61,7 @@ class MIMEMessage:
file.seek(0)
returnstr += file.read() + NL
#closing boundary
returnstr += "--" + self._boundary + "--" + NL
returnstr += "--" + self._boundary + "--" + NL
return returnstr

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

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
'''
return self._boundary
@@ -107,4 +107,3 @@ def _make_boundary(text=None):
b = boundary + '.' + str(counter)
counter += 1
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 OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
"""Namespace module, so you don't need PyXML
"""Namespace module, so you don't need PyXML
"""

ident = "$Id$"
try:
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:
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:
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:
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/"

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:
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_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:
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:
@@ -123,9 +123,9 @@ WSRFLIST = (WSRF_V1_2,)
class OASIS:
'''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"
class X509TOKEN:
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"
@@ -133,7 +133,7 @@ class OASIS:
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"
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
PROPERTIES = WSRF_V1_2.PROPERTIES.XSD_DRAFT1
BASENOTIFICATION = WSRF_V1_2.BASENOTIFICATION.XSD_DRAFT1
@@ -151,45 +151,50 @@ class WSTRUST:
BASE = "http://schemas.xmlsoap.org/ws/2004/04/trust"
ISSUE = "http://schemas.xmlsoap.org/ws/2004/04/trust/Issue"


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:
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"


class WSR:
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:
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:
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:
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:
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_LIST = (WSA200508, WSA200408, WSA200403, WSA200303)


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

WSAW_LIST = (WSAW200605,)


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


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


class GLOBUS:
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/'

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

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

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$"

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

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

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

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

def readlines(self, sizehint = 0):
def readlines(self, sizehint=0):
total = 0
list = []
while 1:
line = self.readline()
if not line: break
if not line:
break
list.append(line)
total += len(line)
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.

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$

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

class UserTuple:
def __init__(self, inittuple=None):
self.data = ()
@@ -67,24 +63,51 @@ class UserTuple:
else:
# the same applies here; (t is tuple(t)) == 1
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):
if isinstance(other, UserTuple): return other.data
else: return other
if isinstance(other, UserTuple):
return other.data
else:
return other

def __cmp__(self, 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):
i = max(i, 0); j = max(j, 0)
i = max(i, 0)
j = max(j, 0)
return self.__class__(self.data[i:j])

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

def __mul__(self, n):
return self.__class__(self.data*n)
return self.__class__(self.data * n)
__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,
# through Lawrence Berkeley National Laboratory (subject to receipt of
# any required approvals from the U.S. Dept. of Energy). All rights
# reserved.
# reserved.
#
# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
#
@@ -14,7 +15,12 @@

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 string import join, strip, split
from UserDict import UserDict
@@ -48,17 +54,17 @@ try:
except:
def SplitQName(qname):
'''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)
Special Cases:
xmlns -- (localName, 'xmlns')
None -- (None, localName)
'''
l = qname.split(':')
if len(l) == 1:
l.insert(0, None)
@@ -77,10 +83,12 @@ basejoin = urllib.basejoin
if sys.version_info[0:2] < (2, 4, 0, 'final', 0)[0:2]:
#basejoin = lambda base,url: urllib.basejoin(base,url.lstrip('./'))
token = './'
def basejoin(base, url):

def basejoin(base, url):
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):
"""Used to indicate a Namespace Error."""
@@ -101,7 +109,7 @@ class DOMException(Exception):
class Base:
"""Base class for instance level Logging"""
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:
@@ -114,6 +122,7 @@ class HTTPResponse:
self.body = response.read() or None
response.close()


class TimeoutHTTP(HTTPConnection):
"""A custom http connection object that supports socket timeout."""
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'):
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 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
except ImportError:
if not hasattr(socket, 'ssl'):
raise RuntimeError, 'no built-in SSL Support'
raise RuntimeError('no built-in SSL Support')

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


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

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.

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

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


# Namespace stuff related to XML Schema.

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_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_XSI_01 = 'http://www.w3.org/2001/XMLSchema-instance'
@@ -302,15 +313,14 @@ class DOM:
NS_XSI = NS_XSI_01

_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():
_xsd_uri_mapping[value] = key


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


# Namespace stuff related to WSDL.

NS_WSDL_1_1 = 'http://schemas.xmlsoap.org/wsdl/'
NS_WSDL_ALL = (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_ALL = (NS_SOAP_HTTP_1_1,)
NS_SOAP_HTTP = NS_SOAP_HTTP_1_1

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


# 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):
"""Return true if the given node is an element with the given
@@ -430,7 +434,7 @@ class DOM:
return child
if default is not join:
return default
raise KeyError, name
raise KeyError(name)

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

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

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

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

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

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


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.
'''
def __init__(self, sw):
@@ -685,39 +689,39 @@ class MessageInterface:
def canonicalize(self):
'''canonicalize the underlying DOM, and return as string.
'''
raise NotImplementedError, ''
raise NotImplementedError('')

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

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

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

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

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

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

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

standard_ns = {\
_xml_prefix:_xml_nsuri,
_xmlns_prefix:_xmlns_nsuri
_xml_prefix: _xml_nsuri,
_xmlns_prefix: _xmlns_nsuri
}
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
namespaceURI = None

def __init__(self, sw, message=None):
'''Initialize.
'''Initialize.
sw -- SoapWriter
'''
self._indx = 0
@@ -762,7 +766,7 @@ class ElementProxy(Base, MessageInterface):
Base.__init__(self)
self._dom = DOM
self.node = None
if type(message) in (types.StringType,types.UnicodeType):
if type(message) in (types.StringType, types.UnicodeType):
self.loadFromString(message)
elif isinstance(message, ElementProxy):
self.node = message._getNode()
@@ -783,11 +787,11 @@ class ElementProxy(Base, MessageInterface):
else:
context = XPath.Context.Context(self.node, processorNss=processorNss)
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
# classes (namespaceURI,name) node.
# classes (namespaceURI,name) node.
#############################################
def checkNode(self, namespaceURI=None, localName=None):
'''
@@ -800,7 +804,7 @@ class ElementProxy(Base, MessageInterface):
if localName and self.node:
check = self._dom.isElement(self.node, localName, namespaceURI)
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):
if node:
@@ -811,12 +815,12 @@ class ElementProxy(Base, MessageInterface):
elif self.node:
node = self._dom.getElement(self.node, self.name, self.namespaceURI, default=None)
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
else:
#self.node = self._dom.create(self.node, self.name, self.namespaceURI, default=None)
self.createDocument(self.namespaceURI, localName=self.name, doctype=None)
self.checkNode()

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

def _getUniquePrefix(self):
'''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.
'''
while 1:
self._indx += 1
prefix = 'ns%d' %self._indx
prefix = 'ns%d' % self._indx
try:
self._dom.findNamespaceURI(prefix, self._getNode())
except DOMException, ex:
@@ -867,7 +871,7 @@ class ElementProxy(Base, MessageInterface):
else:
if node.parentNode:
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):
'''
@@ -875,14 +879,14 @@ class ElementProxy(Base, MessageInterface):
node -- DOM Element Node
'''
if node is None:
raise TypeError, 'node is None'
raise TypeError('node is None')
self.node.appendChild(node)

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

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

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

if namespaceURI == self.reserved_ns[prefix]:
qualifiedName = '%s:%s' %(prefix,localName)
qualifiedName = '%s:%s' % (prefix, localName)
elif namespaceURI is localName is None:
self.node = self._dom.createDocument(None,None,None)
self.node = self._dom.createDocument(None, None, None)
return
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)
self.node = document.childNodes[0]

#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)

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

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

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

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

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

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

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
@@ -1132,10 +1136,10 @@ class ElementProxy(Base, MessageInterface):
return not self.node



class Collection(UserDict):
"""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):
UserDict.__init__(self)
self.parent = weakref.ref(parent)
@@ -1143,7 +1147,8 @@ class Collection(UserDict):
self._func = key or self.default

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.data[key]

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

class CollectionNS(UserDict):
"""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):
UserDict.__init__(self)
self.parent = weakref.ref(parent)
@@ -1174,10 +1180,10 @@ class CollectionNS(UserDict):

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

@@ -1185,17 +1191,17 @@ class CollectionNS(UserDict):
item.parent = weakref.ref(self)
self.list.append(item)
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][key] = item

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):
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

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



# This is a runtime guerilla patch for pulldom (used by minidom) so
# that xml namespace declaration attributes are not lost in parsing.
# 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.

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

PullDOM.startPrefixMapping = startPrefixMapping

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

for aname,value in attrs.items():
for aname, value in attrs.items():
a_uri, a_localname = aname
if a_uri == xmlns_uri:
if a_localname == 'xmlns':
@@ -1294,7 +1298,7 @@ if 1:
# ('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.value = = http://www.w3.org/2001/XMLSchema
# xml.dom.minidom.Attr.value = = http://www.w3.org/2001/XMLSchema

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

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

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

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


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

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

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

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

def addBinding(self, name, type, documentation='', targetNamespace=None):
if self.bindings.has_key(name):
if name in self.bindings:
raise WSDLError(
'Duplicate binding element: %s' % name
)
@@ -133,11 +134,11 @@ class WSDL:
def toDom(self):
""" Generate a DOM representation of the WSDL instance.
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.
"""
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.
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:soap', 'http://schemas.xmlsoap.org/wsdl/soap/')
child.setAttributeNS(XMLNS.BASE, 'xmlns:tns', self.targetNamespace)
if self.name:
child.setAttributeNS(None, 'name', self.name)

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

#
#
# 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.
#
#
imported = []
base_location = self.location
do_it = True
@@ -203,7 +204,7 @@ class WSDL:

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

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.
#
#
for element in DOM.getElements(definitions, None, None):
targetNamespace = DOM.getAttr(element, 'targetNamespace')
localName = element.localName
@@ -296,15 +297,15 @@ class WSDL:

def _import(self, document, element, base_location=None):
'''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
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
the relative "location" and storing it as "location".
document -- document we are loading
element -- DOM Element representing <import>
element -- DOM Element representing <import>
base_location -- location of document from which this
<import> was gleaned.
'''
@@ -344,7 +345,7 @@ class WSDL:
parent = element.parentNode

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


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

return None


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


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

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

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

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

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

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

if self.element is not None:
ns,name = self.element
ns, name = self.element
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:
ns,name = self.type
ns, name = self.type
prefix = epc.getPrefix(ns)
epc.setAttributeNS(None, 'type', '%s:%s'%(prefix,name))
epc.setAttributeNS(None, 'type', '%s:%s' % (prefix, name))


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

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

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

@@ -629,16 +637,15 @@ class PortType(Element):
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'portType')
epc.setAttributeNS(None, 'name', self.name)
if self.resourceProperties:
ns,name = self.resourceProperties
ns, name = self.resourceProperties
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:
op.toDom(epc._getNode())



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

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


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

return None

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

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

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

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=''):
item = OperationBinding(name, documentation)
@@ -844,9 +853,9 @@ class Binding(Element):
epc = ep.createAppendElement(DOM.GetWSDLUri(wsdl.version), 'binding')
epc.setAttributeNS(None, 'name', self.name)

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

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


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

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):
if self.input is None:
@@ -951,7 +959,7 @@ class MessageRoleBinding(Element):
return None

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):
for e in elements:
@@ -1038,7 +1046,8 @@ class MessageRoleBinding(Element):

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


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

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

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


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

tagname = 'header'


class SoapHeaderFaultBinding(SoapHeaderBinding):
tagname = 'headerfault'

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


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


class HttpUrlReplacementBinding:
pass

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



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


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


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


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


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


def GetWSAActionInput(operation):
"""Find wsa:Action attribute, and return value or the default."""
attr = operation.input.action
@@ -1400,8 +1418,9 @@ def GetWSAActionInput(operation):
if not msgName:
msgName = operation.name + 'Request'
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):
"""Find wsa:Action attribute, and return value or the default."""
@@ -1414,26 +1433,28 @@ def GetWSAActionOutput(operation):
if not msgName:
msgName = operation.name + 'Response'
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(())):
if isinstance(kind, t_type):
result = []
namespaceURI, name = kind
return [ item for item in object.extensions
return [item for item in object.extensions
if hasattr(item, 'nodeType') \
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(())):
if isinstance(kind, t_type):
namespaceURI, name = kind
for item in object.extensions:
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
else:
for item in object.extensions:
@@ -1443,7 +1464,7 @@ def FindExtension(object, kind, t_type=type(())):


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
raw WSDL structures."""

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

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

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

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

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

body = msgrole.findBinding(SoapBodyBinding)
if body is None:
raise ValueError, 'Missing soap:body binding.'
raise ValueError('Missing soap:body binding.')
callinfo.encodingStyle = body.encodingStyle
callinfo.namespace = body.namespace
callinfo.use = body.use
@@ -1609,7 +1630,7 @@ def callInfoFromWSDL(port, name):
callinfo.addInParameter(
part.name,
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:
@@ -1626,12 +1647,12 @@ def callInfoFromWSDL(port, name):
"Recieved message not defined in the WSDL schema.", \
"Adding it."
print "Message:", operation.output.message
msgrole = opbinding.output

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

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

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):
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):
return x.isalpha() or x=="_"
return x.isalpha() or x == "_"


def _toUnicodeHex(x):
hexval = hex(ord(x[0]))[2:]
hexlen = len(hexval)
# 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):
return eval( r'u"\u'+x[2:-1]+'"' )
return eval(r'u"\u' + x[2:-1] + '"')


def toXMLname(string):
"""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:
prefix = None
localname = string
T = unicode(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_')
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])
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]))
else:
X.append(T[i])
if prefix:
return "%s:%s" % (prefix, u''.join(X))
return u''.join(X)
@@ -80,12 +89,11 @@ def toXMLname(string):
def fromXMLname(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

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

@@ -6,4 +6,3 @@ ident = "$Id$"
import WSDLTools
import XMLname
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/

[ 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
-- 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

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 []
_children = lambda E: E.childNodes or []
_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
# first element?
_LesserElement, _Element, _GreaterElement = range(3)

def _sorter(n1,n2):

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

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


def _sorter_ns(n1,n2):
def _sorter_ns(n1, n2):
'''_sorter_ns((n,v),(n,v)) -> int
"(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])


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

return 0


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'''
inclusive = []
if node.prefix:
usedPrefixes = ['xmlns:%s' %node.prefix]
usedPrefixes = ['xmlns:%s' % node.prefix]
else:
usedPrefixes = ['xmlns']

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

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

raise TypeError(str(node))

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


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


def _do_text(self, node):
'''_do_text(self, node) -> None
Process a text or CDATA node. Render various special characters
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(s, "<", "&lt;")
s = string.replace(s, ">", "&gt;")
s = string.replace(s, "\015", "&#xD;")
if s: self.write(s)
if s:
self.write(s)
handlers[Node.TEXT_NODE] = _do_text
handlers[Node.CDATA_SECTION_NODE] = _do_text


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


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


def _do_attr(self, n, value):
''''_do_attr(self, node) -> None
Process an attribute.'''
@@ -289,8 +299,7 @@ class _implementation:
W(s)
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
Process an element (and its children).'''

@@ -300,14 +309,14 @@ class _implementation:
# ns_local -- NS declarations relevant to this element
# xml_attrs -- Attributes in XML namespace from parent
# 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 = \
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
if unused is None:
ns_unused_inherited = self.state[3].copy()
ns_local = ns_parent.copy()
inclusive = _inclusive(self)
xml_attrs_local = {}
@@ -318,15 +327,16 @@ class _implementation:
for a in initial_other_attrs + _attrs(node):
if a.namespaceURI == XMLNS.BASE:
n = a.nodeName
if n == "xmlns:": n = "xmlns" # DOM bug workaround
if n == "xmlns:":
n = "xmlns" # DOM bug workaround
ns_local[n] = a.nodeValue
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:
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)
# # 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):
# ns_local['xmlns:%s' %a.prefix] = ??
@@ -336,47 +346,45 @@ class _implementation:

# Render the node
W, name = self.write, None
if in_subset:
if in_subset:
name = node.nodeName
if not inclusive:
if node.prefix is not None:
prefix = 'xmlns:%s' %node.prefix
prefix = 'xmlns:%s' % node.prefix
else:
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]
del ns_unused_inherited[prefix]
W('<')
W(name)

# Create list of NS attributes 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,
# 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

# "omit namespace node with local name xml, which defines
# the xml prefix, if its string value is
# http://www.w3.org/XML/1998/namespace."
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


# If not previously rendered
# 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):
ns_to_render.append((n, v))
elif not inclusive:
@@ -384,14 +392,14 @@ class _implementation:

# Sort and render the ns, marking what was rendered.
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)
ns_rendered[n]=v #0417
ns_rendered[n] = v # 0417

# If exclusive or the parent is in the subset, add the local xml attributes
# Else, add all local and ancestor xml 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())
else:
other_attrs.extend(xml_attrs.values())
@@ -406,7 +414,8 @@ class _implementation:
_implementation.handlers[c.nodeType](self, c)
self.state = state

if name: W('</%s>' % name)
if name:
W('</%s>' % name)
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,
# through Lawrence Berkeley National Laboratory (subject to receipt of
# any required approvals from the U.S. Dept. of Energy). All rights
# reserved.
# reserved.
#
"""Logging"""
ident = "$Id$"
import os, sys
import os
import sys

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

def __init__(self, msg):
return

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

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

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

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

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

def warning(self, msg, *args, **kw):
if self.warnOn() is False: return
if self.warnOn() is False:
return
if BasicLogger.last != self.msg:
BasicLogger.last = 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]'

def debug(self, msg, *args, **kw):
if self.debugOn() is False: return
if self.debugOn() is False:
return
if BasicLogger.last != self.msg:
BasicLogger.last = 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]'

def error(self, msg, *args, **kw):
if BasicLogger.last != self.msg:
BasicLogger.last = 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]'

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


_LoggerClass = BasicLogger


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

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

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


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


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

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

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


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',)
levels -- dict of levels and description
"""
@@ -129,8 +142,7 @@ class GLRecord(dict):
NOTICE='Normal but significant condition.',
INFO='Informational messages that would be useful to a deployer or administrator.',
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):
kw['ts'] = date or self.GLDate()
@@ -141,31 +153,34 @@ class GLRecord(dict):
"""
"""
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()))
):
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

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

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

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

class GLDate(str):
"""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]:

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

"""
def __new__(self, args=None):
@@ -173,13 +188,13 @@ class GLRecord(dict):
"""
import datetime
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')

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):
@@ -193,29 +208,32 @@ def gridLog(**kw):
"""
import os

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

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

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


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


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


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


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


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


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


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


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


def getLevel():
return ILogger.level


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



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

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


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


def main():
loader = utils.MatchTestLoader(True, None, "makeTestSuite")
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!
###########################################################################

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


class WSDLToolsTestCase(unittest.TestCase):

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

@@ -41,12 +43,12 @@ class WSDLToolsTestCase(unittest.TestCase):
for node in DOM.getElements(definition, tag_name, nspname):
name = DOM.getAttr(node, key)
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'):
for cnode in DOM.getElements(node, tag_name):
name = DOM.getAttr(cnode, key)
component[name]
component[name]

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

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

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

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

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):
self.checkXSDCollection('attribute', schema.attr_decl, node)
@@ -133,7 +137,7 @@ class WSDLToolsTestCase(unittest.TestCase):

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


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


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

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

def main():
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!
###########################################################################

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


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


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


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


def main():
extractFiles(SECTION, 'archives')
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 test_wsdl


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


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

if __name__ == "__main__" : main()

if __name__ == "__main__":
main()

Loading…
Cancel
Save