|
From: <bov...@us...> - 2007-02-21 00:50:38
|
Revision: 1360
http://svn.sourceforge.net/pywebsvcs/?rev=1360&view=rev
Author: boverhof
Date: 2007-02-20 16:50:31 -0800 (Tue, 20 Feb 2007)
Log Message:
-----------
A test/wsdl2py/test_SubstitutionGroup.py
M test/wsdl2py/config.txt
A test/wsdl2py/test_SubstitutionGroup.xsd
M test/wsdl2py/test_Racing.py
-- added unittests
M ZSI/schema.py
M ZSI/generate/containers.py
M ZSI/TC.py
M ZSI/TCcompound.py
[ 1664772 ] substitutionGroups unsupported
-- added substitutionGroup support
Modified Paths:
--------------
trunk/zsi/ZSI/TC.py
trunk/zsi/ZSI/TCcompound.py
trunk/zsi/ZSI/generate/containers.py
trunk/zsi/ZSI/schema.py
trunk/zsi/test/wsdl2py/config.txt
trunk/zsi/test/wsdl2py/test_Racing.py
Added Paths:
-----------
trunk/zsi/test/wsdl2py/test_SubstitutionGroup.py
trunk/zsi/test/wsdl2py/test_SubstitutionGroup.xsd
Modified: trunk/zsi/ZSI/TC.py
===================================================================
--- trunk/zsi/ZSI/TC.py 2007-02-13 17:19:11 UTC (rev 1359)
+++ trunk/zsi/ZSI/TC.py 2007-02-21 00:50:31 UTC (rev 1360)
@@ -1474,6 +1474,10 @@
if pyobj is None:
return
+ # dict is elementName:value pairs
+ if type(pyobj) is dict:
+ return pyobj
+
try:
pyobj.typecode = what
except AttributeError:
Modified: trunk/zsi/ZSI/TCcompound.py
===================================================================
--- trunk/zsi/ZSI/TCcompound.py 2007-02-13 17:19:11 UTC (rev 1359)
+++ trunk/zsi/ZSI/TCcompound.py 2007-02-21 00:50:31 UTC (rev 1360)
@@ -12,8 +12,8 @@
_get_xsitype, TypeCode, Any, AnyElement, AnyType, \
Nilled, UNBOUNDED
-from schema import ElementDeclaration, TypeDefinition, \
- _get_substitute_element, _get_type_definition
+from schema import GED, ElementDeclaration, TypeDefinition, \
+ _get_substitute_element, _get_type_definition, _is_substitute_element
from ZSI.wstools.Namespaces import SCHEMA, SOAP
from ZSI.wstools.Utility import SplitQName
@@ -59,6 +59,10 @@
'bad usage, failed to serialize element reference (%s, %s), in: %s' %
(typecode.nspname, typecode.pname, sw.Backtrace(elt),))
+ # check substitutionGroup
+ if _is_substitute_element(typecode, sub):
+ return sub
+
raise TypeError(\
'failed to serialize (%s, %s) illegal sub GED (%s,%s): %s' %
(typecode.nspname, typecode.pname, sub.nspname, sub.pname,
@@ -70,6 +74,7 @@
'failed to serialize substitute %s for %s, not derivation: %s' %
(sub, typecode, sw.Backtrace(elt),))
+ # Make our substitution type match the elements facets
sub.nspname = typecode.nspname
sub.pname = typecode.pname
sub.aname = typecode.aname
@@ -78,21 +83,7 @@
return sub
-def _get_any_instances(ofwhat, d):
- '''Run thru list ofwhat.anames and find unmatched keys in value
- dictionary d. Assume these are element wildcard instances.
- '''
- any_keys = []
- anames = map(lambda what: what.aname, ofwhat)
- for aname,pyobj in d.items():
- if isinstance(pyobj, AnyType) or aname in anames or pyobj is None:
- continue
- any_keys.append(aname)
- return any_keys
-
-
-
class ComplexType(TypeCode):
'''Represents an element of complexType, potentially containing other
elements.
@@ -192,17 +183,26 @@
self.logger.debug("what: (%s,%s)", what.nspname, what.pname)
for j,c_elt in [ (j, c[j]) for j in crange if c[j] ]:
+ # Parse value, and mark this one done.
if debug:
- self.logger.debug("child node: (%s,%s)", c_elt.namespaceURI,
- c_elt.tagName)
+ self.logger.debug("child node: (%s,%s)", c_elt.namespaceURI, c_elt.tagName)
+
+ match = False
if what.name_match(c_elt):
- # Parse value, and mark this one done.
- try:
- value = what.parse(c_elt, ps)
- except EvaluateException, e:
- #what = _get_substitute_element(c_elt, what)
- #value = what.parse(c_elt, ps)
- raise
+ match = True
+ value = what.parse(c_elt, ps)
+ else:
+ # substitutionGroup head must be a global element declaration
+ # if successful delegate to matching GED
+ subwhat = _get_substitute_element(what, c_elt, ps)
+ if subwhat:
+ match = True
+ value = subwhat.parse(c_elt, ps)
+
+ if debug:
+ self.logger.debug("substitutionGroup: %s", subwhat)
+
+ if match:
if what.maxOccurs > 1:
if v.has_key(what.aname):
v[what.aname].append(value)
@@ -214,11 +214,10 @@
v[what.aname] = value
c[j] = None
break
- else:
- if debug:
- self.logger.debug("no element (%s,%s)",
- what.nspname, what.pname)
+ if debug:
+ self.logger.debug("no element (%s,%s)", what.nspname, what.pname)
+
# No match; if it was supposed to be here, that's an error.
if self.inorder is True and i == j:
raise EvaluateException('Out of order complexType',
Modified: trunk/zsi/ZSI/generate/containers.py
===================================================================
--- trunk/zsi/ZSI/generate/containers.py 2007-02-13 17:19:11 UTC (rev 1359)
+++ trunk/zsi/ZSI/generate/containers.py 2007-02-21 00:50:31 UTC (rev 1360)
@@ -1942,12 +1942,20 @@
raise RuntimeError('Must set style(%s) for typecode list generation' %
self.style)
-
+
class ElementSimpleTypeContainer(TypecodeContainerBase):
type = DEC
logger = _GetLogger("ElementSimpleTypeContainer")
+ def _substitutionGroupTag(self):
+ value = self.substitutionGroup
+ if not value:
+ return 'substitutionGroup = None'
+
+ nsuri,ncname = value
+ return 'substitutionGroup = ("%s","%s")' %(nsuri, ncname)
+
def _setContent(self):
aname = self.getAttributeName(self.name)
pyclass = self.pyclass
@@ -1956,6 +1964,7 @@
if pyclass == 'bool': pyclass = 'int'
kw = KW.copy()
kw.update(dict(aname=aname, ns=self.ns, name=self.name,
+ substitutionGroup=self._substitutionGroupTag(),
subclass=self.sKlass,literal=self.literalTag(),
schema=self.schemaTag(), init=self.simpleConstructor(),
klass=self.getClassName(), element="ElementDeclaration"))
@@ -1993,6 +2002,7 @@
self.local = tp.isLocal()
try:
self.name = tp.getAttribute('name')
+ self.substitutionGroup = tp.getAttribute('substitutionGroup')
self.ns = tp.getTargetNamespace()
qName = tp.getAttribute('type')
except Exception, ex:
@@ -2253,6 +2263,14 @@
type = DEC
logger = _GetLogger("ElementGlobalDefContainer")
+ def _substitutionGroupTag(self):
+ value = self.substitutionGroup
+ if not value:
+ return 'substitutionGroup = None'
+
+ nsuri,ncname = value
+ return 'substitutionGroup = ("%s","%s")' %(nsuri, ncname)
+
def _setContent(self):
'''GED defines element name, so also define typecode aname
'''
@@ -2261,6 +2279,7 @@
kw.update(dict(klass=self.getClassName(),
element='ElementDeclaration',
literal=self.literalTag(),
+ substitutionGroup=self._substitutionGroupTag(),
schema=self.schemaTag(),
init=self.simpleConstructor(),
ns=self.ns, name=self.name,
@@ -2286,6 +2305,7 @@
'%(ID1)sclass %(klass)s(%(element)s):',
'%(ID2)s%(literal)s',
'%(ID2)s%(schema)s',
+ '%(ID2)s%(substitutionGroup)s',
'%(ID2)s%(init)s',
'%(ID3)skw["pname"] = ("%(ns)s","%(name)s")',
'%(ID3)skw["aname"] = "%(aname)s"',
@@ -2301,6 +2321,7 @@
self._item = element
self.local = element.isLocal()
self.name = element.getAttribute('name')
+ self.substitutionGroup = element.getAttribute('substitutionGroup')
self.ns = element.getTargetNamespace()
tp = element.getTypeDefinition('type')
self.sKlass = tp.getAttribute('name')
Modified: trunk/zsi/ZSI/schema.py
===================================================================
--- trunk/zsi/ZSI/schema.py 2007-02-13 17:19:11 UTC (rev 1359)
+++ trunk/zsi/ZSI/schema.py 2007-02-21 00:50:31 UTC (rev 1360)
@@ -3,7 +3,7 @@
'''XML Schema support
'''
-from ZSI import _copyright, _seqtypes, _find_type, EvaluateException
+from ZSI import _copyright, _seqtypes, _find_type, _get_element_nsuri_name, EvaluateException
from ZSI.wstools.Namespaces import SCHEMA, SOAP
from ZSI.wstools.Utility import SplitQName
@@ -14,13 +14,47 @@
def _get_global_element_declaration(namespaceURI, name, **kw):
return SchemaInstanceType.getElementDeclaration(namespaceURI, name, **kw)
-def _get_substitute_element(elt, what):
- raise NotImplementedError, 'Not implemented'
+def _get_substitute_element(head, elt, ps):
+ '''if elt matches a member of the head substitutionGroup, return
+ the GED typecode.
+ head -- ElementDeclaration typecode,
+ elt -- the DOM element being parsed
+ ps -- ParsedSoap Instance
+ '''
+ if not isinstance(head, ElementDeclaration):
+ return None
+
+ return ElementDeclaration.getSubstitutionElement(head, elt, ps)
+
def _has_type_definition(namespaceURI, name):
return SchemaInstanceType.getTypeDefinition(namespaceURI, name) is not None
+def _is_substitute_element(head, sub):
+ '''if head and sub are both GEDs, and sub declares
+ head as its substitutionGroup then return True.
+ head -- Typecode instance
+ sub -- Typecode instance
+ '''
+ if not isinstance(head, ElementDeclaration) or not isinstance(sub, ElementDeclaration):
+ return False
+
+ try:
+ group = sub.substitutionGroup
+ except AttributeError:
+ return False
+
+ ged = GED(*group)
+
+ # TODO: better way of representing element references. Wrap them with
+ # facets, and dereference when needed and delegate to..
+ print (head.nspname == ged.nspname and head.pname == ged.pname)
+ if head is ged or not (head.nspname == ged.nspname and head.pname == ged.pname):
+ return False
+
+ return True
+
#
# functions for retrieving schema items from
# the global schema instance.
@@ -67,6 +101,7 @@
types = {}
elements = {}
element_typecode_cache = {}
+ #substitution_registry = {}
def __new__(cls,classname,bases,classdict):
'''If classdict has literal and schema register it as a
@@ -81,10 +116,23 @@
raise AttributeError, 'ElementDeclaration must define schema and literal attributes'
key = (classdict['schema'],classdict['literal'])
- if SchemaInstanceType.elements.has_key(key) is False:
- SchemaInstanceType.elements[key] = type.__new__(cls,classname,bases,classdict)
- return SchemaInstanceType.elements[key]
+ if SchemaInstanceType.elements.has_key(key):
+ return SchemaInstanceType.elements[key]
+ # create global element declaration
+ ged = SchemaInstanceType.elements[key] = type.__new__(cls,classname,bases,classdict)
+
+ # TODO: Maybe I want access to all registrants??
+ #
+ #if classdict.has_key('substitutionGroup'):
+ # sub = classdict.has_key('substitutionGroup')
+ # if not SchemaInstanceType.substitution_registry.has_key(sub):
+ # SchemaInstanceType.substitution_registry[sub] = [ged]
+ # else:
+ # SchemaInstanceType.substitution_registry[sub].append(ged)
+
+ return ged
+
if TypeDefinition in bases:
if classdict.has_key('type') is None:
raise AttributeError, 'TypeDefinition must define type attribute'
@@ -148,10 +196,60 @@
schema = namespaceURI
literal = NCName
+ substitutionGroup -- GED reference of form, (namespaceURI,NCName)
'''
__metaclass__ = SchemaInstanceType
-
+ def checkSubstitute(self, typecode):
+ '''If this is True, allow typecode to be substituted
+ for "self" typecode.
+ '''
+ if not isinstance(typecode, ElementDeclaration):
+ return False
+
+ try:
+ nsuri,ncname = typecode.substitutionGroup
+ except AttributeError:
+ return False
+
+ if (nsuri,ncname) != (self.schema,self.literal):
+ # allow slop with the empty namespace
+ if not nsuri and not self.schema and ncname == self.literal:
+ return True
+
+ return False
+
+ sub = GED(self.schema, self.literal)
+ if sub is None or sub is not typecode:
+ return False
+
+ return True
+
+ def getSubstitutionElement(self, elt, ps):
+ '''if elt matches a member of the head substitutionGroup, return
+ the GED typecode representation of the member.
+
+ head -- ElementDeclaration typecode,
+ elt -- the DOM element being parsed
+ ps -- ParsedSoap instance
+ '''
+ nsuri,ncname = _get_element_nsuri_name(elt)
+ typecode = GED(nsuri,ncname)
+ if typecode is None:
+ return
+
+ try:
+ nsuri,ncname = typecode.substitutionGroup
+ except AttributeError:
+ return
+
+ if (ncname == self.pname) and (nsuri == self.nspname or
+ (not nsuri and not self.nspname)):
+ return typecode
+
+ return
+
+
class LocalElementDeclaration:
'''Typecodes subclass to represent a Local Element Declaration.
'''
@@ -273,8 +371,8 @@
during parsing is retained in the pyobj representation
and thus can be serialized.
'''
- types_dict = {}
-
+ types_dict = dict()
+
def RegisterBuiltin(cls, arg):
'''register a builtin, create a new wrapper.
'''
Modified: trunk/zsi/test/wsdl2py/config.txt
===================================================================
--- trunk/zsi/test/wsdl2py/config.txt 2007-02-13 17:19:11 UTC (rev 1359)
+++ trunk/zsi/test/wsdl2py/config.txt 2007-02-21 00:50:31 UTC (rev 1360)
@@ -19,7 +19,7 @@
#
##########################################################################
[configuration]
-tracefile = 1
+tracefile = False
debug = False
skip = False
twisted = False
@@ -119,7 +119,7 @@
document = True
literal = True
broke = False
-tests = test_MapPoint test_Echo test_AWSECommerceService test_FinancialService test_BasicComm test_Manufacturer test_Racing test_Attributes test_Choice test_DerivedTypes test_EchoWSAddr200403
+tests = test_MapPoint test_Echo test_AWSECommerceService test_FinancialService test_BasicComm test_Manufacturer test_Racing test_Attributes test_Choice test_DerivedTypes test_EchoWSAddr200403 test_SubstitutionGroup
[doc_literal_broke]
document = True
@@ -157,6 +157,7 @@
test_Choice = test_Choice.xsd
test_Attributes = test_Attributes.xsd
test_DerivedTypes = test_DerivedTypes.xsd
+test_SubstitutionGroup = test_SubstitutionGroup.xsd
test_SquareService = SquareService.wsdl
test_DateService = DateService.wsdl
Modified: trunk/zsi/test/wsdl2py/test_Racing.py
===================================================================
--- trunk/zsi/test/wsdl2py/test_Racing.py 2007-02-13 17:19:11 UTC (rev 1359)
+++ trunk/zsi/test/wsdl2py/test_Racing.py 2007-02-21 00:50:31 UTC (rev 1360)
@@ -5,7 +5,7 @@
###########################################################################
import os, sys, unittest
from ServiceTest import main, ServiceTestCase, ServiceTestSuite
-from ZSI import FaultException, ParsedSoap
+from ZSI import FaultException, ParsedSoap, SoapWriter
"""
Unittest
@@ -61,6 +61,21 @@
pyobj.EventApproximatesResult.Any, any))
+ pyobj.EventApproximatesResult.Any = dict(pyobj.EventApproximatesResult.Any)
+ sw = SoapWriter()
+ sw.serialize(pyobj)
+ print str(sw)
+ ps2 = ParsedSoap(str(sw))
+ pyobj2 = ps.Parse(self.client_module.EventApproximatesSoapOut.typecode)
+ print "EAR: ", pyobj2.EventApproximatesResult
+ print "Any: ", pyobj2.EventApproximatesResult.Any
+
+
+ self.failUnless(pyobj.EventApproximatesResult.Any == pyobj2.EventApproximatesResult.Any,
+ 'Failed match:\n %s\n\n%s' %(pyobj.EventApproximatesResult.Any, pyobj2.EventApproximatesResult.Any))
+
+
+
MSG="""<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
Added: trunk/zsi/test/wsdl2py/test_SubstitutionGroup.py
===================================================================
--- trunk/zsi/test/wsdl2py/test_SubstitutionGroup.py (rev 0)
+++ trunk/zsi/test/wsdl2py/test_SubstitutionGroup.py 2007-02-21 00:50:31 UTC (rev 1360)
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+############################################################################
+# Joshua R. Boverhof, LBNL
+# See LBNLCopyright for copyright notice!
+###########################################################################
+import os, sys, unittest, time
+from ServiceTest import main, ServiceTestCase, ServiceTestSuite
+from ZSI import FaultException
+from ZSI.TC import _get_global_element_declaration as GED
+from ZSI.writer import SoapWriter
+from ZSI.parse import ParsedSoap
+
+"""
+Unittest for substitutionGroup
+[ ]
+
+XSD:
+"""
+
+# General targets
+def dispatch():
+ """Run all dispatch tests"""
+ suite = ServiceTestSuite()
+ suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_dispatch'))
+ return suite
+
+def local():
+ """Run all local tests"""
+ suite = ServiceTestSuite()
+ suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_local'))
+ return suite
+
+def net():
+ """Run all network tests"""
+ suite = ServiceTestSuite()
+ suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_net'))
+ return suite
+
+def all():
+ """Run all tests"""
+ suite = ServiceTestSuite()
+ suite.addTest(unittest.makeSuite(SubstitutionGroupTestCase, 'test_'))
+ return suite
+
+
+class SubstitutionGroupTestCase(ServiceTestCase):
+ name = "test_SubstitutionGroup"
+ types_file_name = "test_SubstitutionGroup_xsd_types.py"
+
+ def __init__(self, methodName):
+ ServiceTestCase.__init__(self, methodName)
+ self.wsdl2py_args.append('-b')
+ self.wsdl2py_args.append('-x')
+
+ def test_local_attribute1(self):
+ """
+ """
+ self.types_module
+
+ xml = """<?xml version="1.0" encoding="UTF-8"?>
+ <holder xmlns='urn:subGroup:types'>
+ <baseElt><base>from base</base></baseElt>
+ <childElt><base>from base</base><child>from child</child></childElt></holder>"""
+
+ ps = ParsedSoap(xml, envelope=False)
+ p1 = ps.Parse(GED("urn:subGroup:types", "holder"))
+
+ b1 = p1.BaseElt[0]
+ c1 = p1.BaseElt[1]
+
+ sw = SoapWriter(envelope=False)
+ sw.serialize(p1)
+
+ ps = ParsedSoap(str(sw), envelope=False)
+ p2 = ps.Parse(GED("urn:subGroup:types", "holder"))
+ b2 = p2.BaseElt[0]
+ c2 = p2.BaseElt[1]
+
+ self.failUnlessEqual(b1.Base, b2.Base)
+ self.failUnlessEqual(c1.Base, c2.Base)
+ self.failUnlessEqual(c1.Child, c2.Child)
+
+
+
+if __name__ == "__main__" :
+ main()
+
Added: trunk/zsi/test/wsdl2py/test_SubstitutionGroup.xsd
===================================================================
--- trunk/zsi/test/wsdl2py/test_SubstitutionGroup.xsd (rev 0)
+++ trunk/zsi/test/wsdl2py/test_SubstitutionGroup.xsd 2007-02-21 00:50:31 UTC (rev 1360)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:tns="urn:subGroup:types"
+ targetNamespace="urn:subGroup:types"
+ elementFormDefault='qualified'>
+
+ <xsd:complexType name='baseType'>
+ <xsd:sequence>
+ <xsd:element name="base" type='xsd:string'/>
+ <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name='childType'>
+ <xsd:complexContent>
+ <xsd:extension base="tns:baseType">
+ <xsd:sequence>
+ <xsd:element name="child" type='xsd:string'/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:element name="baseElt" type="tns:baseType"/>
+ <xsd:element name="childElt" type="tns:childType" substitutionGroup='tns:baseElt'/>
+
+ <!-- Holder type -->
+ <xsd:complexType name='holderType'>
+ <xsd:sequence>
+ <xsd:element ref="tns:baseElt" maxOccurs='unbounded'/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:element name='holder' type='tns:holderType'/>
+
+</xsd:schema>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|