Commits

Anonymous committed 42d9299

fix test suite

  • Participants
  • Parent commits fe7d144

Comments (0)

Files changed (20)

File osa/message.py

             List of message parts in the form
             (part name, part type class).
             This description is usually found in message part of a WSDL document.
+            Note, that due to binding section not all message parts are used for encoding.
+            The parts that are used are given be use_parts.
         use_parts : list
             List of parts to be really used for encoding/decoding.
-            This comes from wsdl binding section. Yes, they not
+            This comes from wsdl binding section. Yes, they are not
             quite from this planet.
+            In any case, in the present implementation I assume doc/literal wrapped and
+            use only the very first part from this member for encoding.
     """
     def __init__(self, name, parts, use_parts=None):
         self.name = name
             #etree.SubElement(kw["_body"], self.name)
             return
         #assumed wrapped convention
-        p = self.use_parts[0][1]() #encoding instance
+        cl = self.use_parts[0][1] #class
+        p = cl() #encoding instance
 
         #wrapped message is supplied
-        if len(arg) == 1 and isinstance(arg[0], self.parts[0][1]):
+        if len(arg) == 1 and isinstance(arg[0], cl):
             for child in getattr(p, "_children", []):
-                setattr(p, child['name'], getattr(arg[0], child['name'], None))
+                p = arg[0]
         else:
             #reconstruct wrapper from expanded input
             counter = 0
                                                                     %name)
                 setattr(p, name, val)
 
+        #set default ns to save space
+        etree.register_namespace("", xmlnamespace.get_ns(self.name))
         #the real conversion is done by ComplexType
         p.to_xml(kw["_body"], "{%s}%s" %(p._namespace, p.__class__.__name__))
 

File osa/xmlparser.py

         page_handler = urllib2.urlopen(url)
     else:
         page_handler = open(url, "r")
-    root = parse_qualified(page_handler)
+    root = parse_qualified(page_handler, attr=attr)
     page_handler.close()
     del page_handler
     return root

File osa/xmlschema.py

                 element[0].tag == "{%s}restriction" %xmlnamespace.NS_XSD \
                 and element[0].get("base", None) is not None:
             base_type = element[0].get("base")
-            XMLSchemaParser.create_alias(name, base_type,
-                                         xtypes, types)
+            XMLSchemaParser.create_alias(name, base_type, xtypes, types)
 
     @staticmethod
     def get_doc(x):
             alias = types[alias_type]
         cls_name = xmlnamespace.get_local_name(name)
         cls_ns = xmlnamespace.get_ns(name)
+        #create new type since the namespace may be different
         cls = type(cls_name, (alias,), {"__doc__":"no documentation",
                                   "_namespace":cls_ns})
         types[name] = cls
                 elif types.has_key(type_name):
                     type = types[type_name]
                 elif not(xtypes.has_key(type_name)):
-                    raise ValueError("Type not found in schema for:\n %s" %(etree.tostring(element)))
+                    raise ValueError("Type %s not found for:\n %s" %(type_name,etree.tostring(element)))
                 else:
                     XMLSchemaParser.create_type(type_name,
                                     xtypes[type_name], xtypes, types)

File osa/xmltypes.py

                 Attributes of the new type.
         """
         #list of children, even if empty, must be always present
-        if "_children" not in attributes:
-            raise ValueError("_children attribute must be present")
+        if not(attributes.has_key("_children")):
+            attributes["_children"] = []
 
         #create dictionary for initializing class arguments
         clsDict = {}

File tests/README

 Tests for the library.
-
-Folder serializers - contains tests for simple and complex XML types.
-These test are standalone and do not require any service.
-
-The following services, however, require a simple HelloWorldService to
-be available.
-test_wsdl - test WSDL to Python conversion
-test_client - test method calling

File tests/out.xml

+<Address><street>123 happy way</street><city>badtown</city><zip>32</zip><lattitude>4.3</lattitude><longitude>88.0</longitude></Address>

File tests/schema.xml

+<?xml version="1.0"?>
+<schema targetNamespace="vostok" 
+    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+    xmlns="http://www.w3.org/2001/XMLSchema"
+    xmlns:x = "zapad"
+    xmlns:y = "sever"
+    xmlns:tns = "vostok"
+    elementFormDefault="unqualified" attributeFormDefault="unqualified">
+     <import schemaLocation="schema2.xml"/>
+     <include schemaLocation="schema3.xml"/>
+  <simpleType name="Profession">
+      <restriction base="xsd:string">
+          <enumeration value="cosmonaut"/>
+          <enumeration value="scientist"/>
+      </restriction>
+  </simpleType>
+  <simpleType name="Counter">
+      <restriction base="int">
+          <minInclusive value="0"/>
+          <maxInclusive value="120"/>
+      </restriction>
+  </simpleType>
+  <complexType name="Name">
+      <documentation> bla-bla-bla</documentation>
+   <sequence>
+     <element name="firstName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+     <element name="lastName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+   </sequence>
+  </complexType>
+  <element name = "Comment" type="xsd:string"/>
+  <element name = "Person">
+      <complexType>
+       <sequence>
+         <element name="age" type="xsd:int" minOccurs="1" maxOccurs="1"/>
+         <element name="height" type="xsd:int" minOccurs="1" maxOccurs="1"/>
+         <element name="weight" type="xsd:float" minOccurs="1" maxOccurs="1"/>
+         <element name="name" type="tns:Name" minOccurs="0" maxOccurs="1" nillable="true"/>
+         <element name="place" type="x:Address" minOccurs ="1" maxOccurs="10"/>
+         <element name="car" type="y:Car" minOccurs ="0" maxOccurs="5"/>
+         <element ref="tns:Comment"/>
+       </sequence>
+      </complexType>
+  </element>
+  <element name="Robot" type="tns:Person"/>
+  <element name="Shish" />
+</schema>

File tests/schema2.xml

+<?xml version="1.0"?>
+ <schema targetNamespace="zapad" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" attributeFormDefault="unqualified">
+  <complexType name="Address">
+   <sequence>
+     <element name="country" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+     <element name="city" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+   </sequence>
+  </complexType>
+</schema>

File tests/schema3.xml

+<?xml version="1.0"?>
+ <schema targetNamespace="sever" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" attributeFormDefault="unqualified">
+  <complexType name="Car">
+   <sequence>
+     <element name="model" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+     <element name="weight" type="xsd:int" minOccurs="1" maxOccurs="1"/>
+   </sequence>
+  </complexType>
+</schema>

File tests/serializers/test_complex.py

-#!/usr/bin/env python
-import sys
-for x in sys.path:
-    if x.find("osa") != -1:
-        sys.path.remove(x)
-sys.path.append("../../")
-
-import datetime
-import unittest
-
-import xml.etree.cElementTree as etree
-
-from osa.xmltypes import *
-from osa.soap import *
-
-ns_test = 'test_namespace'
-
-Address = ComplexTypeMeta('Address', (), {
-                "_children":[
-                        {'name':"street", "type":XMLString, "min":1, "max": 1},
-                        {'name':"city", "type":XMLString, "min":1, "max": 1},
-                        {'name':"zip", "type":XMLInteger, "min":1, "max": 1},
-                        {'name':"since", "type":XMLDateTime, "min":0, "max": 1},
-                        {'name':"lattitude", "type":XMLDouble, "min":1, "max": 1},
-                        {'name':"longitude", "type":XMLDouble, "min":1, "max": 1},
-                        ], "__doc__": "an address info"})
-Person = ComplexTypeMeta('Person', (), {
-                "_children":[
-                        {'name':"name", "type":XMLString, "min":0, "max": 1},
-                        {'name':"birthdate", "type":XMLDateTime, "min":0, "max": 1},
-                        {'name':"age", "type":XMLInteger, "min":0, "max": 1},
-                        {'name':"addresses", "type":Address, "min":0, "max": 'unbounded'},
-                        {'name':"titles", "type":XMLString, "min":0, "max": 'unbounded'},
-                        ], "__doc__": "a person info"})
-
-Employee = ComplexTypeMeta('Employee', (Person,), {
-                "_children":[
-                        {'name':"id", "type":XMLInteger, "min":1, "max": 1},
-                        {'name':"salary", "type":XMLDouble, "min":1, "max": 1},
-                        ], "__doc__": "an employee info"})
-
-Level2 = ComplexTypeMeta('Level2', (), {
-                "_children":[
-                        {'name':"arg1", "type":XMLString, "min":1, "max": 1},
-                        {'name':"arg2", "type":XMLDouble, "min":1, "max": 1},
-                        ], "__doc__": "don't know"})
-
-Level3 = ComplexTypeMeta('Level3', (), {
-                "_children":[
-                        {'name':"arg1", "type":XMLInteger, "min":1, "max": 1},
-                        ], "__doc__": "don't know"})
-Level4 = ComplexTypeMeta('Level4', (), {
-                "_children":[
-                        {'name':"arg1", "type":XMLString, "min":1, "max": 1},
-                        ], "__doc__": "don't know"})
-
-Level1 = ComplexTypeMeta('Level1', (), {
-                "_children":[
-                        {'name':"level2", "type":Level2, "min":1, "max": 1},
-                        {'name':"level3", "type":Level3, "min":0, "max": 'unbouneded'},
-                        {'name':"level4", "type":Level4, "min":0, "max": 'unbouneded'},
-                        ], "__doc__": "don't know"})
-
-class TestClassSerializer(unittest.TestCase):
-    def test_simple_class(self):
-        a = Address()
-        a.street = '123 happy way'
-        a.city = 'badtown'
-        a.zip = 32
-        a.lattitude = 4.3
-        a.longitude = 88.0
-
-        element = etree.Element('test')
-        a.to_xml( element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-        self.assertEquals(5, len(element.getchildren()))
-
-        r = Address().from_xml(element)
-
-        self.assertEquals(a.street, r.street)
-        self.assertEquals(a.city, r.city)
-        self.assertEquals(a.zip, r.zip)
-        self.assertEquals(a.lattitude, r.lattitude)
-        self.assertEquals(a.longitude, r.longitude)
-        self.assertEquals(a.since, r.since)
-
-    def test_nested_class(self):
-        p = Person()
-        element = etree.Element('test')
-        p.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-
-        self.assertEquals(None, p.name)
-        self.assertEquals(None, p.birthdate)
-        self.assertEquals(None, p.age)
-        self.assertEquals(None, p.addresses)
-
-    def test_complex_class(self):
-        l = Level1()
-        l.level2 = Level2()
-        l.level2.arg1 = 'abcd'
-        l.level2.arg2 = 1.0/3.0
-        l.level3 = []
-        l.level4 = []
-
-        for i in range(0, 100):
-            a = Level3()
-            a.arg1 = i
-            l.level3.append(a)
-
-        for i in range(0, 4):
-            a = Level4()
-            a.arg1 = str(i)
-            l.level4.append(a)
-
-        element = etree.Element('test')
-        l.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-        l1 = Level1().from_xml(element)
-
-        self.assertEquals(l1.level2.arg1, l.level2.arg1)
-        self.assertEquals(l1.level2.arg2, l.level2.arg2)
-        self.assertEquals(len(l1.level4), len(l.level4))
-        self.assertEquals(len(l1.level3), len(l.level3))
-        for i in range(100):
-            self.assertEquals(l1.level3[i].arg1, l.level3[i].arg1)
-        for i in range(4):
-            self.assertEquals(l1.level4[i].arg1, l.level4[i].arg1)
-
-
-    def test_any(self):
-        a = Address()
-        a.street = '123 happy way'
-        a.city = 'badtown'
-        a.zip = 32
-        a.lattitude = 4.3
-        a.longitude = 88.0
-
-        element = etree.Element('test')
-        a.to_xml( element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-        element.set("{%s}type" %NS_XSI, 'Address')
-
-        XMLAny._types = {'Person':Person, 'Address':Address, 'Level4':Level4,
-                        'Level3':Level3, 'Level2': Level2, 'Level1':Level1}
-
-        r = XMLAny().from_xml(element)
-        self.assertTrue(isinstance(r, Address))
-
-        self.assertEquals(a.street, r.street)
-        self.assertEquals(a.city, r.city)
-        self.assertEquals(a.zip, r.zip)
-        self.assertEquals(a.lattitude, r.lattitude)
-        self.assertEquals(a.longitude, r.longitude)
-        self.assertEquals(a.since, r.since)
-
-if __name__ == '__main__':
-    unittest.main()

File tests/serializers/test_primitive.py

-#!/usr/bin/env python
-
-import sys
-for x in sys.path:
-    if x.find("osa") != -1:
-        sys.path.remove(x)
-sys.path.append("../../")
-
-import datetime
-import unittest
-
-import xml.etree.cElementTree as etree
-
-from osa.xmltypes import *
-
-ns_test = 'test_namespace'
-
-class TestPrimitive(unittest.TestCase):
-    def test_string(self):
-        s = XMLString("value")
-        element = etree.Element('test')
-        s.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element=element[0]
-
-        self.assertEquals(element.text, 'value')
-        value = XMLString().from_xml(element)
-        self.assertEquals(value, 'value')
-    
-    def test_stringenumeration(self):
-        XMLStringEnumeration._allowedValues = ["me", "you"]
-        s1 = XMLStringEnumeration("me")
-        self.assertEquals(s1.value, "me")
-        s2 = XMLStringEnumeration("he")
-        self.assertEquals(s2.value, "he")
-
-        #toxml
-        element = etree.Element('test')
-        s1.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element=element[0]
-        self.assertEquals(element.text, 'me')
-
-        element2 = etree.Element('test')
-        self.assertRaises(ValueError, s2.to_xml, element2, "{%s}%s" %(ns_test, "atach"))
-
-        #back
-        value = XMLStringEnumeration().from_xml(element)
-        self.assertEquals(value, 'me')
-        element.text="he"
-        self.assertRaises(ValueError, XMLStringEnumeration().from_xml, element)
-
-    def test_datetime(self):
-        d = XMLDateTime(datetime.now())
-
-        element = etree.Element('test')
-        d.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-
-        self.assertEquals(element.text, d.value.isoformat())
-        dt = XMLDateTime().from_xml(element)
-        self.assertEquals(d.value, dt)
-
-    def test_date(self):
-        x = datetime.now()
-        x = x.date()
-        d = XMLDate(x)
-
-        element = etree.Element('test')
-        d.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-
-        self.assertEquals(element.text, d.value.isoformat())
-        dt = XMLDate().from_xml(element)
-        self.assertEquals(d.value, dt)
-
-    def test_integer(self):
-        integer = XMLInteger(12)
-
-        element = etree.Element('test')
-        integer.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-
-        self.assertEquals(element.text, '12')
-        value = XMLInteger().from_xml(element)
-        self.assertEquals(value, integer)
-
-    def test_large_integer(self):
-        integer = XMLInteger(128375873458473)
-
-        element = etree.Element('test')
-        integer.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-
-        self.assertEquals(element.text, '128375873458473')
-        value = XMLInteger().from_xml(element)
-        self.assertEquals(value, integer)
-
-    def test_float(self):
-        f = XMLDouble(1.0/3.0)
-        element = etree.Element('test')
-        f.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-
-        self.assertEquals(element.text, repr(f))
-
-        f2 = XMLDouble().from_xml(element)
-        self.assertEquals(f2, f)
-
-    def test_unicode(self):
-        s = XMLString(u'\x34\x55\x65\x34')
-        self.assertEquals(4, len(s))
-        element = etree.Element('test')
-        s.to_xml(element, "{%s}%s" %(ns_test, "atach"))
-        element = element[0]
-        value = XMLString().from_xml(element)
-        self.assertEquals(value, s)
-
-    def test_boolean(self):
-        b = etree.Element('test')
-        XMLBoolean(True).to_xml(b, "{%s}%s" %(ns_test, "atach"))
-        b = b[0]
-        self.assertEquals('true', b.text)
-
-        b = etree.Element('test')
-        XMLBoolean(0).to_xml(b, "{%s}%s" %(ns_test, "atach"))
-        b = b[0]
-        self.assertEquals('false', b.text)
-
-        b = etree.Element('test')
-        XMLBoolean(1).to_xml(b, "{%s}%s" %(ns_test, "atach"))
-        b = b[0]
-        self.assertEquals('true', b.text)
-
-        b = XMLBoolean().from_xml(b)
-        self.assertEquals(b, True)
-
-        b = etree.Element('test')
-        XMLBoolean(False).to_xml(b, "{%s}%s" %(ns_test, "atach"))
-        b = b[0]
-        self.assertEquals('false', b.text)
-
-        b = XMLBoolean().from_xml(b)
-        self.assertEquals(b, False)
-
-        b = etree.Element('test')
-        b.text = ''
-        b = XMLBoolean().from_xml(b)
-        self.assertEquals(b, None)
-
-if __name__ == '__main__':
-    unittest.main()

File tests/test.wsdl

+<?xml version="1.0" encoding="UTF-8"?>
+<definitions name="HelloWorldService" targetNamespace="de.mpg.ipp.hgw.boz.gsoap.helloworld" xmlns:tns="de.mpg.ipp.hgw.boz.gsoap.helloworld" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="de.mpg.ipp.hgw.boz.gsoap.helloworld.types" xmlns:ns1="de.mpg.ipp.hgw.boz.gsoap.helloworld" xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/" xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/">
+
+<types>
+
+ <schema targetNamespace="de.mpg.ipp.hgw.boz.gsoap.helloworld.types" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="de.mpg.ipp.hgw.boz.gsoap.helloworld.types" xmlns:ns1="de.mpg.ipp.hgw.boz.gsoap.helloworld" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" attributeFormDefault="unqualified">
+  <import namespace="de.mpg.ipp.hgw.boz.gsoap.helloworld"/>
+  <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>
+  <complexType name="Name">
+   <sequence>
+     <element name="firstName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+     <element name="lastName" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+   </sequence>
+  </complexType>
+  <complexType name="Person">
+   <sequence>
+     <element name="age" type="xsd:int" minOccurs="1" maxOccurs="1"/>
+     <element name="height" type="xsd:int" minOccurs="1" maxOccurs="1"/>
+     <element name="weight" type="xsd:int" minOccurs="1" maxOccurs="1"/>
+     <element name="name" type="ns2:Name" minOccurs="0" maxOccurs="1" nillable="true"/>
+   </sequence>
+  </complexType>
+ </schema>
+
+ <schema targetNamespace="de.mpg.ipp.hgw.boz.gsoap.helloworld" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns2="de.mpg.ipp.hgw.boz.gsoap.helloworld.types" xmlns:ns1="de.mpg.ipp.hgw.boz.gsoap.helloworld" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" attributeFormDefault="unqualified">
+  <import namespace="de.mpg.ipp.hgw.boz.gsoap.helloworld.types"/>
+  <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>
+  <!-- operation request element -->
+  <element name="testMe">
+   <complexType>
+    <sequence>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation request element -->
+  <element name="giveMessage">
+   <complexType>
+    <sequence>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation response element -->
+  <element name="giveMessageResponse">
+   <complexType>
+    <sequence>
+     <element name="out" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation request element -->
+  <element name="echoString">
+   <complexType>
+    <sequence>
+     <element name="in" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation response element -->
+  <element name="echoStringResponse">
+   <complexType>
+    <sequence>
+     <element name="out" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation request element -->
+  <element name="faultyThing">
+   <complexType>
+    <sequence>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation response element -->
+  <element name="faultyThingResponse">
+   <complexType>
+    <sequence>
+     <element name="out" type="xsd:string" minOccurs="1" maxOccurs="1"/>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation request element -->
+  <element name="sayHello">
+   <complexType>
+    <sequence>
+     <element name="person" type="ns2:Person" minOccurs="0" maxOccurs="1" nillable="true"/>
+     <element name="times" type="xsd:int" minOccurs="1" maxOccurs="1"/>
+    </sequence>
+   </complexType>
+  </element>
+  <!-- operation response element -->
+  <element name="sayHelloResponse">
+   <complexType>
+    <sequence>
+     <element name="result" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
+    </sequence>
+   </complexType>
+  </element>
+ </schema>
+
+</types>
+
+<message name="testMe">
+ <part name="parameters" element="ns1:testMe"/>
+</message>
+
+<message name="giveMessageRequest">
+ <part name="parameters" element="ns1:giveMessage"/>
+</message>
+
+<message name="giveMessageResponse">
+ <part name="parameters" element="ns1:giveMessageResponse"/>
+</message>
+
+<message name="echoStringRequest">
+ <part name="parameters" element="ns1:echoString"/>
+</message>
+
+<message name="echoStringResponse">
+ <part name="parameters" element="ns1:echoStringResponse"/>
+</message>
+
+<message name="faultyThingRequest">
+ <part name="parameters" element="ns1:faultyThing"/>
+</message>
+
+<message name="faultyThingResponse">
+ <part name="parameters" element="ns1:faultyThingResponse"/>
+</message>
+
+<message name="sayHello">
+ <part name="parameters" element="ns1:sayHello"/>
+</message>
+
+<message name="sayHelloResponse">
+ <part name="parameters" element="ns1:sayHelloResponse"/>
+</message>
+
+<portType name="HelloWorldServicePortType">
+ <operation name="testMe">
+  <documentation>Service definition of function ns1__testMe</documentation>
+  <input message="tns:testMe"/>
+ </operation>
+ <operation name="giveMessage">
+  <documentation>Service definition of function ns1__giveMessage</documentation>
+  <input message="tns:giveMessageRequest"/>
+  <output message="tns:giveMessageResponse"/>
+ </operation>
+ <operation name="echoString">
+  <documentation>Service definition of function ns1__echoString</documentation>
+  <input message="tns:echoStringRequest"/>
+  <output message="tns:echoStringResponse"/>
+ </operation>
+ <operation name="faultyThing">
+  <documentation>Service definition of function ns1__faultyThing</documentation>
+  <input message="tns:faultyThingRequest"/>
+  <output message="tns:faultyThingResponse"/>
+ </operation>
+ <operation name="sayHello">
+  <documentation>Service definition of function ns1__sayHello</documentation>
+  <input message="tns:sayHello"/>
+  <output message="tns:sayHelloResponse"/>
+ </operation>
+</portType>
+
+<binding name="HelloWorldService" type="tns:HelloWorldServicePortType">
+ <SOAP:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+ <operation name="testMe">
+  <SOAP:operation soapAction=""/>
+  <input>
+     <SOAP:body parts="parameters" use="literal"/>
+  </input>
+ </operation>
+ <operation name="giveMessage">
+  <SOAP:operation soapAction=""/>
+  <input>
+     <SOAP:body parts="parameters" use="literal"/>
+  </input>
+  <output>
+     <SOAP:body parts="parameters" use="literal"/>
+  </output>
+ </operation>
+ <operation name="echoString">
+  <SOAP:operation soapAction=""/>
+  <input>
+     <SOAP:body parts="parameters" use="literal"/>
+  </input>
+  <output>
+     <SOAP:body parts="parameters" use="literal"/>
+  </output>
+ </operation>
+ <operation name="faultyThing">
+  <SOAP:operation soapAction=""/>
+  <input>
+     <SOAP:body parts="parameters" use="literal"/>
+  </input>
+  <output>
+     <SOAP:body parts="parameters" use="literal"/>
+  </output>
+ </operation>
+ <operation name="sayHello">
+  <SOAP:operation soapAction=""/>
+  <input>
+     <SOAP:body parts="parameters" use="literal"/>
+  </input>
+  <output>
+     <SOAP:body parts="parameters" use="literal"/>
+  </output>
+ </operation>
+</binding>
+
+<service name="HelloWorldService">
+ <documentation>gSOAP 2.8.0 generated service definition</documentation>
+ <port name="HelloWorldService" binding="tns:HelloWorldService">
+  <SOAP:address location="http://lxpowerboz:88/services/cpp/HelloWorldService"/>
+ </port>
+</service>
+
+</definitions>

File tests/test.xml

+<?xml version="1.0"?>
+<kolo bok="ns:round" xmlns:ns="39kingdom" xmlns:ns2="yaga">
+    <lis a="ns:angry">
+    </lis>
+</kolo>

File tests/test_client.py

 #!/usr/bin/env python
+# test_client.py - test Client class, part of osa.
+# Copyright 2013 Sergey Bozhenkov, boz at ipp.mpg.de
+# Licensed under GPLv3 or later, see the COPYING file.
 
 import sys
 for x in sys.path:
         sys.path.remove(x)
 sys.path.append("../")
 
-import datetime
 import unittest
-
 import xml.etree.cElementTree as etree
-
-from osa.client import Client
-from osa.wsdl import WSDLParser, _primmap
-from osa.methods import Method
+from osa.client import *
+from osa.wsdl import *
+from osa.method import *
 from osa.xmltypes import *
+import urllib2
 
 wsdl_url = 'http://lxpowerboz:88/services/python/HelloWorldService?wsdl'
 
 class TestClient(unittest.TestCase):
+    def setUp(self):
+        self.client = Client("test.wsdl")
+    def tearDown(self):
+        self.client = None
     def test_init(self):
-        cl = Client(wsdl_url)
-        self.assertEquals(cl.wsdl_url, wsdl_url)
-        self.assertEquals(cl.names, ["HelloWorldService",])
+        self.assertEquals(self.client.names, ["service HelloWorldService",])
         for t in ("Person", "Name", "echoString", "sayHello"):
-            self.assertTrue(hasattr(cl.types, t))
-            self.assertEquals(type(getattr(cl.types, t)), ComplexTypeMeta)
-            self.assertTrue(t in cl.types.anyType._types.keys())
+            self.assertTrue(hasattr(self.client.types, t))
+            self.assertEquals(type(getattr(self.client.types, t)), ComplexTypeMeta)
         for method in ("testMe", "giveMessage", "echoString", "sayHello", "faultyThing"):
-            self.assertTrue(hasattr(cl.service, method))
-            self.assertEquals(type(getattr(cl.service, method)), Method)
+            self.assertTrue(hasattr(self.client.service, method))
+            self.assertEquals(type(getattr(self.client.service, method)), Method)
 
-    def test_testme(self):
-        #note: giveMessage is broken at the server side
-        cl = Client(wsdl_url)
-        res = cl.service.testMe()
-        self.assertEqual(type(res), cl.types.testMeResponse)
+    def test_giveMessage(self):
+        try:
+            urllib2.urlopen("http://lxpowerboz:88")
+        except urllib2.HTTPError:
+            pass
+        except urllib2.URLError:
+            return
+        res = self.client.service.giveMessage()
+        self.assertTrue(isinstance(res, str))
 
     def test_echoString(self):
-        cl = Client(wsdl_url)
-
-        self.assertEquals('my message 1', cl.service.echoString('my message 1'))
-        self.assertEquals('my message 2', cl.service.echoString(msg = 'my message 2'))
-        m = cl.types.echoString()
-        m.msg = 'my message 3'
-        self.assertEquals('my message 3', cl.service.echoString(m))
+        try:
+            urllib2.urlopen("http://lxpowerboz:88")
+        except urllib2.HTTPError:
+            pass
+        except urllib2.URLError:
+            return
+        self.assertEquals('my message 1', self.client.service.echoString('my message 1'))
 
     def test_sayHello(self):
-        cl = Client(wsdl_url)
-
-        n = cl.types.Name()
+        try:
+            urllib2.urlopen("http://lxpowerboz:88")
+        except urllib2.HTTPError:
+            pass
+        except urllib2.URLError:
+            return
+        n = self.client.types.Name()
         n.firstName = "first"
         n.lastName = "last"
-        p = cl.types.Person()
+        p = self.client.types.Person()
         p.name = n
         p.age = 30
         p.weight = 80
         p.height = 175
-
-        self.assertEquals(['Hello, first']*5, cl.service.sayHello(p, 5))
-        self.assertEquals(['Hello, first']*8, cl.service.sayHello(person = p, times = 8))
-        m = cl.types.sayHello()
-        m.person = p
-        m.times = 10
-        self.assertEquals(['Hello, first']*10, cl.service.sayHello(m))
+        self.assertEquals(['Hello, first\n']*5, self.client.service.sayHello(p, 5))
 
     def test_faultyThing(self):
-        cl = Client(wsdl_url)
-        self.assertRaises(RuntimeError, cl.service.faultyThing)
         try:
-            cl.service.faultyThing()
+            urllib2.urlopen("http://lxpowerboz:88")
+        except urllib2.HTTPError:
+            pass
+        except urllib2.URLError:
+            return
+        try:
+            self.client.service.faultyThing()
         except RuntimeError as e:
             self.assertFalse(str(e).find('4u!') == -1)
 
 
-
-
 if __name__ == '__main__':
     unittest.main()

File tests/test_message.py

+#!/usr/bin/env python
+# test_message.py - test Message class, part of osa.
+# Copyright 2013 Sergey Bozhenkov, boz at ipp.mpg.de
+# Licensed under GPLv3 or later, see the COPYING file.
+
+import sys
+for x in sys.path:
+    if x.find("osa") != -1:
+        sys.path.remove(x)
+sys.path.append("../")
+
+import unittest
+import xml.etree.cElementTree as etree
+from osa.xmlschema import *
+from osa.xmlparser import *
+from osa.message import *
+
+class TestMessage(unittest.TestCase):
+    def setUp(self):
+        root = parse_qualified_from_url("schema.xml")
+        schema = XMLSchemaParser(root)
+        xtypes = schema.get_list_of_defined_types()
+        self.types = XMLSchemaParser.convert_xmltypes_to_python(xtypes)
+    def tearDown(self):
+        self.types = None
+    def test_toxml(self):
+        message = Message("{vostok}msg", [["add", self.types["{vostok}Person"]],
+                                  ["params", self.types["{vostok}Name"]],
+                                  ["params", self.types["{sever}Car"]],
+                                  ])
+
+        #empty
+        root = etree.Element("root")
+        message.to_xml(_body=root)
+
+        #name
+        message.use_parts = [message.parts[1]]
+        #empty input=> exception
+        self.assertRaises(ValueError, message.to_xml, _body=root)
+        #single instance, wrong type => exception, the same path as above
+        car = self.types["{sever}Car"]()
+        car.model = "zaz"
+        self.assertRaises(ValueError, message.to_xml, car, _body=root)
+        #single instance of proper type
+        name = self.types["{vostok}Name"]()
+        name.firstName = "bobo"
+        name.lastName = "khnyk"
+        message.to_xml(name, _body=root)
+        self.assertEquals(len(root), 1)
+        self.assertEquals(root[0].tag, "{vostok}Name")
+        self.assertEquals(len(root[0]), 2)
+        #positional parameters
+        root = etree.Element("root")
+        message.to_xml("bobik", "sharikov", _body=root)
+        self.assertEquals(len(root), 1)
+        self.assertEquals(root[0].tag, "{vostok}Name")
+        self.assertEquals(len(root[0]), 2)
+        #keyword parameters
+        root = etree.Element("root")
+        message.to_xml(lastName = "zaa", firstName="yoyo", _body=root)
+        self.assertEquals(len(root), 1)
+        self.assertEquals(root[0].tag, "{vostok}Name")
+        self.assertEquals(len(root[0]), 2)
+
+    def test_fromxml(self):
+        root = etree.Element("Name")
+        fn = etree.SubElement(root, "firstName")
+        fn.text = "kolo"
+        sn = etree.SubElement(root, "lastName")
+        sn.text = "bok"
+
+        message = Message("{vostok}msg", [["add", self.types["{vostok}Person"]],
+                                  ["params", self.types["{vostok}Name"]],
+                                  ["params", self.types["{sever}Car"]],
+                                  ])
+        message.use_parts = [message.parts[1]]
+        res = message.from_xml(root)
+        self.assertEquals(res.__class__.__name__, "Name")
+        self.assertEquals(res.firstName, "kolo")
+        self.assertEquals(res.lastName, "bok")
+
+
+if __name__ == '__main__':
+    unittest.main()

File tests/test_wsdl.py

 #!/usr/bin/env python
+# test_wsdl.py - test WSDLParser class, part of osa.
+# Copyright 2013 Sergey Bozhenkov, boz at ipp.mpg.de
+# Licensed under GPLv3 or later, see the COPYING file.
 
 import sys
 for x in sys.path:
         sys.path.remove(x)
 sys.path.append("../")
 
-import datetime
 import unittest
-
 import xml.etree.cElementTree as etree
-
-from osa.wsdl import WSDLParser, _primmap
-from osa.methods import Method
+from osa.wsdl import *
+from osa.method import * 
+from osa.message import * 
 from osa.xmltypes import *
 
 wsdl_url = 'test.wsdl'
+ns1 = "de.mpg.ipp.hgw.boz.gsoap.helloworld"
+ns2 = "de.mpg.ipp.hgw.boz.gsoap.helloworld.types"
 
 class TestWSDL(unittest.TestCase):
     def test_reading(self):
         self.assertEquals(w.tns, "de.mpg.ipp.hgw.boz.gsoap.helloworld")
         self.assertEquals(type(w.wsdl), type(etree.Element('root')))
 
-    def test_service_name(self):
+    def test_get_types(self):
         w = WSDLParser(wsdl_url)
-        self.assertEquals(w.get_service_names(), ["HelloWorldService"])
+        types = w.get_types()
+        self.assertTrue('{%s}Name' %ns2 in types.keys())
+        self.assertTrue('{%s}Person' %ns2 in types.keys())
+        self.assertTrue('{%s}echoString' %ns1 in types.keys())
+        self.assertTrue('{%s}faultyThing' %ns1 in types.keys())
+        self.assertTrue('{%s}testMe' %ns1 in types.keys())
+        self.assertTrue('{%s}sayHello' %ns1 in types.keys())
+        self.assertTrue('{%s}echoStringResponse' %ns1 in types.keys())
+        self.assertTrue('{%s}faultyThingResponse' %ns1 in types.keys())
+        self.assertTrue('{%s}sayHelloResponse' %ns1 in types.keys())
+        self.assertTrue(types['{%s}Name' %ns2], 'firstName')
+        self.assertTrue(types['{%s}Name' %ns2], 'lastName')
+        self.assertTrue(types['{%s}Person' %ns2], 'name')
+        self.assertTrue(types['{%s}Person' %ns2], 'age')
+        self.assertTrue(types['{%s}Person' %ns2], 'height')
+        self.assertTrue(types['{%s}Person' %ns2], 'weight')
+        self.assertTrue(types['{%s}Person' %ns2]._children[3]['name'] == "name")
+        self.assertTrue(types['{%s}Person' %ns2]._children[0]['name'] == "age")
+        self.assertTrue(types['{%s}Person' %ns2]._children[3]['type'] == types['{%s}Name' %ns2])
+        self.assertTrue(types['{%s}Person' %ns2]._children[0]['type'] == xmltypes.XMLInteger)
+        self.assertTrue(types['{%s}sayHello' %ns1], 'person')
+        self.assertTrue(types['{%s}sayHello' %ns1], 'times')
+        self.assertTrue(types['{%s}sayHello' %ns1]._children[0]['name'] == "person")
+        self.assertTrue(types['{%s}sayHello' %ns1]._children[1]['name'] == "times")
+        self.assertTrue(types['{%s}sayHello' %ns1]._children[0]['type'] == types['{%s}Person' %ns2])
+        self.assertTrue(types['{%s}sayHello' %ns1]._children[1]['type'] == xmltypes.XMLInteger)
 
-    def test_conversions(self):
+    def test_get_messages(self):
         w = WSDLParser(wsdl_url)
-        types = w.get_types(_primmap)
-        self.assertTrue('Name' in types.keys())
-        self.assertTrue('Person' in types.keys())
-        self.assertTrue('echoString' in types.keys())
-        self.assertTrue('faultyThing' in types.keys())
-        self.assertTrue('testMe' in types.keys())
-        self.assertTrue('sayHello' in types.keys())
-        self.assertTrue('echoStringResponse' in types.keys())
-        self.assertTrue('faultyThingResponse' in types.keys())
-        #self.assertTrue('testMeResponse' in types.keys())
-        self.assertTrue('sayHelloResponse' in types.keys())
-        self.assertTrue(types['Name'], 'firstName')
-        self.assertTrue(types['Name'], 'lastName')
-        self.assertTrue(types['Person'], 'name')
-        self.assertTrue(types['Person'], 'age')
-        self.assertTrue(types['Person'], 'height')
-        self.assertTrue(types['Person'], 'weight')
-        self.assertTrue(types['Person']._children[3]['name'] == "name")
-        self.assertTrue(types['Person']._children[0]['name'] == "age")
-        self.assertTrue(types['Person']._children[3]['type'] == types['Name'])
-        self.assertTrue(types['Person']._children[0]['type'] == types['int'])
-        self.assertTrue(types['sayHello'], 'person')
-        self.assertTrue(types['sayHello'], 'times')
-        self.assertTrue(types['sayHello']._children[0]['name'] == "person")
-        self.assertTrue(types['sayHello']._children[1]['name'] == "times")
-        self.assertTrue(types['sayHello']._children[0]['type'] == types['Person'])
-        self.assertTrue(types['sayHello']._children[1]['type'] == types['int'])
-        methods = w.get_methods(types)
-        self.assertTrue('testMe' in methods.keys())
-        self.assertTrue('giveMessage' in methods.keys())
-        self.assertTrue('echoString' in methods.keys())
-        self.assertTrue('sayHello' in methods.keys())
-        self.assertTrue('faultyThing' in methods.keys())
-        self.assertTrue(isinstance(methods['testMe'], Method))
-        self.assertTrue(isinstance(methods['giveMessage'], Method))
-        self.assertTrue(isinstance(methods['echoString'], Method))
-        self.assertTrue(isinstance(methods['sayHello'], Method))
-        self.assertTrue(isinstance(methods['faultyThing'], Method))
+        types = w.get_types()
+        msgs = w.get_messages(types)
+        names = ("testMe", "giveMessageRequest",
+                 "giveMessageResponse", "echoStringRequest",
+                 "echoStringResponse", "faultyThingRequest",
+                 "faultyThingResponse", "sayHello",
+                 "sayHelloResponse")
+        for n in names:
+            self.assertTrue(msgs.has_key("{%s}%s" %(ns1, n)))
+            m = msgs["{%s}%s" %(ns1, n)]
+            self.assertTrue(isinstance(m, Message))
+            self.assertEquals(m.name, "{%s}%s" %(ns1, n))
+            self.assertEquals(len(m.parts), 1)
+            self.assertEquals(len(m.parts[0]), 2)
+            self.assertEquals(m.parts[0][0], "parameters")
 
-    def test_methods(self):
+    def test_get_operations(self):
         w = WSDLParser(wsdl_url)
-        types = w.get_types(_primmap)
-        methods = w.get_methods(types)
+        types = w.get_types()
+        msgs = w.get_messages(types)
+        ops = w.get_operations(msgs)
+        self.assertTrue(ops.has_key("{%s}HelloWorldServicePortType" %ns1))
+        ops = ops["{%s}HelloWorldServicePortType" %ns1]
+        names = ("testMe", "giveMessage", "echoString", "faultyThing", "sayHello")
+        for n in names:
+            self.assertTrue(ops.has_key(n))
+            op = ops[n]
+            self.assertTrue(isinstance(op, Method))
+            self.assertTrue(isinstance(op.input, Message))
+            if n != "testMe":
+                self.assertTrue(isinstance(op.output, Message))
 
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        methods['testMe'].input.to_xml(_body = root)
-        self.assertEquals(len(root), 1)
+        self.assertTrue(ops["testMe"].input is msgs["{%s}testMe" %ns1])
+        self.assertTrue(ops["giveMessage"].input is msgs["{%s}giveMessageRequest" %ns1])
+        self.assertTrue(ops["giveMessage"].output is msgs["{%s}giveMessageResponse" %ns1])
+        self.assertTrue(ops["echoString"].input is msgs["{%s}echoStringRequest" %ns1])
+        self.assertTrue(ops["echoString"].output is msgs["{%s}echoStringResponse" %ns1])
+        self.assertTrue(ops["faultyThing"].input is msgs["{%s}faultyThingRequest" %ns1])
+        self.assertTrue(ops["faultyThing"].output is msgs["{%s}faultyThingResponse" %ns1])
+        self.assertTrue(ops["sayHello"].input is msgs["{%s}sayHello" %ns1])
+        self.assertTrue(ops["sayHello"].output is msgs["{%s}sayHelloResponse" %ns1])
 
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        methods['giveMessage'].input.to_xml(_body = root)
-        self.assertEquals(len(root), 1)
+    def test_get_bindings(self):
+        w = WSDLParser(wsdl_url)
+        types = w.get_types()
+        msgs = w.get_messages(types)
+        ops = w.get_operations(msgs)
+        bs = w.get_bindings(ops)
+        ops = ops["{%s}HelloWorldServicePortType" %ns1]
+        self.assertTrue(bs.has_key("{%s}HelloWorldService" %ns1))
+        bs = bs["{%s}HelloWorldService" %ns1]
+        names = ("testMe", "giveMessage", "echoString", "faultyThing", "sayHello")
+        for n in names:
+            self.assertTrue(bs.has_key(n))
+            b = bs[n]
+            op = ops[n]
+            self.assertTrue(b is op)
+            self.assertTrue(b.input.use_parts is not None)
+            self.assertEquals(len(b.input.use_parts), 1)
+            self.assertEquals(b.input.use_parts[0][0], "parameters")
+            if n != "testMe":
+                self.assertEquals(len(b.output.use_parts), 1)
+                self.assertEquals(b.output.use_parts[0][0], "parameters")
+            self.assertEquals(b.action, "")
 
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        methods['faultyThing'].input.to_xml(_body = root)
-        self.assertEquals(len(root), 1)
+    def test_get_services(self):
+        w = WSDLParser(wsdl_url)
+        types = w.get_types()
+        msgs = w.get_messages(types)
+        ops = w.get_operations(msgs)
+        bs = w.get_bindings(ops)
+        ss = w.get_services(bs)
+        bs = bs["{%s}HelloWorldService" %ns1]
+        self.assertTrue(ss.has_key("HelloWorldService"))
+        ss = ss["HelloWorldService"]
+        names = ("testMe", "giveMessage", "echoString", "faultyThing", "sayHello")
+        for n in names:
+            self.assertTrue(ss.has_key(n))
+            s = ss[n]
+            b = bs[n]
+            self.assertTrue(s is b)
+            self.assertEquals(s.location, "http://lxpowerboz:88/services/cpp/HelloWorldService")
 
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        methods['echoString'].input.to_xml(msg = 'message', _body = root)
-        self.assertEquals(len(root), 1)
-        self.assertEquals('message', XMLString().from_xml(root[0][0]))
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        methods['echoString'].input.to_xml('message', _body = root)
-        self.assertEquals(len(root), 1)
-        self.assertEquals('message', XMLString().from_xml(root[0][0]))
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        mm = types['echoString']()
-        mm.msg = 'message'
-        methods['echoString'].input.to_xml(mm, _body = root)
-        self.assertEquals(len(root), 1)
-        self.assertEquals('message', XMLString().from_xml(root[0][0]))
-
-        n = types['Name']()
-        n.firstName = "first"
-        n.lastName = "last"
-        p = types['Person']()
-        p.name = n
-        p.age = 30
-        p.weight = 80
-        p.height = 175
-        t = 5
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        methods['sayHello'].input.to_xml(person = p, times = t, _body = root)
-        self.assertEquals(len(root), 1)
-        self.assertEquals(len(root[0]), 2)
-        rp = types['Person']().from_xml(root[0][0])
-        rt = types['int']().from_xml(root[0][1])
-        self.assertEquals(rt, t)
-        self.assertEquals(rp.age, p.age)
-        self.assertEquals(rp.weight, p.weight)
-        self.assertEquals(rp.height, p.height)
-        self.assertEquals(rp.name.firstName, p.name.firstName)
-        self.assertEquals(rp.name.lastName, p.name.lastName)
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        methods['sayHello'].input.to_xml( p, t, _body = root)
-        self.assertEquals(len(root), 1)
-        self.assertEquals(len(root[0]), 2)
-        rp = types['Person']().from_xml(root[0][0])
-        rt = types['int']().from_xml(root[0][1])
-        self.assertEquals(rt, t)
-        self.assertEquals(rp.age, p.age)
-        self.assertEquals(rp.weight, p.weight)
-        self.assertEquals(rp.height, p.height)
-        self.assertEquals(rp.name.firstName, p.name.firstName)
-        self.assertEquals(rp.name.lastName, p.name.lastName)
-        root = etree.Element('root')
-        self.assertEquals(len(root), 0)
-        mm = types['sayHello']()
-        mm.person = p
-        mm.times = t
-        methods['sayHello'].input.to_xml(mm, _body = root)
-        self.assertEquals(len(root), 1)
-        self.assertEquals(len(root[0]), 2)
-        rp = types['Person']().from_xml(root[0][0])
-        rt = types['int']().from_xml(root[0][1])
-        self.assertEquals(rt, t)
-        self.assertEquals(rp.age, p.age)
-        self.assertEquals(rp.weight, p.weight)
-        self.assertEquals(rp.height, p.height)
-        self.assertEquals(rp.name.firstName, p.name.firstName)
-        self.assertEquals(rp.name.lastName, p.name.lastName)
 
 if __name__ == '__main__':
     unittest.main()

File tests/test_xmlparser.py

+#!/usr/bin/env python
+# test_xmlparser.py - test ns substitution, part of osa.
+# Copyright 2013 Sergey Bozhenkov, boz at ipp.mpg.de
+# Licensed under GPLv3 or later, see the COPYING file.
+
+import sys
+for x in sys.path:
+    if x.find("osa") != -1:
+        sys.path.remove(x)
+sys.path.append("../")
+
+import unittest
+import xml.etree.cElementTree as etree
+from osa.xmlparser import *
+
+class TestXMLParser(unittest.TestCase):
+    def test_ns_attr_parsing(self):
+        root = parse_qualified_from_url("test.xml", attr=["a"])
+        self.assertEquals(root.get("bok"), "ns:round")
+        self.assertEquals(root[0].get("a"), "{39kingdom}angry")
+
+if __name__ == '__main__':
+    unittest.main()

File tests/test_xmlschema.py

+#!/usr/bin/env python
+# test_xmlschema.py - test schema parsing, part of osa.
+# Copyright 2013 Sergey Bozhenkov, boz at ipp.mpg.de
+# Licensed under GPLv3 or later, see the COPYING file.
+
+import sys
+for x in sys.path:
+    if x.find("osa") != -1:
+        sys.path.remove(x)
+sys.path.append("../")
+
+import unittest
+import xml.etree.cElementTree as etree
+from osa.xmlschema import *
+from osa.xmlparser import *
+
+class TestXMLSchema(unittest.TestCase):
+    def setUp(self):
+        root = parse_qualified_from_url("schema.xml")
+        self.schema = XMLSchemaParser(root)
+    def tearDown(self):
+        self.schema = None
+    def test_get_list_of_types(self):
+        res = self.schema.get_list_of_defined_types()
+        self.assertTrue(res.has_key("{vostok}Name"))
+        self.assertEquals(res["{vostok}Name"].tag, "{%s}complexType" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{vostok}Name"].get("name"), "Name")
+        self.assertTrue(res.has_key("{vostok}Person"))
+        self.assertEquals(res["{vostok}Person"].tag, "{%s}element" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{vostok}Person"].get("name"), "Person")
+        self.assertTrue(res.has_key("{vostok}Robot"))
+        self.assertEquals(res["{vostok}Robot"].tag, "{%s}element" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{vostok}Robot"].get("name"), "Robot")
+        self.assertTrue(res.has_key("{vostok}Counter"))
+        self.assertEquals(res["{vostok}Counter"].tag, "{%s}simpleType" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{vostok}Counter"].get("name"), "Counter")
+        self.assertTrue(res.has_key("{vostok}Profession"))
+        self.assertEquals(res["{vostok}Profession"].tag, "{%s}simpleType" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{vostok}Profession"].get("name"), "Profession")
+        self.assertTrue(res.has_key("{vostok}Shish"))
+        self.assertEquals(res["{vostok}Shish"].tag, "{%s}element" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{vostok}Shish"].get("name"), "Shish")
+        self.assertTrue(res.has_key("{zapad}Address"))
+        self.assertEquals(res["{zapad}Address"].tag, "{%s}complexType" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{zapad}Address"].get("name"), "Address")
+        self.assertTrue(res.has_key("{sever}Car"))
+        self.assertEquals(res["{sever}Car"].tag, "{%s}complexType" %xmlnamespace.NS_XSD)
+        self.assertEquals(res["{sever}Car"].get("name"), "Car")
+    def test_convert(self):
+        xtypes = self.schema.get_list_of_defined_types()
+        types = XMLSchemaParser.convert_xmltypes_to_python(xtypes)
+        self.assertEqual(types["{vostok}Name"].__class__.__name__, "ComplexTypeMeta")
+        self.assertTrue(types.has_key("{vostok}Name"))
+        self.assertTrue(hasattr(types["{vostok}Name"], "firstName"))
+        self.assertTrue(hasattr(types["{vostok}Name"], "lastName"))
+        self.assertEquals(types["{vostok}Name"]._namespace, "vostok")
+        self.assertTrue(types.has_key("{vostok}Person"))
+        self.assertEqual(types["{vostok}Person"].__class__.__name__, "ComplexTypeMeta")
+        self.assertTrue(hasattr(types["{vostok}Person"], "age"))
+        self.assertTrue(hasattr(types["{vostok}Person"], "weight"))
+        self.assertTrue(hasattr(types["{vostok}Person"], "name"))
+        self.assertTrue(hasattr(types["{vostok}Person"], "place"))
+        self.assertTrue(hasattr(types["{vostok}Person"], "car"))
+        self.assertTrue(hasattr(types["{vostok}Person"], "Comment"))
+        self.assertEquals(types["{vostok}Person"]._namespace, "vostok")
+        self.assertTrue(types.has_key("{vostok}Robot"))
+        self.assertEqual(types["{vostok}Robot"].__class__.__name__, "ComplexTypeMeta")
+        self.assertTrue(hasattr(types["{vostok}Robot"], "age"))
+        self.assertTrue(hasattr(types["{vostok}Robot"], "weight"))
+        self.assertTrue(hasattr(types["{vostok}Robot"], "name"))
+        self.assertTrue(hasattr(types["{vostok}Robot"], "place"))
+        self.assertTrue(hasattr(types["{vostok}Robot"], "car"))
+        self.assertTrue(hasattr(types["{vostok}Robot"], "Comment"))
+        self.assertEquals(types["{vostok}Robot"]._namespace, "vostok")
+        self.assertTrue(types.has_key("{vostok}Counter"))
+        self.assertEquals(types["{vostok}Counter"].__base__.__name__, "XMLInteger")
+        self.assertTrue(isinstance(types["{vostok}Counter"](), int))
+        self.assertEquals(types["{vostok}Counter"]._namespace, "vostok")
+        self.assertTrue(types.has_key("{vostok}Profession"))
+        self.assertEquals(len(types["{vostok}Profession"]._allowedValues), 2)
+        self.assertTrue("cosmonaut" in types["{vostok}Profession"]._allowedValues)
+        self.assertTrue("scientist" in types["{vostok}Profession"]._allowedValues)
+        self.assertEquals(types["{vostok}Profession"]._namespace, "vostok")
+        self.assertEquals(types["{vostok}Profession"].__base__.__name__, "XMLStringEnumeration")
+        self.assertTrue(types.has_key("{vostok}Shish"))
+        self.assertEqual(types["{vostok}Shish"].__class__.__name__, "ComplexTypeMeta")
+        self.assertEqual(len(types["{vostok}Shish"]._children), 0)
+        self.assertTrue(types.has_key("{zapad}Address"))
+        self.assertTrue(hasattr(types["{zapad}Address"], "city"))
+        self.assertTrue(hasattr(types["{zapad}Address"], "country"))
+        self.assertEquals(types["{zapad}Address"]._namespace, "zapad")
+        self.assertEqual(types["{zapad}Address"].__class__.__name__, "ComplexTypeMeta")
+        self.assertTrue(types.has_key("{sever}Car"))
+        self.assertTrue(hasattr(types["{sever}Car"], "model"))
+        self.assertTrue(hasattr(types["{sever}Car"], "weight"))
+        self.assertEquals(types["{sever}Car"]._namespace, "sever")
+        self.assertEqual(types["{sever}Car"].__class__.__name__, "ComplexTypeMeta")
+if __name__ == '__main__':
+    unittest.main()

File tests/test_xmltypes_complex.py

+#!/usr/bin/env python
+# test_xmltypes_complex.py - test serialization of compound classes, part of osa.
+# Copyright 2013 Sergey Bozhenkov, boz at ipp.mpg.de
+# Licensed under GPLv3 or later, see the COPYING file.
+
+import sys
+for x in sys.path:
+    if x.find("osa") != -1:
+        sys.path.remove(x)
+sys.path.append("../")
+
+import unittest
+
+import xml.etree.cElementTree as etree
+
+from osa.xmltypes import *
+from osa.xmlnamespace import *
+
+ns_test = 'test_namespace'
+
+Address = ComplexTypeMeta('Address', (), {
+                "_children":[
+                        {'name':"street", "type":XMLString, "min":1, "max": 1},
+                        {'name':"city", "type":XMLString, "min":1, "max": 1},
+                        {'name':"zip", "type":XMLInteger, "min":1, "max": 1},
+                        {'name':"since", "type":XMLDateTime, "min":0, "max": 1},
+                        {'name':"lattitude", "type":XMLDouble, "min":1, "max": 1},
+                        {'name':"longitude", "type":XMLDouble, "min":1, "max": 1},
+                        ], "__doc__": "an address info"})
+Person = ComplexTypeMeta('Person', (), {
+                "_children":[
+                        {'name':"name", "type":XMLString, "min":0, "max": 1},
+                        {'name':"birthdate", "type":XMLDateTime, "min":0, "max": 1},
+                        {'name':"age", "type":XMLInteger, "min":0, "max": 1},
+                        {'name':"addresses", "type":Address, "min":0, "max": 'unbounded'},
+                        {'name':"titles", "type":XMLString, "min":0, "max": 'unbounded'},
+                        ], "__doc__": "a person info"})
+
+Employee = ComplexTypeMeta('Employee', (Person,), {
+                "_children":[
+                        {'name':"id", "type":XMLInteger, "min":1, "max": 1},
+                        {'name':"salary", "type":XMLDouble, "min":1, "max": 1},
+                        ], "__doc__": "an employee info"})
+
+Level2 = ComplexTypeMeta('Level2', (), {
+                "_children":[
+                        {'name':"arg1", "type":XMLString, "min":1, "max": 1},
+                        {'name':"arg2", "type":XMLDouble, "min":1, "max": 1},
+                        ], "__doc__": "don't know"})
+
+Level3 = ComplexTypeMeta('Level3', (), {
+                "_children":[
+                        {'name':"arg1", "type":XMLInteger, "min":1, "max": 1},
+                        ], "__doc__": "don't know"})
+Level4 = ComplexTypeMeta('Level4', (), {
+                "_children":[
+                        {'name':"arg1", "type":XMLString, "min":1, "max": 1},
+                        ], "__doc__": "don't know"})
+
+Level1 = ComplexTypeMeta('Level1', (), {
+                "_children":[
+                        {'name':"level2", "type":Level2, "min":1, "max": 1},
+                        {'name':"level3", "type":Level3, "min":0, "max": 'unbouneded'},
+                        {'name':"level4", "type":Level4, "min":0, "max": 'unbouneded'},
+                        ], "__doc__": "don't know"})
+
+class TestClassSerializer(unittest.TestCase):
+    def test_simple_class(self):
+        a = Address()
+        a.street = '123 happy way'
+        a.city = 'badtown'
+        a.zip = 32
+        a.lattitude = 4.3
+        a.longitude = 88.0
+
+        element = etree.Element('test')
+        a.to_xml( element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+        self.assertEquals(5, len(element.getchildren()))
+
+        r = Address().from_xml(element)
+
+        self.assertEquals(a.street, r.street)
+        self.assertEquals(a.city, r.city)
+        self.assertEquals(a.zip, r.zip)
+        self.assertEquals(a.lattitude, r.lattitude)
+        self.assertEquals(a.longitude, r.longitude)
+        self.assertEquals(a.since, r.since)
+
+    def test_nested_class(self):
+        p = Person()
+        element = etree.Element('test')
+        p.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+
+        self.assertEquals(None, p.name)
+        self.assertEquals(None, p.birthdate)
+        self.assertEquals(None, p.age)
+        self.assertEquals(None, p.addresses)
+
+    def test_complex_class(self):
+        l = Level1()
+        l.level2 = Level2()
+        l.level2.arg1 = 'abcd'
+        l.level2.arg2 = 1.0/3.0
+        l.level3 = []
+        l.level4 = []
+
+        for i in range(0, 100):
+            a = Level3()
+            a.arg1 = i
+            l.level3.append(a)
+
+        for i in range(0, 4):
+            a = Level4()
+            a.arg1 = str(i)
+            l.level4.append(a)
+
+        element = etree.Element('test')
+        l.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+        l1 = Level1().from_xml(element)
+
+        self.assertEquals(l1.level2.arg1, l.level2.arg1)
+        self.assertEquals(l1.level2.arg2, l.level2.arg2)
+        self.assertEquals(len(l1.level4), len(l.level4))
+        self.assertEquals(len(l1.level3), len(l.level3))
+        for i in range(100):
+            self.assertEquals(l1.level3[i].arg1, l.level3[i].arg1)
+        for i in range(4):
+            self.assertEquals(l1.level4[i].arg1, l.level4[i].arg1)
+
+
+    def test_any(self):
+        a = Address()
+        a.street = '123 happy way'
+        a.city = 'badtown'
+        a.zip = 32
+        a.lattitude = 4.3
+        a.longitude = 88.0
+
+        element = etree.Element('test')
+        a.to_xml( element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+        element.set("{%s}type" %NS_XSI, 'Address')
+
+        XMLAny._types = {'Person':Person, 'Address':Address, 'Level4':Level4,
+                        'Level3':Level3, 'Level2': Level2, 'Level1':Level1}
+
+        r = XMLAny().from_xml(element)
+        self.assertTrue(isinstance(r, Address))
+
+        self.assertEquals(a.street, r.street)
+        self.assertEquals(a.city, r.city)
+        self.assertEquals(a.zip, r.zip)
+        self.assertEquals(a.lattitude, r.lattitude)
+        self.assertEquals(a.longitude, r.longitude)
+        self.assertEquals(a.since, r.since)
+    def test_tofrom_file(self):
+        fname = "out.xml"
+        a = Address()
+        a.street = '123 happy way'
+        a.city = 'badtown'
+        a.zip = 32
+        a.lattitude = 4.3
+        a.longitude = 88.0
+        try:
+            os.remove(fname)
+        except:
+            pass
+        a.to_file(fname)
+        b = Address.from_file(fname)
+        self.assertEquals(b, a)
+        self.assertTrue(b is not a)
+
+if __name__ == '__main__':
+    unittest.main()

File tests/test_xmltypes_primitive.py

+#!/usr/bin/env python
+# test_xmltypes_primitive.py - test serialization of primitive classes, part of osa.
+# Copyright 2013 Sergey Bozhenkov, boz at ipp.mpg.de
+# Licensed under GPLv3 or later, see the COPYING file.
+
+import sys
+for x in sys.path:
+    if x.find("osa") != -1:
+        sys.path.remove(x)
+sys.path.append("../")
+
+from osa.xmltypes import *
+from datetime import datetime
+import unittest
+import xml.etree.cElementTree as etree
+
+ns_test = 'test_namespace'
+
+class TestPrimitive(unittest.TestCase):
+    def test_string(self):
+        s = XMLString("value")
+        element = etree.Element('test')
+        s.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element=element[0]
+
+        self.assertEquals(element.text, 'value')
+        value = XMLString().from_xml(element)
+        self.assertEquals(value, 'value')
+    
+    def test_stringenumeration(self):
+        XMLStringEnumeration._allowedValues = ["me", "you"]
+        s1 = XMLStringEnumeration("me")
+        self.assertEquals(s1.value, "me")
+        s2 = XMLStringEnumeration("he")
+        self.assertEquals(s2.value, "he")
+
+        #toxml
+        element = etree.Element('test')
+        s1.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element=element[0]
+        self.assertEquals(element.text, 'me')
+
+        element2 = etree.Element('test')
+        self.assertRaises(ValueError, s2.to_xml, element2, "{%s}%s" %(ns_test, "atach"))
+
+        #back
+        value = XMLStringEnumeration().from_xml(element)
+        self.assertEquals(value, 'me')
+        element.text="he"
+        self.assertRaises(ValueError, XMLStringEnumeration().from_xml, element)
+
+    def test_datetime(self):
+        d = XMLDateTime(datetime.now())
+
+        element = etree.Element('test')
+        d.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+
+        self.assertEquals(element.text, d.value.isoformat())
+        dt = XMLDateTime().from_xml(element)
+        self.assertEquals(d.value, dt)
+
+    def test_date(self):
+        x = datetime.now()
+        x = x.date()
+        d = XMLDate(x)
+
+        element = etree.Element('test')
+        d.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+
+        self.assertEquals(element.text, d.value.isoformat())
+        dt = XMLDate().from_xml(element)
+        self.assertEquals(d.value, dt)
+
+    def test_integer(self):
+        integer = XMLInteger(12)
+
+        element = etree.Element('test')
+        integer.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+
+        self.assertEquals(element.text, '12')
+        value = XMLInteger().from_xml(element)
+        self.assertEquals(value, integer)
+
+    def test_large_integer(self):
+        integer = XMLInteger(128375873458473)
+
+        element = etree.Element('test')
+        integer.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+
+        self.assertEquals(element.text, '128375873458473')
+        value = XMLInteger().from_xml(element)
+        self.assertEquals(value, integer)
+
+    def test_float(self):
+        f = XMLDouble(1.0/3.0)
+        element = etree.Element('test')
+        f.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+
+        self.assertEquals(element.text, repr(f))
+
+        f2 = XMLDouble().from_xml(element)
+        self.assertEquals(f2, f)
+
+    def test_unicode(self):
+        s = XMLString(u'\x34\x55\x65\x34')
+        self.assertEquals(4, len(s))
+        element = etree.Element('test')
+        s.to_xml(element, "{%s}%s" %(ns_test, "atach"))
+        element = element[0]
+        value = XMLString().from_xml(element)
+        self.assertEquals(value, s)
+
+    def test_boolean(self):
+        b = etree.Element('test')
+        XMLBoolean(True).to_xml(b, "{%s}%s" %(ns_test, "atach"))
+        b = b[0]
+        self.assertEquals('true', b.text)
+
+        b = etree.Element('test')
+        XMLBoolean(0).to_xml(b, "{%s}%s" %(ns_test, "atach"))
+        b = b[0]
+        self.assertEquals('false', b.text)
+
+        b = etree.Element('test')
+        XMLBoolean(1).to_xml(b, "{%s}%s" %(ns_test, "atach"))
+        b = b[0]
+        self.assertEquals('true', b.text)
+
+        b = XMLBoolean().from_xml(b)
+        self.assertEquals(b, True)
+
+        b = etree.Element('test')
+        XMLBoolean(False).to_xml(b, "{%s}%s" %(ns_test, "atach"))
+        b = b[0]
+        self.assertEquals('false', b.text)
+
+        b = XMLBoolean().from_xml(b)
+        self.assertEquals(b, False)
+
+        b = etree.Element('test')
+        b.text = ''
+        b = XMLBoolean().from_xml(b)
+        self.assertEquals(b, None)
+
+    def test_any(self):
+        #test any from_xml, the other way is
+        #should not be used in real life in any case
+        element = etree.Element('test')
+        element.text = "10.0"
+
+        #no type => xml
+        inst = XMLAny()
+        v = inst.from_xml(element)
+        self.assertEquals(type(v).__name__ , "Element")
+
+        #float
+        element.set("{%s}type" %xmlnamespace.NS_XSI, "{%s}float" %xmlnamespace.NS_XSD)
+        v = inst.from_xml(element)
+        self.assertEquals(v.__class__.__name__, "float")
+        self.assertEquals(v, 10.0)
+
+        #string
+        element.set("{%s}type" %xmlnamespace.NS_XSI, "{%s}string" %xmlnamespace.NS_XSD)
+        v = inst.from_xml(element)
+        self.assertEquals(v.__class__.__name__, "str")
+        self.assertEquals(v, "10.0")
+
+
+
+
+
+if __name__ == '__main__':
+    unittest.main()