From: <bov...@us...> - 2006-10-13 23:35:33
|
Revision: 1266 http://svn.sourceforge.net/pywebsvcs/?rev=1266&view=rev Author: boverhof Date: 2006-10-13 16:35:29 -0700 (Fri, 13 Oct 2006) Log Message: ----------- M test/test_t8.py M ZSI/TCnumbers.py M ZSI/TC.py M ZSI/TCcompound.py M doc/c06-tc.tex -- added some of the examples to unittest code -- some cleanup in code, remove outdated stuff, comments, use booleans. -- updates to Typecode chapter Modified Paths: -------------- trunk/zsi/ZSI/TC.py trunk/zsi/ZSI/TCcompound.py trunk/zsi/ZSI/TCnumbers.py trunk/zsi/doc/c06-tc.tex trunk/zsi/test/test_t8.py Modified: trunk/zsi/ZSI/TC.py =================================================================== --- trunk/zsi/ZSI/TC.py 2006-10-13 00:12:32 UTC (rev 1265) +++ trunk/zsi/ZSI/TC.py 2006-10-13 23:35:29 UTC (rev 1266) @@ -842,7 +842,7 @@ type = (SCHEMA.XSD3, 'string') logger = _GetLogger('ZSI.TC.String') - def __init__(self, pname=None, strip=1, **kw): + def __init__(self, pname=None, strip=True, **kw): TypeCode.__init__(self, pname, **kw) if kw.has_key('resolver'): self.resolver = kw['resolver'] self.strip = strip @@ -852,7 +852,7 @@ ''' if self.strip: text = text.strip() if self.pyclass is not None: - return self.pyclass(text) + return self.pyclass(text) return text def get_formatted_content(self, pyobj): @@ -1047,7 +1047,14 @@ ps.Backtrace(elt)) return val + def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): + if pyobj not in self.choices: + raise EvaluateException('Value not in enumeration list', + ps.Backtrace(elt)) + String.serialize(self, elt, sw, pyobj, name=name, orig=orig, **kw) + + # This is outside the Integer class purely for code esthetics. _ignored = [] Modified: trunk/zsi/ZSI/TCcompound.py =================================================================== --- trunk/zsi/ZSI/TCcompound.py 2006-10-13 00:12:32 UTC (rev 1265) +++ trunk/zsi/ZSI/TCcompound.py 2006-10-13 23:35:29 UTC (rev 1266) @@ -96,10 +96,9 @@ logger = _GetLogger('ZSI.TCcompound.ComplexType') def __init__(self, pyclass, ofwhat, pname=None, inorder=False, inline=False, - mutable=True, hasextras=0, mixed=False, mixed_aname='_text', **kw): + mutable=True, mixed=False, mixed_aname='_text', **kw): '''pyclass -- the Python class to hold the fields ofwhat -- a list of fields to be in the complexType - hasextras -- ignore extra input fields inorder -- fields must be in exact order or not inline -- don't href/id when serializing mutable -- object could change between multiple serializations @@ -117,7 +116,6 @@ self.mixed_aname = mixed_aname if self.mutable is True: self.inline = True - self.hasextras = hasextras self.type = kw.get('type') or _get_xsitype(self) t = type(ofwhat) if t not in _seqtypes: @@ -158,16 +156,6 @@ c = _child_elements(elt) count = len(c) if self.nilled(elt, ps): return Nilled -# repeatable_args = False -# for tc in self.ofwhat: -# if tc.maxOccurs > 1: -# repeatable_args = True -# break -# -# if not repeatable_args: -# if count > len(self.ofwhat) and not self.hasextras: -# raise EvaluateException('Too many sub-elements (%d>%d)' %( -# count,len(self.ofwhat)), ps.Backtrace(elt)) # Create the object. v = {} @@ -268,11 +256,7 @@ # type definition must be informed of element tag (nspname,pname), # element declaration is initialized with a tag. try: - if issubclass(self.pyclass, ElementDeclaration) is False and\ - issubclass(self.pyclass, TypeDefinition) is True: - pyobj = self.pyclass((self.nspname,self.pname)) - else: - pyobj = self.pyclass() + pyobj = self.pyclass() except Exception, e: raise TypeError("Constructing element (%s,%s) with pyclass(%s), %s" \ %(self.nspname, self.pname, self.pyclass.__name__, str(e))) @@ -469,7 +453,7 @@ class Struct(ComplexType): '''Struct is a complex type for accessors identified by name. - Constraint: No element may be have the same name as any other, + Constraint: No element may have the same name as any other, nor may any element have a maxOccurs > 1. <xs:group name="Struct" > @@ -486,17 +470,16 @@ logger = _GetLogger('ZSI.TCcompound.Struct') def __init__(self, pyclass, ofwhat, pname=None, inorder=False, inline=False, - mutable=True, hasextras=0, **kw): + mutable=True, **kw): '''pyclass -- the Python class to hold the fields ofwhat -- a list of fields to be in the struct - hasextras -- ignore extra input fields inorder -- fields must be in exact order or not inline -- don't href/id when serializing mutable -- object could change between multiple serializations ''' ComplexType.__init__(self, pyclass, ofwhat, pname=pname, inorder=inorder, inline=inline, mutable=mutable, - hasextras=hasextras, **kw + **kw ) # Check Constraints @@ -533,7 +516,7 @@ raise TypeError("Only single-dimensioned arrays supported") self.fill = fill self.sparse = sparse - if self.sparse: ofwhat.optional = 1 + #if self.sparse: ofwhat.minOccurs = 0 self.mutable = mutable self.size = size self.nooffset = nooffset Modified: trunk/zsi/ZSI/TCnumbers.py =================================================================== --- trunk/zsi/ZSI/TCnumbers.py 2006-10-13 00:12:32 UTC (rev 1265) +++ trunk/zsi/ZSI/TCnumbers.py 2006-10-13 23:35:29 UTC (rev 1266) @@ -126,6 +126,13 @@ ps.Backtrace(elt)) return val + def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): + if pyobj not in self.choices: + raise EvaluateException('Value not in int enumeration list', + ps.Backtrace(elt)) + Integer.serialize(self, elt, sw, pyobj, name=name, orig=orig, **kw) + + class FPfloat(Decimal): '''IEEE 32bit floating point value. ''' @@ -166,5 +173,12 @@ '" not in enumeration list', ps.Backtrace(elt)) return val + + def serialize(self, elt, sw, pyobj, name=None, orig=None, **kw): + if pyobj not in self.choices: + raise EvaluateException('Value not in int enumeration list', + ps.Backtrace(elt)) + Decimal.serialize(self, elt, sw, pyobj, name=name, orig=orig, **kw) + if __name__ == '__main__': print _copyright Modified: trunk/zsi/doc/c06-tc.tex =================================================================== --- trunk/zsi/doc/c06-tc.tex 2006-10-13 00:12:32 UTC (rev 1265) +++ trunk/zsi/doc/c06-tc.tex 2006-10-13 23:35:29 UTC (rev 1266) @@ -35,9 +35,11 @@ The \code{nsdict} parameter to the \class{SoapWriter} construct can be used to specify prefix to namespace-URI mappings, these are otherwise handled automatically. +\section{\class{TC.TypeCode}} + +The \class{TypeCode} class is the parent class of all typecodes. + \begin{classdesc}{TypeCode}{**keywords} -The \code{pname} - The following keyword arguments may be used: \begin{tableiii}{l|c|p{30em}}{textrm}{Keyword}{Default}{Description} @@ -150,7 +152,8 @@ for the fourth. \subsection{compound data} -- Struct or Array -Compound data, such as a \code{struct}, may also be self-describing: +Compound data, such as a \code{struct}, may also be self-describing (namespace +are omitted for clarity): \begin{verbatim} <tns:foo> <tns:i xsi:type="SOAP-ENC:integer">12</tns:i> @@ -161,8 +164,11 @@ If this is parsed with a \class{TC.Any} typecode, either a Python \code{dict} is created or if \code{aslist} is True a \code{list}: \begin{verbatim} +ps = ParsedSoap(xml, envelope=False) +print ps.Parse(TC.Any()) { 'name': u'Hello world', 'i': 12 } +print ps.Parse(TC.Any(aslist=True)) [ 12, u'Hello world' ] \end{verbatim} Note that one preserves order, while the other preserves the element names. @@ -193,8 +199,18 @@ This class would know that the \code{i} element is an integer, so that the explicit typing becomes optional, rather than required. -The rest of this section describes how to add new -types to the \ZSI{} typecode engine. +\subsection{Adding new types} Most of the \class{TypeCodes} classes in +\module{TC} are registered with \class{Any}, making an instance of itself +available for dynamic typing. New \class{TypeCode} classes can be created and +registered with \class{Any} by using \function{RegisterType}. In order to +override an existing entry in the registry call \function{RegisterType} with +\code{clobber=True}. The serialization entries are mappings between builtin +Python types and a \class{TypeCode} instance, it is not possible to have one +Python type map to multiple typecodes. The parsing entries are mappings +between \code{(namespaceURI,name)} tuples, representing the \code{xsi:type} +attribute, and a \class{TypeCode} instance. Thus, only one instance of a +\class{TypeCode} class can represent a XML Schema type. So this mechanism is +not appropriate for representing XML Schema element information. \begin{classdesc}{\emph{NEWTYPECODE}(TypeCode)}{...} The new typecode should be derived from the \class{TC.TypeCode} class, and @@ -272,15 +288,21 @@ processed as dynamic types. This may be acceptable in some environments. +\section{\class{TC.SimpleType}} +Parent class of all simple types. + +\begin{memberdesc}{empty_content} +This is a class attribute. +Value returned when tag or node is present, is not nilled, and without text +content. +\end{memberdesc} + \section{Strings} -SOAP Strings are Python strings. -If the value to be serialized is a Python sequence, then an \code{href} -is generated, with the first element of the sequence used as the URI. -This can be used, for example, when generating SOAP with attachments. +SOAP/XMLSchema Strings are Python strings. \begin{classdesc}{String}{name\optional{, **keywords}} -The parent type of all SOAP strings. +The parent type of all strings. The following keyword arguments may be used: @@ -288,17 +310,14 @@ \lineiii{\code{resolver}}{\code{None}}{A function that can resolve an absolute URI and return its content as a string, as described in the \class{ParsedSoap} description.} -\lineiii{\code{strip}}{\code{1}}{If true, leading and trailing whitespace +\lineiii{\code{strip}}{\code{True}}{If true, leading and trailing whitespace are stripped from the content.} -\lineiii{\code{textprotect}}{\code{1}}{If true, less-than and ampersand -characters are replaced with \code{\<} and \code{\&}, respectively. -\versionadded{1.1}} \end{tableiii} \end{classdesc} \begin{classdesc}{Enumeration}{value_list, name\optional{, **keywords}} Like \class{TC.String}, but the value must be a member of -the \code{value_list} sequence of text strings +the \code{choices} sequence of text strings \end{classdesc} In addition to \class{TC.String}, @@ -374,9 +393,9 @@ \section{Integers} -SOAP integers are Python integers. +SOAP/XMLSchema integers are Python integers. -\begin{classdesc}{Integer}{name\optional{, **keywords}} +\begin{classdesc}{Integer}{\optional{**keywords}} The parent type of all integers. This class handles any of the several types (and ranges) of SOAP integers. @@ -388,66 +407,66 @@ \end{tableiii} \end{classdesc} -\begin{classdesc}{IEnumeration}{value_list, name\optional{, **keywords}} +\begin{classdesc}{IEnumeration}{choices\optional{, **keywords}} Like \class{TC.Integer}, but the value must be a member of -the \code{value_list} sequence. +the \code{choices} sequence. \end{classdesc} A number of sub-classes are defined to handle smaller-ranged numbers. -\begin{classdesc}{Ibyte}{name\optional{, **keywords}} +\begin{classdesc}{Ibyte}{\optional{**keywords}} A signed eight-bit value. \end{classdesc} -\begin{classdesc}{IunsignedByte}{name\optional{, **keywords}} +\begin{classdesc}{IunsignedByte}{\optional{**keywords}} An unsigned eight-bit value. \end{classdesc} -\begin{classdesc}{Ishort}{name\optional{, **keywords}} +\begin{classdesc}{Ishort}{\optional{**keywords}} A signed 16-bit value. \end{classdesc} -\begin{classdesc}{IunsignedShort}{name\optional{, **keywords}} +\begin{classdesc}{IunsignedShort}{\optional{**keywords}} An unsigned 16-bit value. \end{classdesc} -\begin{classdesc}{Iint}{name\optional{, **keywords}} +\begin{classdesc}{Iint}{\optional{**keywords}} A signed 32-bit value. \end{classdesc} -\begin{classdesc}{IunsignedInt}{name\optional{, **keywords}} +\begin{classdesc}{IunsignedInt}{\optional{**keywords}} An unsigned 32-bit value. \end{classdesc} -\begin{classdesc}{Ilong}{name\optional{, **keywords}} +\begin{classdesc}{Ilong}{\optional{**keywords}} An signed 64-bit value. \end{classdesc} -\begin{classdesc}{IunsignedLong}{name\optional{, **keywords}} +\begin{classdesc}{IunsignedLong}{\optional{**keywords}} An unsigned 64-bit value. \end{classdesc} -\begin{classdesc}{IpositiveInteger}{name\optional{, **keywords}} +\begin{classdesc}{IpositiveInteger}{\optional{**keywords}} A value greater than zero. \end{classdesc} -\begin{classdesc}{InegativeInteger}{name\optional{, **keywords}} +\begin{classdesc}{InegativeInteger}{\optional{**keywords}} A value less than zero. \end{classdesc} -\begin{classdesc}{InonPositiveInteger}{name\optional{, **keywords}} +\begin{classdesc}{InonPositiveInteger}{\optional{**keywords}} A value less than or equal to zero. \end{classdesc} -\begin{classdesc}{InonNegativeInteger}{name\optional{, **keywords}} +\begin{classdesc}{InonNegativeInteger}{\optional{**keywords}} A value greater than or equal to zero. \end{classdesc} \section{Floating-point Numbers} -SOAP floating point numbers are Python floats. +SOAP/XMLSchema floating point numbers are Python floats. -\begin{classdesc}{Decimal}{name\optional{, **keywords}} +\begin{classdesc}{Decimal}{\optional{**keywords}} The parent type of all floating point numbers. This class handles any of the several types (and ranges) of SOAP floating point numbers. @@ -515,43 +534,43 @@ When serializing, an integral or floating point number is taken as the number of seconds since the epoch, in UTC. -\begin{classdesc}{Duration}{name\optional{, **keywords}} +\begin{classdesc}{Duration}{\optional{**keywords}} A relative time period. Negative durations have all values less than zero; this makes it easy to add a duration to a Python time tuple. \end{classdesc} -\begin{classdesc}{Gregorian}{name\optional{, **keywords}} +\begin{classdesc}{Gregorian}{\optional{**keywords}} An absolute time period. This class should not be instantiated directly; use one of the \code{gXXX} classes instead. \end{classdesc} -\begin{classdesc}{gDateTime}{name\optional{, **keywords}} +\begin{classdesc}{gDateTime}{\optional{**keywords}} A date and time. \end{classdesc} -\begin{classdesc}{gDate}{name\optional{, **keywords}} +\begin{classdesc}{gDate}{\optional{**keywords}} A date. \end{classdesc} -\begin{classdesc}{gYearMonth}{name\optional{, **keywords}} +\begin{classdesc}{gYearMonth}{\optional{**keywords}} A year and month. \end{classdesc} -\begin{classdesc}{gYear}{name\optional{, **keywords}} +\begin{classdesc}{gYear}{\optional{**keywords}} A year. \end{classdesc} -\begin{classdesc}{gMonthDay}{name\optional{, **keywords}} +\begin{classdesc}{gMonthDay}{\optional{**keywords}} A month and day. \end{classdesc} -\begin{classdesc}{gDay}{name\optional{, **keywords}} +\begin{classdesc}{gDay}{\optional{**keywords}} A day. \end{classdesc} -\begin{classdesc}{gTime}{name\optional{, **keywords}} +\begin{classdesc}{gTime}{\optional{**keywords}} A time. \end{classdesc} @@ -559,7 +578,7 @@ SOAP Booleans are Python integers. -\begin{classdesc}{Boolean}{name\optional{, **keywords}} +\begin{classdesc}{Boolean}{\optional{**keywords}} When marshaling zero or the word ``false'' is returned as \code{0} and any non-zero value or the word ``true'' is returned as \code{1}. When serializing, the number \code{0} or \code{1} will be generated. @@ -583,7 +602,7 @@ Note that it is generally more efficient to keep the \class{ParsedSoap} object alive until the XML data is no longerneeded. -\begin{classdesc}{XML}{name\optional{, **keywords}} +\begin{classdesc}{XML}{\optional{**keywords}} This typecode represents a portion of an XML document embedded in a SOAP message. The value is the element node. @@ -616,37 +635,31 @@ identifying the namespace prefixes that should be output.} \end{tableiii} -\section{Struct} +\section{ComplexType} -SOAP structs are either Python dictionaries or -instances of application-specified classes. +Represents the XMLSchema ComplexType . +\versionadded{2.0} -\begin{classdesc}{Struct}{pyclass, typecode_seq, name\optional{, **keywords}} +\begin{classdesc}{ComplexType}{pyclass, ofwhat\optional{, **keywords}} This class defines a compound data structure. If \code{pyclass} is \code{None}, then the data will be marshaled -into a Python dictionary, and each item in the \code{typecode_seq} sequence +into a Python dictionary, and each item in the \code{ofwhat} sequence specifies a (possible) dictionary entry. -Otherwise, \code{pyclass} must be a Python class object whose constructor -takes a single parameter, which will be the value of the \code{name} -parameter given in the \class{TC.Struct} constructor. -(This allows a single \code{pyclass} to be used for different typecodes.) +Otherwise, \code{pyclass} must be a Python class object. The data is then marshaled into the object, and each item in the -\code{typecode_seq} +\code{ofwhat} sequence specifies an attribute of the instance to set. -Note that each typecode in \code{typecode_seq} must have a name. +Note that each typecode in \code{ofwhat} must have a name. The following keyword arguments may be used: \begin{tableiii}{l|c|p{30em}}{textrm}{Keyword}{Default}{Description} -\lineiii{\code{hasextras}}{\code{0}}{Ignore any extra elements that appear -in the in the structure. -If \code{inorder} is true, extras can only appear at the end.} -\lineiii{\code{inorder}}{\code{0}}{Items within the structure must appear -in the order specified in the \code{TCseq} sequence.} -\lineiii{\code{inline}}{\code{0}}{The structure is single-reference, +\lineiii{\code{inorder}}{\code{False}}{Items within the structure must appear +in the order specified in the \code{ofwhat} sequence.} +\lineiii{\code{inline}}{\code{False}}{The structure is single-reference, so ZSI does not have to use \code{href/id} encodings.} -\lineiii{\code{mutable}}{\code{0}}{If an object is going to be serialized +\lineiii{\code{mutable}}{\code{False}}{If an object is going to be serialized multiple times, and its state may be modified between serializations, then this keyword should be used, otherwise a single instance will be serialized, with multiple references to it. @@ -659,11 +672,15 @@ specified by this parameter. By default, type-checking is not done for structures; matching child element names is usually sufficient and senders rarely provide type information.} +\lineiii{\code{mixed}}{\code{False}}{using a mixed content model, allow text and +element content.} +\lineiii{\code{mixed_aname}}{\code{'_text'}}{if mixed is True, text +content is set in this attribute (key).} \end{tableiii} If the \code{typed} keyword is used, then its value is assigned to -all typecodes in the \code{typecode_seq} parameter. -If any of the typecodes in \code{typecode_seq} are repeatable, then the +all typecodes in the \code{ofwhat} parameter. +If any of the typecodes in \code{ofwhat} are repeatable, then the \code{inorder} keyword should not be used and the \code{hasextras} parameter \emph{must} be used. @@ -688,25 +705,12 @@ \end{verbatim} \end{classdesc} -\section{Choice} +\section{Struct} -A choice is a Python two-element \samp{(name, value)} tuple, representing -a union of different types. -The first item is a string identifying the type, and the second is the -actual data. +SOAP Struct is a complex type for accessors identified by name. No element may +have the same name as any other, nor may any element have a maxOccurs > 1. +SOAP Structs are either Python dictionaries or instances of application-specified classes. -\begin{classdesc}{Choice}{typecode_seq, name\optional{, **keywords}} -When parsing, ZSI will look at the element name in the SOAP message, and -determine which of the choices to create. - -When serializing Python objects to SOAP messages, \ZSI{} must be -explicitly told which of the choices define the data. -This is done by passing a two-element tuple. -The first item is a string identifying the name of a typecode -from the \code{typecode_seq} list of typecodes. -The second is the object to be serialized. -\end{classdesc} - \section{Arrays} SOAP arrays are Python lists; multi-dimensional arrays are @@ -718,9 +722,9 @@ \strong{Currently only singly-dimensioned arrays are supported.} -\begin{classdesc}{Array}{atype, ofwhat, name\optional{, **keywords}} -The \code{atype} parameter is a text string representing the SOAP array type. -the \code{ofwhat} parameter is a typecode describing the array elements. +\begin{classdesc}{Array}{atype, ofwhat\optional{, **keywords}} +The \code{atype} parameter is a \code{(URI,NCName)} tuple representing the SOAP +array type. The \code{ofwhat} parameter is a typecode describing the array elements. \end{classdesc} The following keyword arguments may be used: @@ -732,14 +736,16 @@ the array.} \lineiii{\code{fill}}{\code{None}}{The value to use when an array element is omitted.} -\lineiii{\code{mutable}}{\code{0}}{Same as \class{TC.Struct} -\versionadded{1.2}} +\lineiii{\code{mutable}}{\code{False}}{If an object is going to be serialized +multiple times, and its state may be modified between serializations, +then this keyword should be used, otherwise a single instance will be +serialized, with multiple references to it.} \lineiii{\code{nooffset}}{\code{0}}{Do not use the SOAP \code{offset} attribute so skip leading elements with the same value as \code{fill}.} -\lineiii{\code{sparse}}{\code{0}}{The array is sparse.} +\lineiii{\code{sparse}}{\code{False}}{The array is sparse.} \lineiii{\code{size}}{\code{None}}{An integer or list of integers that specifies the maximum array dimensions.} -\lineiii{\code{undeclared}}{\code{0}}{The SOAP \samp{arrayType} attribute +\lineiii{\code{undeclared}}{\code{False}}{The SOAP \samp{arrayType} attribute need not appear.} \end{tableiii} Modified: trunk/zsi/test/test_t8.py =================================================================== --- trunk/zsi/test/test_t8.py 2006-10-13 00:12:32 UTC (rev 1265) +++ trunk/zsi/test/test_t8.py 2006-10-13 23:35:29 UTC (rev 1266) @@ -1,9 +1,15 @@ #!/usr/bin/env python import unittest, sys from ZSI import * +from ZSI.wstools.Namespaces import SCHEMA, SOAP +NSDICT = {'tns':'xmlns:tns="urn:a"', + 'xsi':'xmlns:xsi="%s"' %SCHEMA.XSI3, + 'xsd':'xmlns:xsd="%s"' %SCHEMA.XSD3, + 'soap':'xmlns:SOAP-ENC="%s"' %SOAP.ENC, +} -class t8TestCase(unittest.TestCase): +class AnyTestCase(unittest.TestCase): "Test Any serialize and parse" def check_parse_empty_all(self): @@ -26,8 +32,6 @@ sw = SoapWriter() sw.serialize("", typecode=tc, typed=True) soap = str(sw) - print - print soap ps = ParsedSoap(soap) parsed = ps.Parse(Any()) self.assertEqual("", parsed) @@ -39,7 +43,6 @@ sw = SoapWriter() sw.serialize(orig, typecode=Any(pname="builtins", aslist=True)) - print >>sys.stdout, sw ps = ParsedSoap(str(sw)) parsed = ps.Parse(Any()) @@ -57,26 +60,87 @@ self.assertEqual(tuple, type(parsed[3])) self.assertEqual(type(myFloat), type(parsed[4])) - - def check_Any_nill(self): + def check_any_nill(self): result = ['23', {'a' : None, 'b': 5}] soap = str(SoapWriter().serialize(result, TC.Any(pname="NilRequest", nillable=True, aslist=True))) - print soap ps = ParsedSoap(soap) tc = TC.Any(nillable=True) pyobj = ps.Parse(tc) + def check_any_compound(self): + # from zsi developer's guide + xml = """ +<tns:foo %(tns)s %(xsi)s %(soap)s> + <tns:i xsi:type="SOAP-ENC:integer">12</tns:i> + <tns:name xsi:type="SOAP-ENC:string">Hello world</tns:name> +</tns:foo>""" %NSDICT -def makeTestSuite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(t8TestCase, "check")) - return suite + ps = ParsedSoap(xml, envelope=False) + self.failUnless(ps.Parse(TC.Any()) == {'i': 12, 'name': 'Hello world'}) + self.failUnless(ps.Parse(TC.Any(aslist=True)) == [12, 'Hello world']) + def check_any_typed_soap_integer(self): + # from zsi developer's guide + value = 12 + d = dict(value=value) + d.update(NSDICT) + xml = """<tns:i xsi:type="SOAP-ENC:integer" %(xsi)s %(soap)s %(tns)s>%(value)d</tns:i>""" %d + ps = ParsedSoap(xml, envelope=False) + self.failUnless(ps.Parse(TC.Any()) == value) + + def check_any_typed_xsd_int(self): + # from zsi developer's guide + value = 12 + d = dict(value=value) + d.update(NSDICT) + xml = """<tns:i xsi:type="xsd:int" %(xsi)s %(soap)s %(tns)s %(xsd)s>%(value)d</tns:i>""" %d + ps = ParsedSoap(xml, envelope=False) + self.failUnless(ps.Parse(TC.Any()) == value) + + def check_any_typed_nonNegativeInteger(self): + # from zsi developer's guide + value = 12 + d = dict(value=value) + d.update(NSDICT) + xml = """<tns:i xsi:type="xsd:nonNegativeInteger" %(xsi)s %(soap)s %(tns)s %(xsd)s>%(value)d</tns:i>""" %d + ps = ParsedSoap(xml, envelope=False) + self.failUnless(ps.Parse(TC.Any()) == value) + + def check_any_untyped_int(self): + # from zsi developer's guide + d = dict(value=12) + d.update(NSDICT) + xml = """<tns:i %(tns)s>12</tns:i>""" %NSDICT + ps = ParsedSoap(xml, envelope=False) + self.failUnlessRaises(EvaluateException, ps.Parse, TC.Any()) + + +# +# Creates permutation of test options: "check", "check_any", etc +# +_SEP = '_' +for t in [i[0].split(_SEP) for i in filter(lambda i: callable(i[1]), AnyTestCase.__dict__.items())]: + test = '' + for f in t: + test += f + if globals().has_key(test): test += _SEP; continue + def _closure(): + name = test + def _makeTestSuite(): + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(AnyTestCase, name)) + return suite + return _makeTestSuite + + globals()[test] = _closure() + test += _SEP + +makeTestSuite = check + def main(): unittest.main(defaultTest="makeTestSuite") - if __name__ == "__main__" : main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |