Browse Source

----------------------------------------------------------------------

Modified Files:

        Utility.py -- added a CollectionNS class that keys items via
            (targetNamespace, name).

        WSDLTools.py --

            Made WSDL Collections into CollectionNS instances,
            this fixes problem with collisions, caused by wsdl:imports,
            between items with same name but defined in different
            targetNamespaces.  So now all items can be accessed via
            (namespace,name), but ONLY those items defined in
            WSDL.targetNamepsace (not an import.targetNamespace) can
            be accessed using just 'name'.

            Also changed how portType is "loaded".  Now instead of
            dropping all the operation nodes in "load", I drop
            the portType node into "load".  This makes sense because
            portType really should know about itself, and the
            XML Schema definition of "portType" includes an "anyAttribute"
            and I need to make this stuff available.  I may change the
            other WSDL information items to do this to be consistent.

 ----------------------------------------------------------------------
main
Joshua Boverhof 21 years ago
parent
commit
b3575379e4
2 changed files with 111 additions and 17 deletions
  1. +52
    -0
      Utility.py
  2. +59
    -17
      WSDLTools.py

+ 52
- 0
Utility.py View File

@@ -9,6 +9,7 @@


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


import types
from string import join, strip, split from string import join, strip, split
from UserDict import UserDict from UserDict import UserDict
from StringIO import StringIO from StringIO import StringIO
@@ -421,6 +422,14 @@ class DOM:
return default return default
return '' return ''


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

def getElementText(self, node, preserve_ws=None): def getElementText(self, node, preserve_ws=None):
"""Return the text value of an xml element node. Leading and trailing """Return the text value of an xml element node. Leading and trailing
whitespace is stripped from the value unless the preserve_ws flag whitespace is stripped from the value unless the preserve_ws flag
@@ -584,6 +593,49 @@ class Collection(UserDict):
return self.list return self.list




class CollectionNS(UserDict):
"""Helper class for maintaining ordered named collections."""
default = lambda self,k: k.name
def __init__(self, parent, key=None):
UserDict.__init__(self)
self.parent = weakref.ref(parent)
self.targetNamespace = None
self.list = []
self._func = key or self.default

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

def __setitem__(self, key, item):
item.parent = weakref.ref(self)
self.list.append(item)
targetNamespace = getattr(item, 'targetNamespace', self.parent().targetNamespace)
if not self.data.has_key(targetNamespace):
self.data[targetNamespace] = {}
self.data[targetNamespace][key] = item

def __isSequence(self, key):
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()))
return keys

def items(self):
return map(lambda i: (self._func(i), i), self.list)

def values(self):
return self.list




# This is a runtime guerilla patch for pulldom (used by minidom) so # This is a runtime guerilla patch for pulldom (used by minidom) so
# that xml namespace declaration attributes are not lost in parsing. # that xml namespace declaration attributes are not lost in parsing.


+ 59
- 17
WSDLTools.py View File

@@ -9,7 +9,7 @@


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


from Utility import DOM, Collection
from Utility import DOM, Collection, CollectionNS
from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter from XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter
from StringIO import StringIO from StringIO import StringIO
import urllib import urllib
@@ -64,10 +64,10 @@ class WSDL:
self.location = None self.location = None
self.document = None self.document = None
self.name = None self.name = None
self.services = Collection(self)
self.messages = Collection(self)
self.portTypes = Collection(self)
self.bindings = Collection(self)
self.services = CollectionNS(self)
self.messages = CollectionNS(self)
self.portTypes = CollectionNS(self)
self.bindings = CollectionNS(self)
self.imports = Collection(self) self.imports = Collection(self)
self.types = Types(self) self.types = Types(self)
self.extensions = [] self.extensions = []
@@ -80,39 +80,47 @@ class WSDL:


version = '1.1' version = '1.1'


def addService(self, name, documentation=''):
def addService(self, name, documentation='', targetNamespace=None):
if self.services.has_key(name): if self.services.has_key(name):
raise WSDLError( raise WSDLError(
'Duplicate service element: %s' % name 'Duplicate service element: %s' % name
) )
item = Service(name, documentation) item = Service(name, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.services[name] = item self.services[name] = item
return item return item


def addMessage(self, name, documentation=''):
def addMessage(self, name, documentation='', targetNamespace=None):
if self.messages.has_key(name): if self.messages.has_key(name):
raise WSDLError( raise WSDLError(
'Duplicate message element: %s.' % name 'Duplicate message element: %s.' % name
) )
item = Message(name, documentation) item = Message(name, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.messages[name] = item self.messages[name] = item
return item return item


def addPortType(self, name, documentation=''):
def addPortType(self, name, documentation='', targetNamespace=None):
if self.portTypes.has_key(name): if self.portTypes.has_key(name):
raise WSDLError( raise WSDLError(
'Duplicate portType element: name' 'Duplicate portType element: name'
) )
item = PortType(name, documentation) item = PortType(name, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.portTypes[name] = item self.portTypes[name] = item
return item return item


def addBinding(self, name, type, documentation=''):
def addBinding(self, name, type, documentation='', targetNamespace=None):
if self.bindings.has_key(name): if self.bindings.has_key(name):
raise WSDLError( raise WSDLError(
'Duplicate binding element: %s' % name 'Duplicate binding element: %s' % name
) )
item = Binding(name, type, documentation) item = Binding(name, type, documentation)
if targetNamespace:
item.targetNamespace = targetNamespace
self.bindings[name] = item self.bindings[name] = item
return item return item


@@ -158,6 +166,7 @@ class WSDL:


reader = SchemaReader(base_url=self.location) reader = SchemaReader(base_url=self.location)
for element in DOM.getElements(definitions, None, None): for element in DOM.getElements(definitions, None, None):
targetNamespace = DOM.getAttr(element, 'targetNamespace')
localName = element.localName localName = element.localName


if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL): if not DOM.nsUriMatch(element.namespaceURI, NS_WSDL):
@@ -172,7 +181,7 @@ class WSDL:
elif localName == 'message': elif localName == 'message':
name = DOM.getAttr(element, 'name') name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element) docs = GetDocumentation(element)
message = self.addMessage(name, docs)
message = self.addMessage(name, docs, targetNamespace)
parts = DOM.getElements(element, 'part', NS_WSDL) parts = DOM.getElements(element, 'part', NS_WSDL)
message.load(parts) message.load(parts)
continue continue
@@ -180,9 +189,10 @@ class WSDL:
elif localName == 'portType': elif localName == 'portType':
name = DOM.getAttr(element, 'name') name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element) docs = GetDocumentation(element)
ptype = self.addPortType(name, docs)
operations = DOM.getElements(element, 'operation', NS_WSDL)
ptype.load(operations)
ptype = self.addPortType(name, docs, targetNamespace)
#operations = DOM.getElements(element, 'operation', NS_WSDL)
#ptype.load(operations)
ptype.load(element)
continue continue


elif localName == 'binding': elif localName == 'binding':
@@ -194,7 +204,7 @@ class WSDL:
) )
type = type.split(':', 1)[-1] type = type.split(':', 1)[-1]
docs = GetDocumentation(element) docs = GetDocumentation(element)
binding = self.addBinding(name, type, docs)
binding = self.addBinding(name, type, docs, targetNamespace)
operations = DOM.getElements(element, 'operation', NS_WSDL) operations = DOM.getElements(element, 'operation', NS_WSDL)
binding.load(operations) binding.load(operations)
binding.load_ex(GetExtensions(element)) binding.load_ex(GetExtensions(element))
@@ -203,7 +213,7 @@ class WSDL:
elif localName == 'service': elif localName == 'service':
name = DOM.getAttr(element, 'name') name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element) docs = GetDocumentation(element)
service = self.addService(name, docs)
service = self.addService(name, docs, targetNamespace)
ports = DOM.getElements(element, 'port', NS_WSDL) ports = DOM.getElements(element, 'port', NS_WSDL)
service.load(ports) service.load(ports)
service.load_ex(GetExtensions(element)) service.load_ex(GetExtensions(element))
@@ -350,11 +360,37 @@ class MessagePart(Element):
self.element = None self.element = None
self.type = None self.type = None


def getWSDL(self):
"""Return the WSDL object that contains this Message Part."""
return self.parent().parent().parent().parent()

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

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



class PortType(Element): class PortType(Element):
'''PortType has a anyAttribute, thus must provide for an extensible
mechanism for supporting such attributes.

Instance Data:
operations --
attributes --

'''

def __init__(self, name, documentation=''): def __init__(self, name, documentation=''):
Element.__init__(self, name, documentation) Element.__init__(self, name, documentation)
self.operations = Collection(self) self.operations = Collection(self)
self.attributes = {}


def getWSDL(self): def getWSDL(self):
return self.parent().parent() return self.parent().parent()
@@ -364,7 +400,13 @@ class PortType(Element):
self.operations[name] = item self.operations[name] = item
return item return item


def load(self, elements):
def load(self, element):
self.name = DOM.getAttr(element, 'name')
self.documentation = GetDocumentation(element)
self.attributes.update(DOM.getAttrs(element))

NS_WSDL = DOM.GetWSDLUri(self.getWSDL().version)
elements = DOM.getElements(element, 'operation', NS_WSDL)
for element in elements: for element in elements:
name = DOM.getAttr(element, 'name') name = DOM.getAttr(element, 'name')
docs = GetDocumentation(element) docs = GetDocumentation(element)
@@ -424,7 +466,7 @@ class Operation(Element):
wsdl = self.getPortType().getWSDL() wsdl = self.getPortType().getWSDL()
return wsdl.messages[self.faults[name].message] return wsdl.messages[self.faults[name].message]


def addFault(self, name, message, documentation=''):
def addFault(self, message, name, documentation=''):
if self.faults.has_key(name): if self.faults.has_key(name):
raise WSDLError( raise WSDLError(
'Duplicate fault element: %s' % name 'Duplicate fault element: %s' % name


Loading…
Cancel
Save