Update of /cvsroot/pywebsvcs/zsi/ZSI/wsdl
In directory sc8-pr-cvs1:/tmp/cvs-serv7890
Modified Files:
ServiceProxy.py Utility.py WSDLTools.py XMLSchema.py
Removed Files:
SOAPCallInfo.py Transports.py XMLWriter.py
Log Message:
Simplify code:
-Remove toXML methods, and WSDLWriter class.
-Remove SMTP transport, since only use of Transports is for
WSDL reading. Should remove timeout stuff altogether and use
Python's current URL library.
-Merge some smaller files into the only place they're used.
Index: ServiceProxy.py
===================================================================
RCS file: /cvsroot/pywebsvcs/zsi/ZSI/wsdl/ServiceProxy.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ServiceProxy.py 18 Mar 2003 05:04:08 -0000 1.1
+++ ServiceProxy.py 21 Mar 2003 16:31:25 -0000 1.2
@@ -7,13 +7,232 @@
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
-from SOAPCallInfo import callInfoFromWSDL
-from WSDLTools import WSDLReader
from urlparse import urlparse
from ZSI import *
from ZSI.client import *
import weakref
+from Utility import DOM
+import WSDLTools
+
+
+class SOAPCallInfo:
+ """SOAPCallInfo captures the important binding information about a
+ SOAP operation, in a structure that is easier to work with than
+ raw WSDL structures."""
+
+ def __init__(self, methodName):
+ self.methodName = methodName
+ self.inheaders = []
+ self.outheaders = []
+ self.inparams = []
+ self.outparams = []
+ self.retval = None
+
+ encodingStyle = DOM.NS_SOAP_ENC
+ documentation = ''
+ soapAction = None
+ transport = None
+ namespace = None
+ location = None
+ use = 'encoded'
+ style = 'rpc'
+
+ def addInParameter(self, name, type, namespace=None, element_type=0):
+ """Add an input parameter description to the call info."""
+ parameter = ParameterInfo(name, type, namespace, element_type)
+ self.inparams.append(parameter)
+ return parameter
+
+ def addOutParameter(self, name, type, namespace=None, element_type=0):
+ """Add an output parameter description to the call info."""
+ parameter = ParameterInfo(name, type, namespace, element_type)
+ self.outparams.append(parameter)
+ return parameter
+
+ def setReturnParameter(self, name, type, namespace=None, element_type=0):
+ """Set the return parameter description for the call info."""
+ parameter = ParameterInfo(name, type, namespace, element_type)
+ self.retval = parameter
+ return parameter
+
+ def addInHeaderInfo(self, name, type, namespace, element_type=0,
+ mustUnderstand=0):
+ """Add an input SOAP header description to the call info."""
+ headerinfo = HeaderInfo(name, type, namespace, element_type)
+ if mustUnderstand:
+ headerinfo.mustUnderstand = 1
+ self.inheaders.append(headerinfo)
+ return headerinfo
+
+ def addOutHeaderInfo(self, name, type, namespace, element_type=0,
+ mustUnderstand=0):
+ """Add an output SOAP header description to the call info."""
+ headerinfo = HeaderInfo(name, type, namespace, element_type)
+ if mustUnderstand:
+ headerinfo.mustUnderstand = 1
+ self.outheaders.append(headerinfo)
+ return headerinfo
+
+ def getInParameters(self):
+ """Return a sequence of the in parameters of the method."""
+ return self.inparams
+
+ def getOutParameters(self):
+ """Return a sequence of the out parameters of the method."""
+ return self.outparams
+
+ def getReturnParameter(self):
+ """Return param info about the return value of the method."""
+ return self.retval
+
+ def getInHeaders(self):
+ """Return a sequence of the in headers of the method."""
+ return self.inheaders
+
+ def getOutHeaders(self):
+ """Return a sequence of the out headers of the method."""
+ return self.outheaders
+
+
+class ParameterInfo:
+ """A ParameterInfo object captures parameter binding information."""
+ def __init__(self, name, type, namespace=None, element_type=0):
+ if element_type:
+ self.element_type = 1
+ if namespace is not None:
+ self.namespace = namespace
+ self.name = name
+ self.type = type
+
+ element_type = 0
+ namespace = None
+ default = None
+
+
+class HeaderInfo(ParameterInfo):
+ """A HeaderInfo object captures SOAP header binding information."""
+ def __init__(self, name, type, namespace, element_type=None):
+ ParameterInfo.__init__(self, name, type, namespace, element_type)
+
+ mustUnderstand = 0
+ actor = None
+
+
+def callInfoFromWSDL(port, name):
+ """Return a SOAPCallInfo given a WSDL port and operation name."""
+ wsdl = port.getService().getWSDL()
+ binding = port.getBinding()
+ portType = binding.getPortType()
+ operation = portType.operations[name]
+ opbinding = binding.operations[name]
+ messages = wsdl.messages
+ callinfo = SOAPCallInfo(name)
+
+ addrbinding = port.getAddressBinding()
+ if not isinstance(addrbinding, WSDLTools.SoapAddressBinding):
+ raise ValueError, 'Unsupported binding type.'
+ callinfo.location = addrbinding.location
+
+ soapbinding = binding.findBinding(WSDLTools.SoapBinding)
+ if soapbinding is None:
+ raise ValueError, 'Missing soap:binding element.'
+ callinfo.transport = soapbinding.transport
+ callinfo.style = soapbinding.style or 'document'
+
+ soap_op_binding = opbinding.findBinding(WSDLTools.SoapOperationBinding)
+ if soap_op_binding is not None:
+ callinfo.soapAction = soap_op_binding.soapAction
+ callinfo.style = soap_op_binding.style or callinfo.style
+
+ parameterOrder = operation.parameterOrder
+
+ if operation.input is not None:
+ message = messages[operation.input.message]
+ msgrole = opbinding.input
+
+ mime = msgrole.findBinding(WSDLTools.MimeMultipartRelatedBinding)
+ if mime is not None:
+ raise ValueError, 'Mime bindings are not supported.'
+ else:
+ for item in msgrole.findBindings(WSDLTools.SoapHeaderBinding):
+ part = messages[item.message].parts[item.part]
+ header = callinfo.addInHeaderInfo(
+ part.name,
+ part.element or part.type,
+ item.namespace,
+ element_type = part.element and 1 or 0
+ )
+ header.encodingStyle = item.encodingStyle
+
+ body = msgrole.findBinding(WSDLTools.SoapBodyBinding)
+ if body is None:
+ raise ValueError, 'Missing soap:body binding.'
+ callinfo.encodingStyle = body.encodingStyle
+ callinfo.namespace = body.namespace
+ callinfo.use = body.use
+
+ if body.parts is not None:
+ parts = []
+ for name in body.parts:
+ parts.append(message.parts[name])
+ else:
+ parts = message.parts.values()
+
+ for part in parts:
+ callinfo.addInParameter(
+ part.name,
+ part.element or part.type,
+ element_type = part.element and 1 or 0
+ )
+
+ if operation.output is not None:
+ message = messages[operation.output.message]
+ msgrole = opbinding.output
+
+ mime = msgrole.findBinding(WSDLTools.MimeMultipartRelatedBinding)
+ if mime is not None:
+ raise ValueError, 'Mime bindings are not supported.'
+ else:
+ for item in msgrole.findBindings(WSDLTools.SoapHeaderBinding):
+ part = messages[item.message].parts[item.part]
+ header = callinfo.addOutHeaderInfo(
+ part.name,
+ part.element or part.type,
+ item.namespace,
+ element_type = part.element and 1 or 0
+ )
+ header.encodingStyle = item.encodingStyle
+
+ body = msgrole.findBinding(WSDLTools.SoapBodyBinding)
+ if body is None:
+ raise ValueError, 'Missing soap:body binding.'
+ callinfo.encodingStyle = body.encodingStyle
+ callinfo.namespace = body.namespace
+ callinfo.use = body.use
+
+ if body.parts is not None:
+ parts = []
+ for name in body.parts:
+ parts.append(message.parts[name])
+ else:
+ parts = message.parts.values()
+
+ if parts:
+ callinfo.setReturnParameter(
+ parts[0].name,
+ parts[0].element or parts[0].type,
+ element_type = parts[0].element and 1 or 0
+ )
+ for part in parts[1:]:
+ callinfo.addOutParameter(
+ part.name,
+ part.element or part.type,
+ element_type = part.element and 1 or 0
+ )
+
+ return callinfo
+
class ServiceProxy:
"""A ServiceProxy provides a convenient way to call a remote web
@@ -22,7 +241,7 @@
def __init__(self, wsdl, service=None, port=None):
if not hasattr(wsdl, 'targetNamespace'):
- wsdl = WSDLReader().loadFromURL(wsdl)
+ wsdl = WSDLTools.WSDLReader().loadFromURL(wsdl)
# for item in wsdl.types.items():
# self._serializer.loadSchema(item)
self._service = wsdl.services[service or 0]
Index: Utility.py
===================================================================
RCS file: /cvsroot/pywebsvcs/zsi/ZSI/wsdl/Utility.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- Utility.py 18 Mar 2003 05:04:08 -0000 1.1
+++ Utility.py 21 Mar 2003 16:31:25 -0000 1.2
@@ -10,9 +10,110 @@
from string import join, strip, split
from UserDict import UserDict
from StringIO import StringIO
-from Transports import urlopen
import xml.dom.minidom, weakref
+import string, httplib, smtplib, urllib, socket
+from TimeoutSocket import TimeoutSocket, TimeoutError
+from StringIO import StringIO
+from urlparse import urlparse
+from httplib import HTTPConnection, HTTPSConnection
+
+class HTTPResponse:
+ """Captures the information in an HTTP response message."""
+
+ def __init__(self, response):
+ self.status = response.status
+ self.reason = response.reason
+ self.headers = response.msg
+ 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):
+ HTTPConnection.__init__(self, host, port)
+ self.timeout = timeout
+
+ def connect(self):
+ self.sock = TimeoutSocket(self.timeout)
+ self.sock.connect((self.host, self.port))
+
+
+class TimeoutHTTPS(HTTPSConnection):
+ """A custom https object that supports socket timeout. Note that this
+ is not really complete. The builtin SSL support in the Python socket
+ module requires a real socket (type) to be passed in to be hooked to
+ SSL. That means our fake socket won't work and our timeout hacks are
+ bypassed for send and recv calls. Since our hack _is_ in place at
+ connect() time, it should at least provide some timeout protection."""
+ def __init__(self, host, port=None, timeout=20, **kwargs):
+ if not hasattr(socket, 'ssl'):
+ raise ValueError(
+ 'This Python installation does not have SSL support.'
+ )
+ HTTPSConnection.__init__(self, str(host), port, **kwargs)
+ self.timeout = timeout
+
+ def connect(self):
+ sock = TimeoutSocket(self.timeout)
+ sock.connect((self.host, self.port))
+ realsock = getattr(sock.sock, '_sock', sock.sock)
+ ssl = socket.ssl(realsock, self.key_file, self.cert_file)
+ self.sock = httplib.FakeSocket(sock, ssl)
+
+def urlopen(url, timeout=20, redirects=None):
+ """A minimal urlopen replacement hack that supports timeouts for http.
+ Note that this supports GET only."""
+ scheme, host, path, params, query, frag = urlparse(url)
+ 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 scheme == 'https':
+ if not hasattr(socket, 'ssl'):
+ raise ValueError(
+ 'This Python installation does not have SSL support.'
+ )
+ conn = TimeoutHTTPS(host, None, timeout)
+ else:
+ conn = TimeoutHTTP(host, None, timeout)
+
+ conn.putrequest('GET', path)
+ conn.putheader('Connection', 'close')
+ conn.endheaders()
+ response = None
+ while 1:
+ response = conn.getresponse()
+ if response.status != 100:
+ break
+ conn._HTTPConnection__state = httplib._CS_REQ_SENT
+ conn._HTTPConnection__response = None
+
+ status = response.status
+
+ # If we get an HTTP redirect, we will follow it automatically.
+ if status >= 300 and status < 400:
+ location = response.msg.getheader('location')
+ if location is not None:
+ response.close()
+ if redirects is not None and redirects.has_key(location):
+ raise RecursionError(
+ 'Circular HTTP redirection detected.'
+ )
+ if redirects is None:
+ redirects = {}
+ redirects[location] = 1
+ return urlopen(location, timeout, redirects)
+ raise HTTPResponse(response)
+
+ if not (status >= 200 and status < 300):
+ raise HTTPResponse(response)
+
+ body = StringIO(response.read())
+ response.close()
+ return body
class DOM:
"""The DOM singleton defines a number of XML related constants and
@@ -325,17 +426,6 @@
if preserve_ws is None:
value = strip(value)
return value
-
- def elementToStream(self, element, stream, format=0):
- """Write the xml representation of an element to a stream."""
- if format: element.writexml(stream, '', ' ', '\n')
- else: element.writexml(stream)
- return stream
-
- def elementToString(self, element, format=0):
- """Return an xml string representation of an element."""
- method = format and element.toprettyxml or element.toxml
- return method()
def findNamespaceURI(self, prefix, node):
"""Find a namespace uri given a prefix and a context node."""
Index: WSDLTools.py
===================================================================
RCS file: /cvsroot/pywebsvcs/zsi/ZSI/wsdl/WSDLTools.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- WSDLTools.py 18 Mar 2003 05:04:08 -0000 1.1
+++ WSDLTools.py 21 Mar 2003 16:31:25 -0000 1.2
@@ -1,1376 +1,971 @@
-# Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-
-from Utility import DOM, Collection
-from XMLSchema import XMLSchema
[...2316 lines suppressed...]
+ for item in object.extensions:
+ if isinstance(item, kind):
+ result.append(item)
+ return result
+
+def FindExtension(object, kind, t_type=type(())):
+ if isinstance(kind, t_type):
+ namespaceURI, name = kind
+ for item in object.extensions:
+ if not hasattr(item, 'nodeType'):
+ continue
+ if DOM.nsUriMatch(namespaceURI, item.namespaceURI) and \
+ item.name == name:
+ return item
+ else:
+ for item in object.extensions:
+ if isinstance(item, kind):
+ return item
+ return None
+
Index: XMLSchema.py
===================================================================
RCS file: /cvsroot/pywebsvcs/zsi/ZSI/wsdl/XMLSchema.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- XMLSchema.py 18 Mar 2003 05:04:08 -0000 1.1
+++ XMLSchema.py 21 Mar 2003 16:31:25 -0000 1.2
@@ -48,11 +48,6 @@
self.targetNamespace = DOM.getAttr(element, 'targetNamespace')
self.element = element
- def toXML(self, writer):
- strval = DOM.elementToString(self.element)
- writer.writeXML(strval)
-
-
class realXMLSchema:
"""A schema is a collection of schema components derived from one
or more schema documents, that is, one or more <schema> element
--- SOAPCallInfo.py DELETED ---
--- Transports.py DELETED ---
--- XMLWriter.py DELETED ---
|