def get_object_as_xml_cloth(inst, cls=None, no_namespace=False, encoding='utf8'): """Returns an ElementTree representation of a :class:`spyne.model.complex.ComplexModel` subclass. :param inst: The instance of the class to be serialized. :param cls: The class to be serialized. Optional. :param root_tag_name: The root tag string to use. Defaults to the output of ``value.__class__.get_type_name_ns()``. :param no_namespace: When true, namespace information is discarded. """ if cls is None: cls = inst.__class__ if cls.get_namespace() is None and no_namespace is None: no_namespace = True if no_namespace is None: no_namespace = False ostr = BytesIO() xml_cloth = XmlCloth(use_ns=(not no_namespace)) ctx = FakeContext() with etree.xmlfile(ostr, encoding=encoding) as xf: ctx.outprot_ctx.doctype_written = False ctx.protocol.prot_stack = tlist([], ProtocolMixin) tn = cls.get_type_name() ret = xml_cloth.subserialize(ctx, cls, inst, xf, tn) assert not isgenerator(ret) return ostr.getvalue()
def subunit2junitxml(ctr): from testtools import ExtendedToStreamDecorator from testtools import StreamToExtendedDecorator from subunit import StreamResultToBytes from subunit.filters import filter_by_result from subunit.filters import run_tests_from_stream from spyne.util.six import BytesIO from junitxml import JUnitXmlResult sys.argv = ['subunit-1to2'] subunit1_file_name = 'test_result.%d.subunit' % ctr subunit2 = BytesIO() run_tests_from_stream(open(subunit1_file_name, 'rb'), ExtendedToStreamDecorator( StreamResultToBytes(subunit2))) subunit2.seek(0) sys.argv = ['subunit2junitxml'] sys.stdin = subunit2 def f(output): return StreamToExtendedDecorator(JUnitXmlResult(output)) junit_file_name = 'test_result.%d.xml' % ctr filter_by_result(f, junit_file_name, True, False, protocol_version=2, passthrough_subunit=True, input_stream=subunit2)
def subunit2junitxml(ctr): from testtools import ExtendedToStreamDecorator from testtools import StreamToExtendedDecorator from subunit import StreamResultToBytes from subunit.filters import filter_by_result from subunit.filters import run_tests_from_stream from spyne.util.six import BytesIO from junitxml import JUnitXmlResult sys.argv = ['subunit-1to2'] subunit1_file_name = 'test_result.%d.subunit' % ctr subunit2 = BytesIO() run_tests_from_stream(open(subunit1_file_name, 'rb'), ExtendedToStreamDecorator(StreamResultToBytes(subunit2))) subunit2.seek(0) sys.argv = ['subunit2junitxml'] sys.stdin = subunit2 def f(output): return StreamToExtendedDecorator(JUnitXmlResult(output)) junit_file_name = 'test_result.%d.xml' % ctr filter_by_result(f, junit_file_name, True, False, protocol_version=2, passthrough_subunit=True, input_stream=subunit2)
def test_soap_bare_empty_output(self): class SomeService(ServiceBase): @rpc(String, _body_style='bare') def some_call(ctx, s): assert s == 'abc' app = Application([SomeService], 'tns', in_protocol=Soap11(), out_protocol=Soap11(cleanup_namespaces=True)) req = b""" <soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="tns"> <soap11env:Body> <tns:some_call>abc</tns:some_call> </soap11env:Body> </soap11env:Envelope> """ server = WsgiApplication(app) resp = etree.fromstring(b''.join(server({ 'QUERY_STRING': '', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'text/xml; charset=utf8', 'SERVER_NAME': 'localhost', 'wsgi.input': BytesIO(req), }, start_response, "http://null"))) print(etree.tostring(resp, pretty_print=True)) assert resp[0].tag == '{http://schemas.xmlsoap.org/soap/envelope/}Body' assert len(resp[0]) == 1 assert resp[0][0].tag == '{tns}some_call'+ RESPONSE_SUFFIX assert len(resp[0][0]) == 0
def test_simple_aux_wsgi(self): data = [] class Service(ServiceBase): @srpc(String, _returns=String) def call(s): data.append(s) class AuxService(ServiceBase): __aux__ = SyncAuxProc() @srpc(String, _returns=String) def call(s): data.append(s) app = Application([Service, AuxService], 'tns', in_protocol=HttpRpc(), out_protocol=HttpRpc()) server = WsgiApplication(app) server( { 'QUERY_STRING': 's=hey', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'text/xml', 'SERVER_NAME': 'localhost', 'wsgi.input': BytesIO(), }, start_response, "http://null") assert data == ['hey', 'hey']
def test_many(self): class SomeComplexModel(ComplexModel): s = Unicode i = Integer v = [ SomeComplexModel(s='a', i=1), SomeComplexModel(s='b', i=2), SomeComplexModel(s='c', i=3), SomeComplexModel(s='d', i=4), SomeComplexModel(s='e', i=5), ] class SomeService(Service): @rpc(_returns=Array(SomeComplexModel)) def get(ctx): return v desc = SomeService.public_methods['get'] ctx = FakeContext(out_object=[v], descriptor=desc) ostr = ctx.out_stream = BytesIO() XmlDocument(Application([SomeService], __name__)) \ .serialize(ctx, XmlDocument.RESPONSE) elt = etree.fromstring(ostr.getvalue()) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath('x:getResult/x:SomeComplexModel/x:i/text()', namespaces={'x': __name__}) == ['1', '2', '3', '4', '5'] assert elt.xpath('x:getResult/x:SomeComplexModel/x:s/text()', namespaces={'x': __name__}) == ['a', 'b', 'c', 'd', 'e']
def test_one(self): class SomeComplexModel(ComplexModel): s = Unicode i = Integer v = SomeComplexModel(s='a', i=1), class SomeService(ServiceBase): @rpc(_returns=SomeComplexModel) def get(ctx): return v desc = SomeService.public_methods['get'] ctx = FakeContext(out_object=v, descriptor=desc) ostr = ctx.out_stream = BytesIO() XmlDocument(Application([SomeService], __name__)) \ .serialize(ctx, XmlDocument.RESPONSE) elt = etree.fromstring(ostr.getvalue()) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath('x:getResult/x:i/text()', namespaces={'x': __name__}) == ['1'] assert elt.xpath('x:getResult/x:s/text()', namespaces={'x': __name__}) == ['a']
def test_unicode_chars_in_exception(self): class SomeService(Service): @srpc(Unicode(pattern=u'x'), _returns=Unicode) def some_call(s): test(should, never, reach, here) app = Application([SomeService], "tns", name="test_mandatory_elements", in_protocol=XmlDocument(validator='lxml'), out_protocol=XmlDocument()) server = WsgiApplication(app) req = ( u'<some_call xmlns="tns">' u'<s>Ğ</s>' u'</some_call>' ).encode('utf8') print("AAA") resp = server({ 'QUERY_STRING': '', 'PATH_INFO': '/', 'REQUEST_METHOD': 'POST', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '80', 'wsgi.input': BytesIO(req), "wsgi.url_scheme": 'http', }, lambda x, y: print(x,y)) print("AAA") assert u'Ğ'.encode('utf8') in b''.join(resp)
def serialize(self, ctx, message): """Uses ``ctx.out_object``, ``ctx.out_header`` or ``ctx.out_error`` to set ``ctx.out_body_doc``, ``ctx.out_header_doc`` and ``ctx.out_document`` as an ``lxml.etree._Element instance``. Not meant to be overridden. """ assert message in (self.REQUEST, self.RESPONSE) self.event_manager.fire_event('before_serialize', ctx) if ctx.out_stream is None: ctx.out_stream = BytesIO() logger.debug("%r %d", ctx.out_stream, id(ctx.out_stream)) if ctx.out_error is not None: # All errors at this point must be Fault subclasses. inst = ctx.out_error cls = inst.__class__ name = cls.get_type_name() if self.developer_mode: # FIXME: the eff is this? ctx.out_object = (inst, ) retval = self._incgen(ctx, cls, inst, name) else: with self.docfile(ctx.out_stream, encoding=self.encoding) as xf: retval = self.to_parent(ctx, cls, inst, xf, name) else: assert message is self.RESPONSE result_class = ctx.descriptor.out_message name = result_class.get_type_name() if ctx.descriptor.body_style == BODY_STYLE_WRAPPED: if self.ignore_wrappers: result_inst = ctx.out_object[0] while result_class.Attributes._wrapper and \ len(result_class._type_info) == 1: result_class, = \ result_class._type_info.values() else: result_inst = result_class() for i, attr_name in enumerate( result_class._type_info.keys()): setattr(result_inst, attr_name, ctx.out_object[i]) else: result_inst, = ctx.out_object retval = self._incgen(ctx, result_class, result_inst, name) self.event_manager.fire_event('after_serialize', ctx) return retval
def test_soap_bare_wrapped_array_output(self): class SomeService(Service): @rpc(_body_style='bare', _returns=Array(String)) def some_call(ctx): return ['abc', 'def'] app = Application([SomeService], 'tns', in_protocol=Soap11(), out_protocol=Soap11(cleanup_namespaces=True)) req = b""" <soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="tns"> <soap11env:Body> <tns:some_call/> </soap11env:Body> </soap11env:Envelope> """ server = WsgiApplication(app) resp = etree.fromstring(b''.join(server({ 'QUERY_STRING': '', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'text/xml; charset=utf8', 'wsgi.input': BytesIO(req) }, start_response, "http://null"))) print(etree.tostring(resp, pretty_print=True)) assert resp[0].tag == '{http://schemas.xmlsoap.org/soap/envelope/}Body' assert resp[0][0].tag == '{tns}some_call' + RESPONSE_SUFFIX assert resp[0][0][0].text == 'abc' assert resp[0][0][1].text == 'def'
def test_file(self): v = b'aaaa' f = BytesIO(v) elt = get_object_as_xml(File.Value(handle=f), File, 'B') eltstr = etree.tostring(elt) print(eltstr) assert elt.text == b64encode(v).decode('ascii')
def test_thread_aux_wsgi(self): import logging logging.basicConfig(level=logging.DEBUG) data = set() class SomeService(Service): @srpc(String, _returns=String) def call(s): data.add(s) class AuxService(Service): __aux__ = ThreadAuxProc() @srpc(String, _returns=String) def call(s): data.add(s + "aux") app = Application([SomeService, AuxService], 'tns', in_protocol=HttpRpc(), out_protocol=HttpRpc()) server = WsgiApplication(app) server({ 'QUERY_STRING': 's=hey', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'text/xml; charset=utf8', 'SERVER_NAME': 'localhost', 'wsgi.input': BytesIO(), }, start_response, "http://null") import time time.sleep(1) assert data == set(['hey', 'heyaux'])
def serialize(self, ctx, message): """Uses ``ctx.out_object``, ``ctx.out_header`` or ``ctx.out_error`` to set ``ctx.out_body_doc``, ``ctx.out_header_doc`` and ``ctx.out_document`` as an ``lxml.etree._Element instance``. Not meant to be overridden. """ assert message in (self.REQUEST, self.RESPONSE) self.event_manager.fire_event('before_serialize', ctx) if ctx.out_stream is None: ctx.out_stream = BytesIO() logger.debug("%r %d", ctx.out_stream, id(ctx.out_stream)) if ctx.out_error is not None: # All errors at this point must be Fault subclasses. inst = ctx.out_error cls = inst.__class__ name = cls.get_type_name() ctx.out_document = E.div() with self.docfile(ctx.out_stream) as xf: # as XmlDocument is not push-ready yet, this is what we do. # this is an ugly hack, bear with me. retval = XmlCloth.HtmlMicroFormat() \ .to_parent(ctx, cls, inst, xf, name) else: assert message is self.RESPONSE result_message_class = ctx.descriptor.out_message name = result_message_class.get_type_name() if ctx.descriptor.body_style == BODY_STYLE_WRAPPED: if self.ignore_wrappers: result_message = ctx.out_object[0] while result_message_class.Attributes._wrapper and \ len(result_message_class._type_info) == 1: result_message_class, = \ result_message_class._type_info.values() else: result_message = result_message_class() for i, attr_name in enumerate( result_message_class._type_info.keys()): setattr(result_message, attr_name, ctx.out_object[i]) else: result_message, = ctx.out_object retval = self.incgen(ctx, result_message_class, result_message, name) self.event_manager.fire_event('after_serialize', ctx) return retval
def test_fault_generation(self): class SoapException(ServiceBase): @srpc() def soap_exception(): raise Fault("Client.Plausible", "A plausible fault", 'http://faultactor.example.com') app = Application([SoapException], 'tns', in_protocol=Soap12(), out_protocol=Soap12()) req = b""" <soap12env:Envelope xmlns:soap12env="http://www.w3.org/2003/05/soap-envelope" xmlns:tns="tns"> <soap12env:Body> <tns:soap_exception/> </soap12env:Body> </soap12env:Envelope> """ server = WsgiApplication(app) response = etree.fromstring(b''.join( server( { 'QUERY_STRING': '', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'text/xml; charset=utf8', 'wsgi.input': BytesIO(req) }, start_response, "http://null"))) response_str = etree.tostring(response, pretty_print=True) print(response_str) expected = b""" <soap12env:Envelope xmlns:soap12env="http://www.w3.org/2003/05/soap-envelope"> <soap12env:Body> <soap12env:Fault> <soap12env:Reason> <soap12env:Text xml:lang="en">A plausible fault</soap12env:Text> </soap12env:Reason> <soap12env:Role>http://faultactor.example.com</soap12env:Role> <soap12env:Code> <soap12env:Value>soap12env:Sender</soap12env:Value> <soap12env:Subcode> <soap12env:Value>Plausible</soap12env:Value> </soap12env:Subcode> </soap12env:Code> </soap12env:Fault> </soap12env:Body> </soap12env:Envelope>""" if not LXMLOutputChecker().check_output(expected, response_str, PARSE_XML): raise Exception("Got: %s but expected: %s" % (response_str, expected))
def test_rpc(self): data = {"a":"b", "c": "d"} class KeyValuePair(ComplexModel): key = Unicode value = Unicode class SomeService(Service): @rpc(String(max_occurs='unbounded'), _returns=Array(KeyValuePair), _in_variable_names={ 'keys': 'key' } ) def get_values(ctx, keys): for k in keys: yield KeyValuePair(key=k, value=data[k]) application = Application([SomeService], in_protocol=MessagePackRpc(), out_protocol=MessagePackRpc(ignore_wrappers=False), name='Service', tns='tns') server = WsgiApplication(application) input_string = msgpack.packb([0, 0, "get_values", [["a", "c"]]]) input_stream = BytesIO(input_string) ret = server({ 'CONTENT_LENGTH': str(len(input_string)), 'CONTENT_TYPE': 'application/x-msgpack', 'HTTP_CONNECTION': 'close', 'HTTP_CONTENT_LENGTH': str(len(input_string)), 'HTTP_CONTENT_TYPE': 'application/x-msgpack', 'PATH_INFO': '/', 'QUERY_STRING': '', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '7000', 'REQUEST_METHOD': 'POST', 'wsgi.url_scheme': 'http', 'wsgi.input': input_stream, }, start_response) ret = b''.join(ret) print(repr(ret)) ret = msgpack.unpackb(ret) print(repr(ret)) s = [1, 0, None, {b'get_valuesResponse': { b'get_valuesResult': [ {b"KeyValuePair": {b'key': b'a', b'value': b'b'}}, {b"KeyValuePair": {b'key': b'c', b'value': b'd'}}, ] }} ] print(s) assert ret == s
def chart(ctx, typename): """Return a sparkline chart of the given type.""" data = ctx.descriptor.service_class.history[typename] height = 20.0 scale = height / max(data) im = Image.new("RGB", (len(data), int(height)), 'white') draw = ImageDraw.Draw(im) draw.line([(i, int(height - (v * scale))) for i, v in enumerate(data)], fill="#009900") del draw f = BytesIO() im.save(f, "PNG") result = f.getvalue() ctx.out_protocol = HttpRpc() ctx.transport.resp_headers["Content-Type"] = "image/png" return [result]
def test_mtom_join_envelope_chunks(self): FILE_NAME = 'EA055406-5881-4F02-A3DC-9A5A7510D018.dat' TNS = 'http://gib.gov.tr/vedop3/eFatura' # large enough payload to be chunked PAYLOAD = b"sample data " * 1024 class SomeService(Service): @rpc(Unicode(sub_name="fileName"), ByteArray(sub_name='binaryData'), ByteArray(sub_name="hash"), _returns=Unicode) def documentRequest(ctx, file_name, file_data, data_hash): assert file_name == FILE_NAME assert file_data == (PAYLOAD, ) return file_name app = Application([SomeService], tns=TNS, in_protocol=Soap12(), out_protocol=Soap12()) server = WsgiApplication(app, block_length=1024) response = etree.fromstring(b''.join( server( { 'QUERY_STRING': '', 'PATH_INFO': '/call', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'Content-Type: multipart/related; ' 'type="application/xop+xml"; ' 'boundary="uuid:2e53e161-b47f-444a-b594-eb6b72e76997"; ' 'start="<*****@*****.**>"; ' 'start-info="application/soap+xml"; action="sendDocument"', 'wsgi.input': BytesIO( MTOM_REQUEST.replace(b"\n", b"\r\n").replace( b"sample data", PAYLOAD)), }, start_response, "http://null"))) response_str = etree.tostring(response, pretty_print=True) print(response_str) nsdict = dict(tns=TNS) assert etree.fromstring(response_str) \ .xpath(".//tns:documentRequestResult/text()", namespaces=nsdict) \ == [FILE_NAME]
class TestXmlClothToParent(unittest.TestCase): def setUp(self): self.ctx = FakeContext() self.stream = BytesIO() logging.basicConfig(level=logging.DEBUG) def _run(self, inst, cls=None): if cls is None: cls = inst.__class__ with etree.xmlfile(self.stream) as parent: XmlCloth().subserialize(self.ctx, cls, inst, parent, name=cls.__name__) elt = etree.fromstring(self.stream.getvalue()) print(etree.tostring(elt, pretty_print=True)) return elt def test_simple(self): v = 'punk.' elt = self._run(v, Unicode) assert elt.text == v def test_complex_primitive(self): class SomeObject(ComplexModel): s = Unicode v = 'punk.' elt = self._run(SomeObject(s=v)) assert elt[0].text == v def test_complex_inheritance(self): class A(ComplexModel): i = Integer class B(A): s = Unicode i = 42 s = 'punk.' elt = self._run(B(i=i, s=s)) # order is important assert len(elt) == 2 assert elt[0].text == str(i) assert elt[1].text == s
def test_method_exception(self): from spyne.protocol.xml import XmlDocument h = [0] def on_method_exception_object(ctx): assert ctx.out_error is not None from spyne.protocol.xml import SchemaValidationError assert isinstance(ctx.out_error, SchemaValidationError) logging.error(repr(ctx.out_error)) h[0] += 1 class SomeService(Service): @rpc(Unicode(5)) def some_call(ctx, some_str): print(some_str) app = Application([SomeService], "some_tns", in_protocol=XmlDocument(validator='lxml'), out_protocol=Soap11()) app.event_manager.add_listener( "method_exception_object", on_method_exception_object) # this shouldn't be called because: # 1. document isn't validated # 2. hence; document can't be parsed # 3. hence; document can't be mapped to a function # 4. hence; document can't be mapped to a service class # 5. hence; no handlers from the service class is invoked. # 6. hence; the h[0] == 1 check (instead of 2) SomeService.event_manager.add_listener( "method_exception_object", on_method_exception_object) wsgi_app = WsgiApplication(app) xml_request = b""" <tns:some_call xmlns:tns="some_tns"> <tns:some_str>123456</tns:some_str> </tns:some_call> """ _ = b''.join(wsgi_app({ 'PATH_INFO': '/', 'SERVER_NAME': 'localhost', 'SERVER_PORT': '7000', 'REQUEST_METHOD': 'POST', 'wsgi.url_scheme': 'http', 'wsgi.input': BytesIO(xml_request), }, start_response)) assert h[0] == 1
def stream_factory(total_content_length, filename, content_type, content_length=None): if total_content_length >= SWAP_DATA_TO_FILE_THRESHOLD or \ delete == False: if delete == False: # You need python >= 2.6 for this. retval = tempfile.NamedTemporaryFile('wb+', dir=dir, delete=delete) else: retval = tempfile.NamedTemporaryFile('wb+', dir=dir) else: retval = BytesIO() return retval
def __run_service(self, service): app = Application([service], 'tns', in_protocol=HttpRpc(), out_protocol=Soap11()) server = WsgiApplication(app) return_string = b''.join(server({ 'QUERY_STRING': '', 'PATH_INFO': '/some_call', 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'text/xml; charset=utf8', 'SERVER_NAME': 'localhost', 'wsgi.input': BytesIO(b""), }, start_response, "http://null")) elt = etree.fromstring(return_string) print(etree.tostring(elt, pretty_print=True)) return elt, app.interface.nsmap
class TestXmlCloth(unittest.TestCase): def setUp(self): self.ctx = FakeContext() self.stream = BytesIO() logging.basicConfig(level=logging.DEBUG) def _run(self, inst, spid=None, cloth=None): cls = inst.__class__ if cloth is None: assert spid is not None cloth = etree.fromstring("""<a><b spyne_id="%s"></b></a>""" % spid) else: assert spid is None with etree.xmlfile(self.stream) as parent: XmlCloth(cloth=cloth).set_identifier_prefix("spyne_").subserialize(self.ctx, cls, inst, parent) elt = etree.fromstring(self.stream.getvalue()) print(etree.tostring(elt, pretty_print=True)) return elt def test_simple_value(self): class SomeObject(ComplexModel): s = Unicode v = "punk." elt = self._run(SomeObject(s=v), spid="s") assert elt[0].text == v def test_simple_empty(self): class SomeObject(ComplexModel): s = Unicode elt = self._run(SomeObject(), spid="s") assert len(elt) == 0 # FIXME: just fix it def _test_simple_empty_nonoptional(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) elt = self._run(SomeObject(), spid="s") assert elt[0].text is None # FIXME: just fix it def _test_simple_empty_nonoptional_clear(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) cloth = etree.fromstring("""<a><b spyne_id="s">oi punk!</b></a>""") elt = self._run(SomeObject(), cloth=cloth) assert elt[0].text is None def test_xml_data_tag(self): class SomeObject(ComplexModel): d = XmlData(Unicode) cloth = etree.fromstring('<a><spyne_data spyne_id="d"/></a>') elt = self._run(SomeObject(d="data"), cloth=cloth) assert elt.text == "data" def test_xml_data_attr(self): class SomeObject(ComplexModel): d = XmlData(Unicode) cloth = etree.fromstring('<a spyne_data="d"></a>') elt = self._run(SomeObject(d="data"), cloth=cloth) assert elt.text == "data" def test_xml_data_attr(self): class SomeObject(ComplexModel): d = XmlData(Unicode) cloth = etree.fromstring('<a spyne_data="d"></a>') elt = self._run(SomeObject(d="data"), cloth=cloth) assert elt.text == "data" def test_xml_data_attr_undesignated(self): class SomeObject(ComplexModel): d = Unicode cloth = etree.fromstring('<a spyne_data="d"></a>') elt = self._run(SomeObject(d="data"), cloth=cloth) assert elt.text == "data" def test_simple_value_xmlattribute(self): v = "punk." class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1)) cloth = etree.fromstring("""<a></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib["s"] == v def test_simple_value_xmlattribute_subname(self): v = "punk." class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1, sub_name="foo")) cloth = etree.fromstring("""<a></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib["foo"] == v def test_simple_value_xmlattribute_non_immediate(self): v = "punk." class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1, sub_name="foo")) cloth = etree.fromstring("""<a><b spyne_attr="s"/></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib["foo"] == v assert elt[0].attrib["foo"] == v def test_simple_value_xmlattribute_non_immediate_non_designated(self): v = "punk." class SomeObject(ComplexModel): s = Unicode(min_occurs=1, sub_name="foo") cloth = etree.fromstring("""<a><b spyne_attr="s"/></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert not "foo" in elt.attrib assert elt[0].attrib["foo"] == v def test_non_tagbag(self): cloth = E.a(E.b(E.c(E.d(spyne_id="i"), spyne_id="c"), spyne_id="i"), spyne_tagbag="") class C2(ComplexModel): i = Integer class C1(ComplexModel): i = Integer c = C2 elt = self._run(C1(i=1, c=C2(i=2)), cloth=cloth) assert elt.xpath("//b/text()") == ["1"] # no order guarantee is given assert set(elt.xpath("//d/text()")) == set(["1", "2"]) def test_array(self): v = range(3) class SomeObject(ComplexModel): s = Array(Integer) cloth = E.a(E.b(E.c(spyne_id="integer"), spyne_id="s")) elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.xpath("//c/text()") == [str(i) for i in v] def test_array_empty(self): class SomeObject(ComplexModel): s = Array(Integer) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath("//c") == [] # FIXME: just fix it def _test_array_empty_nonoptional(self): class SomeObject(ComplexModel): s = Array(Integer(min_occurs=1)) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath("//c") == [cloth[0][0]] def test_simple_two_tags(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s="s", i=5) cloth = E.a(E.b1(), E.b2(E.c1(spyne_id="s"), E.c2()), E.e(E.g1(), E.g2(spyne_id="i"), E.g3())) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == "b1" assert elt[1].tag == "b2" assert elt[1][0].tag == "c1" assert elt[1][0].text == "s" assert elt[1][1].tag == "c2" assert elt[2].tag == "e" assert elt[2][0].tag == "g1" assert elt[2][1].tag == "g2" assert elt[2][1].text == "5" assert elt[2][2].tag == "g3" def test_sibling_order(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s="s") cloth = E.a(E.b1(), E.b2(E.c0(), E.c1(), E.c2(spyne_id="s"), E.c3(), E.c4())) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == "b1" assert elt[1].tag == "b2" assert elt[1][0].tag == "c0" assert elt[1][1].tag == "c1" assert elt[1][2].tag == "c2" assert elt[1][2].text == "s" assert elt[1][3].tag == "c3" assert elt[1][4].tag == "c4" def test_parent_text(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s="s") cloth = E.a("text 0", E.b1(spyne_id="s")) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.tag == "a" assert elt.text == "text 0" assert elt[0].tag == "b1" assert elt[0].text == "s" def test_anc_text(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s="s") cloth = E.a(E.b1("text 1", E.c1(spyne_id="s"))) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == "b1" assert elt[0].text == "text 1" assert elt[0][0].tag == "c1" assert elt[0][0].text == "s" def test_prevsibl_tail(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s="s") cloth = E.a(E.b1(E.c1(), "text 2", E.c2(spyne_id="s"))) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == "b1" assert elt[0][0].tag == "c1" assert elt[0][0].tail == "text 2" assert elt[0][1].text == "s" def test_sibling_tail_close(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s="s") cloth = E.a(E.b0(spyne_id="s"), "text 3") print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == "b0" assert elt[0].text == "s" assert elt[0].tail == "text 3" def test_sibling_tail_close_sibling(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s="s", i=5) cloth = E.a(E.b0(spyne_id="s"), "text 3", E.b1(spyne_id="i")) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == "b0" assert elt[0].text == "s" assert elt[0].tail == "text 3" def test_sibling_tail_close_anc(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s="s", i=5) cloth = E.a( E.b0(), "text 0", E.b1(E.c0(spyne_id="s"), "text 1", E.c1(), "text 2"), "text 3", E.b2(E.c1(spyne_id="i"), "text 4"), ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath("/a/b1/c0")[0].tail == "text 1" assert elt.xpath("/a/b1/c1")[0].tail == "text 2" assert elt.xpath("/a/b2/c1")[0].tail == "text 4" def test_nested_conflicts(self): class SomeObject(ComplexModel): s = Unicode i = Integer c = SelfReference v = SomeObject(s="x", i=1, c=SomeObject(s="y", i=2)) cloth = E.a( E.b0(), "text 0", E.b1(E.c0(spyne_id="s"), "text 1", E.c1(E.d0(spyne_id="s"), E.d1(spyne_id="i"), spyne_id="c"), "text 2"), "text 3", E.b2(E.c2(spyne_id="i"), "text 4"), ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath("/a/b1/c0")[0].text == str(v.s) assert elt.xpath("/a/b1/c1/d0")[0].text == str(v.c.s) assert elt.xpath("/a/b1/c1/d1")[0].text == str(v.c.i) assert elt.xpath("/a/b2/c2")[0].text == str(v.i)
def setUp(self): self.ctx = FakeContext() self.stream = BytesIO() logging.basicConfig(level=logging.DEBUG)
class TestXmlCloth(unittest.TestCase): def setUp(self): self.ctx = FakeContext() self.stream = BytesIO() logging.basicConfig(level=logging.DEBUG) def _run(self, inst, spid=None, cloth=None): cls = inst.__class__ if cloth is None: assert spid is not None cloth = etree.fromstring("""<a><b spyne_id="%s"></b></a>""" % spid) else: assert spid is None with etree.xmlfile(self.stream) as parent: XmlCloth(cloth=cloth).subserialize(self.ctx, cls, inst, parent) elt = etree.fromstring(self.stream.getvalue()) print etree.tostring(elt, pretty_print=True) return elt def test_simple_value(self): class SomeObject(ComplexModel): s = Unicode v = 'punk.' elt = self._run(SomeObject(s=v), spid='s') assert elt[0].text == v def test_simple_empty(self): class SomeObject(ComplexModel): s = Unicode elt = self._run(SomeObject(), spid='s') assert len(elt) == 0 # FIXME: just fix it def _test_simple_empty_nonoptional(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) elt = self._run(SomeObject(), spid='s') assert elt[0].text is None # FIXME: just fix it def _test_simple_empty_nonoptional_clear(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) cloth = etree.fromstring("""<a><b spyne_id="s">oi punk!</b></a>""") elt = self._run(SomeObject(), cloth=cloth) assert elt[0].text is None def test_simple_value_xmlattribute(self): v = 'punk.' class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1)) cloth = etree.fromstring("""<a></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib['s'] == v def test_array(self): v = range(3) class SomeObject(ComplexModel): s = Array(Integer) cloth = E.a( E.b( E.c(spyne_id="integer"), spyne_id="s", ) ) elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.xpath('//c/text()') == [str(i) for i in v] def test_array_empty(self): class SomeObject(ComplexModel): s = Array(Integer) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath('//c') == [] # FIXME: just fix it def _test_array_empty_nonoptional(self): class SomeObject(ComplexModel): s = Array(Integer(min_occurs=1)) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath('//c') == [cloth[0][0]] def test_simple_two_tags(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s='s', i=5) cloth = E.a( E.b1(), E.b2( E.c1(spyne_id="s"), E.c2(), ), E.e( E.g1(), E.g2(spyne_id="i"), E.g3(), ), ) elt = self._run(v, cloth=cloth) print etree.tostring(elt, pretty_print=True) assert elt[0].tag == 'b1' assert elt[1].tag == 'b2' assert elt[1][0].tag == 'c1' assert elt[1][0].text == 's' assert elt[1][1].tag == 'c2' assert elt[2].tag == 'e' assert elt[2][0].tag == 'g1' assert elt[2][1].tag == 'g2' assert elt[2][1].text == '5' assert elt[2][2].tag == 'g3'
class TestXmlCloth(unittest.TestCase): def setUp(self): self.ctx = FakeContext() self.stream = BytesIO() logging.basicConfig(level=logging.DEBUG) def _run(self, inst, spid=None, cloth=None): cls = inst.__class__ if cloth is None: assert spid is not None cloth = etree.fromstring("""<a><b spyne_id="%s"></b></a>""" % spid) else: assert spid is None with etree.xmlfile(self.stream) as parent: XmlCloth.ID_ATTR_NAME = 'spyne_id' XmlCloth.TAGBAG_ATTR_NAME = 'spyne_tagbag' XmlCloth(cloth=cloth).subserialize(self.ctx, cls, inst, parent) elt = etree.fromstring(self.stream.getvalue()) print(etree.tostring(elt, pretty_print=True)) return elt def test_simple_value(self): class SomeObject(ComplexModel): s = Unicode v = 'punk.' elt = self._run(SomeObject(s=v), spid='s') assert elt[0].text == v def test_simple_empty(self): class SomeObject(ComplexModel): s = Unicode elt = self._run(SomeObject(), spid='s') assert len(elt) == 0 # FIXME: just fix it def _test_simple_empty_nonoptional(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) elt = self._run(SomeObject(), spid='s') assert elt[0].text is None # FIXME: just fix it def _test_simple_empty_nonoptional_clear(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) cloth = etree.fromstring("""<a><b spyne_id="s">oi punk!</b></a>""") elt = self._run(SomeObject(), cloth=cloth) assert elt[0].text is None def test_simple_value_xmlattribute(self): v = 'punk.' class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1)) cloth = etree.fromstring("""<a></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib['s'] == v def test_non_tagbag(self): cloth = E.a( E.b( E.c( E.d( spyne_id="i", ), spyne_id="c", ), spyne_id="i", ), spyne_tagbag='', ) class C2(ComplexModel): i = Integer class C1(ComplexModel): i = Integer c = C2 elt = self._run(C1(i=1, c=C2(i=2)), cloth=cloth) assert elt.xpath('//b/text()') == ['1'] # no order guarantee is given assert set(elt.xpath('//d/text()')) == set(['1', '2']) def test_array(self): v = range(3) class SomeObject(ComplexModel): s = Array(Integer) cloth = E.a( E.b( E.c(spyne_id="integer"), spyne_id="s", ) ) elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.xpath('//c/text()') == [str(i) for i in v] def test_array_empty(self): class SomeObject(ComplexModel): s = Array(Integer) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath('//c') == [] # FIXME: just fix it def _test_array_empty_nonoptional(self): class SomeObject(ComplexModel): s = Array(Integer(min_occurs=1)) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath('//c') == [cloth[0][0]] def test_simple_two_tags(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s='s', i=5) cloth = E.a( E.b1(), E.b2( E.c1(spyne_id="s"), E.c2(), ), E.e( E.g1(), E.g2(spyne_id="i"), E.g3(), ), ) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[1].tag == 'b2' assert elt[1][0].tag == 'c1' assert elt[1][0].text == 's' assert elt[1][1].tag == 'c2' assert elt[2].tag == 'e' assert elt[2][0].tag == 'g1' assert elt[2][1].tag == 'g2' assert elt[2][1].text == '5' assert elt[2][2].tag == 'g3' def test_sibling_order(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b1(), E.b2( E.c0(), E.c1(), E.c2(spyne_id="s"), E.c3(), E.c4(), ), ) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[1].tag == 'b2' assert elt[1][0].tag == 'c0' assert elt[1][1].tag == 'c1' assert elt[1][2].tag == 'c2' assert elt[1][2].text == 's' assert elt[1][3].tag == 'c3' assert elt[1][4].tag == 'c4' def test_parent_text(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( "text 0", E.b1(spyne_id="s"), ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.tag == 'a' assert elt.text == 'text 0' assert elt[0].tag == 'b1' assert elt[0].text == 's' def test_anc_text(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b1( "text 1", E.c1(spyne_id="s"), ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[0].text == 'text 1' assert elt[0][0].tag == 'c1' assert elt[0][0].text == 's' def test_prevsibl_tail(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b1( E.c1(), "text 2", E.c2(spyne_id="s"), ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[0][0].tag == 'c1' assert elt[0][0].tail == 'text 2' assert elt[0][1].text == 's' def test_sibling_tail_close(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b0(spyne_id="s"), "text 3", ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b0' assert elt[0].text == 's' assert elt[0].tail == 'text 3' def test_sibling_tail_close_sibling(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s='s', i=5) cloth = E.a( E.b0(spyne_id="s"), "text 3", E.b1(spyne_id="i"), ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b0' assert elt[0].text == 's' assert elt[0].tail == 'text 3' def test_sibling_tail_close_anc(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s='s', i=5) cloth = E.a( E.b0(), "text 0", E.b1( E.c0(spyne_id="s"), "text 1", E.c1(), "text 2", ), "text 3", E.b2( E.c1(spyne_id="i"), "text 4", ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath('/a/b1/c0')[0].tail == 'text 1' assert elt.xpath('/a/b1/c1')[0].tail == 'text 2' assert elt.xpath('/a/b2/c1')[0].tail == 'text 4' def test_nested_conflicts(self): class SomeObject(ComplexModel): s = Unicode i = Integer c = SelfReference v = SomeObject(s='x', i=1, c=SomeObject(s='y', i=2)) cloth = E.a( E.b0(), "text 0", E.b1( E.c0(spyne_id="s"), "text 1", E.c1( E.d0(spyne_id="s"), E.d1(spyne_id="i"), spyne_id="c", ), "text 2", ), "text 3", E.b2( E.c2(spyne_id="i"), "text 4", ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath('/a/b1/c0')[0].text == str(v.s) assert elt.xpath('/a/b1/c1/d0')[0].text == str(v.c.s) assert elt.xpath('/a/b1/c1/d1')[0].text == str(v.c.i) assert elt.xpath('/a/b2/c2')[0].text == str(v.i)
class TestXmlCloth(unittest.TestCase): def setUp(self): self.ctx = FakeContext() self.stream = BytesIO() logging.basicConfig(level=logging.DEBUG) def _run(self, inst, spid=None, cloth=None): cls = inst.__class__ if cloth is None: assert spid is not None cloth = etree.fromstring("""<a><b spyne_id="%s"></b></a>""" % spid) else: assert spid is None with etree.xmlfile(self.stream) as parent: XmlCloth(cloth=cloth).set_identifier_prefix('spyne_') \ .subserialize(self.ctx, cls, inst, parent) elt = etree.fromstring(self.stream.getvalue()) print(etree.tostring(elt, pretty_print=True)) return elt def test_simple_value(self): class SomeObject(ComplexModel): s = Unicode v = 'punk.' elt = self._run(SomeObject(s=v), spid='s') assert elt[0].text == v def test_simple_empty(self): class SomeObject(ComplexModel): s = Unicode elt = self._run(SomeObject(), spid='s') assert len(elt) == 0 # FIXME: just fix it def _test_simple_empty_nonoptional(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) elt = self._run(SomeObject(), spid='s') assert elt[0].text is None # FIXME: just fix it def _test_simple_empty_nonoptional_clear(self): class SomeObject(ComplexModel): s = Unicode(min_occurs=1) cloth = etree.fromstring("""<a><b spyne_id="s">oi punk!</b></a>""") elt = self._run(SomeObject(), cloth=cloth) assert elt[0].text is None def test_xml_data_tag(self): class SomeObject(ComplexModel): d = XmlData(Unicode) cloth = etree.fromstring('<a><spyne_data spyne_id="d"/></a>') elt = self._run(SomeObject(d='data'), cloth=cloth) assert elt.text == 'data' def test_xml_data_attr(self): class SomeObject(ComplexModel): d = XmlData(Unicode) cloth = etree.fromstring('<a spyne_data="d"></a>') elt = self._run(SomeObject(d='data'), cloth=cloth) assert elt.text == 'data' def test_xml_data_attr(self): class SomeObject(ComplexModel): d = XmlData(Unicode) cloth = etree.fromstring('<a spyne_data="d"></a>') elt = self._run(SomeObject(d='data'), cloth=cloth) assert elt.text == 'data' def test_xml_data_attr_undesignated(self): class SomeObject(ComplexModel): d = Unicode cloth = etree.fromstring('<a spyne_data="d"></a>') elt = self._run(SomeObject(d='data'), cloth=cloth) assert elt.text == 'data' def test_simple_value_xmlattribute(self): v = 'punk.' class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1)) cloth = etree.fromstring("""<a></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib['s'] == v def test_simple_value_xmlattribute_subname(self): v = 'punk.' class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1, sub_name='foo')) cloth = etree.fromstring("""<a></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib['foo'] == v def test_simple_value_xmlattribute_non_immediate(self): v = 'punk.' class SomeObject(ComplexModel): s = XmlAttribute(Unicode(min_occurs=1, sub_name='foo')) cloth = etree.fromstring("""<a><b spyne_attr="s"/></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.attrib['foo'] == v assert elt[0].attrib['foo'] == v def test_simple_value_xmlattribute_non_immediate_non_designated(self): v = 'punk.' class SomeObject(ComplexModel): s = Unicode(min_occurs=1, sub_name='foo') cloth = etree.fromstring("""<a><b spyne_attr="s"/></a>""") elt = self._run(SomeObject(s=v), cloth=cloth) assert not 'foo' in elt.attrib assert elt[0].attrib['foo'] == v def test_non_tagbag(self): cloth = E.a( E.b( E.c( E.d( spyne_id="i", ), spyne_id="c", ), spyne_id="i", ), spyne_tagbag='', ) class C2(ComplexModel): i = Integer class C1(ComplexModel): i = Integer c = C2 elt = self._run(C1(i=1, c=C2(i=2)), cloth=cloth) assert elt.xpath('//b/text()') == ['1'] # no order guarantee is given assert set(elt.xpath('//d/text()')) == set(['1', '2']) def test_array(self): v = range(3) class SomeObject(ComplexModel): s = Array(Integer) cloth = E.a( E.b( E.c(spyne_id="integer"), spyne_id="s", ) ) elt = self._run(SomeObject(s=v), cloth=cloth) assert elt.xpath('//c/text()') == [str(i) for i in v] def test_array_empty(self): class SomeObject(ComplexModel): s = Array(Integer) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath('//c') == [] # FIXME: just fix it def _test_array_empty_nonoptional(self): class SomeObject(ComplexModel): s = Array(Integer(min_occurs=1)) elt_str = '<a><b spyne_id="s"><c spyne_id="integer"></c></b></a>' cloth = etree.fromstring(elt_str) elt = self._run(SomeObject(), cloth=cloth) assert elt.xpath('//c') == [cloth[0][0]] def test_simple_two_tags(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s='s', i=5) cloth = E.a( E.b1(), E.b2( E.c1(spyne_id="s"), E.c2(), ), E.e( E.g1(), E.g2(spyne_id="i"), E.g3(), ), ) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[1].tag == 'b2' assert elt[1][0].tag == 'c1' assert elt[1][0].text == 's' assert elt[1][1].tag == 'c2' assert elt[2].tag == 'e' assert elt[2][0].tag == 'g1' assert elt[2][1].tag == 'g2' assert elt[2][1].text == '5' assert elt[2][2].tag == 'g3' def test_sibling_order(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b1(), E.b2( E.c0(), E.c1(), E.c2(spyne_id="s"), E.c3(), E.c4(), ), ) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[1].tag == 'b2' assert elt[1][0].tag == 'c0' assert elt[1][1].tag == 'c1' assert elt[1][2].tag == 'c2' assert elt[1][2].text == 's' assert elt[1][3].tag == 'c3' assert elt[1][4].tag == 'c4' def test_parent_text(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( "text 0", E.b1(spyne_id="s"), ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.tag == 'a' assert elt.text == 'text 0' assert elt[0].tag == 'b1' assert elt[0].text == 's' def test_anc_text(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b1( "text 1", E.c1(spyne_id="s"), ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[0].text == 'text 1' assert elt[0][0].tag == 'c1' assert elt[0][0].text == 's' def test_prevsibl_tail(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b1( E.c1(), "text 2", E.c2(spyne_id="s"), ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b1' assert elt[0][0].tag == 'c1' assert elt[0][0].tail == 'text 2' assert elt[0][1].text == 's' def test_sibling_tail_close(self): class SomeObject(ComplexModel): s = Unicode v = SomeObject(s='s') cloth = E.a( E.b0(spyne_id="s"), "text 3", ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b0' assert elt[0].text == 's' assert elt[0].tail == 'text 3' def test_sibling_tail_close_sibling(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s='s', i=5) cloth = E.a( E.b0(spyne_id="s"), "text 3", E.b1(spyne_id="i"), ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt[0].tag == 'b0' assert elt[0].text == 's' assert elt[0].tail == 'text 3' def test_sibling_tail_close_anc(self): class SomeObject(ComplexModel): s = Unicode i = Integer v = SomeObject(s='s', i=5) cloth = E.a( E.b0(), "text 0", E.b1( E.c0(spyne_id="s"), "text 1", E.c1(), "text 2", ), "text 3", E.b2( E.c1(spyne_id="i"), "text 4", ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath('/a/b1/c0')[0].tail == 'text 1' assert elt.xpath('/a/b1/c1')[0].tail == 'text 2' assert elt.xpath('/a/b2/c1')[0].tail == 'text 4' def test_nested_conflicts(self): class SomeObject(ComplexModel): s = Unicode i = Integer c = SelfReference v = SomeObject(s='x', i=1, c=SomeObject(s='y', i=2)) cloth = E.a( E.b0(), "text 0", E.b1( E.c0(spyne_id="s"), "text 1", E.c1( E.d0(spyne_id="s"), E.d1(spyne_id="i"), spyne_id="c", ), "text 2", ), "text 3", E.b2( E.c2(spyne_id="i"), "text 4", ) ) print(etree.tostring(cloth, pretty_print=True)) elt = self._run(v, cloth=cloth) print(etree.tostring(elt, pretty_print=True)) assert elt.xpath('/a/b1/c0')[0].text == str(v.s) assert elt.xpath('/a/b1/c1/d0')[0].text == str(v.c.s) assert elt.xpath('/a/b1/c1/d1')[0].text == str(v.c.i) assert elt.xpath('/a/b2/c2')[0].text == str(v.i)