|
| 1 | +from datetime import datetime |
| 2 | + |
| 3 | +import pytest |
| 4 | +import xmltodict |
| 5 | +from xmlrpcproto.common import Binary, py2xml, xml2py |
| 6 | +from lxml import etree |
| 7 | + |
| 8 | + |
| 9 | +CASES = [ |
| 10 | + ( |
| 11 | + Binary("you can't read this!".encode()), |
| 12 | + "<base64>eW91IGNhbid0IHJlYWQgdGhpcyE=</base64>", |
| 13 | + ), |
| 14 | + (-12.53, "<double>-12.53</double>"), |
| 15 | + ("Hello world!", "<string>Hello world!</string>"), |
| 16 | + ( |
| 17 | + datetime(year=1998, month=7, day=17, hour=14, minute=8, second=55), |
| 18 | + "<dateTime.iso8601>19980717T14:08:55</dateTime.iso8601>", |
| 19 | + ), |
| 20 | + (42, "<i4>42</i4>"), |
| 21 | + (True, "<boolean>1</boolean>"), |
| 22 | + (False, "<boolean>0</boolean>"), |
| 23 | + (None, "<nil/>"), |
| 24 | + ( |
| 25 | + [1404, "Something here", 1], |
| 26 | + ( |
| 27 | + "<array>" |
| 28 | + "<data>" |
| 29 | + "<value>" |
| 30 | + "<i4>1404</i4>" |
| 31 | + "</value>" |
| 32 | + "<value>" |
| 33 | + "<string>Something here</string>" |
| 34 | + "</value>" |
| 35 | + "<value>" |
| 36 | + "<i4>1</i4>" |
| 37 | + "</value>" |
| 38 | + "</data>" |
| 39 | + "</array>" |
| 40 | + ), |
| 41 | + ), |
| 42 | + ( |
| 43 | + {"foo": 1}, |
| 44 | + ( |
| 45 | + "<struct>" |
| 46 | + "<member>" |
| 47 | + "<name>foo</name>" |
| 48 | + "<value><i4>1</i4></value>" |
| 49 | + "</member>" |
| 50 | + "</struct>" |
| 51 | + ), |
| 52 | + ), |
| 53 | + ( |
| 54 | + [[1, "a"]], |
| 55 | + ( |
| 56 | + "<array>" |
| 57 | + "<data>" |
| 58 | + "<value>" |
| 59 | + "<array>" |
| 60 | + "<data>" |
| 61 | + "<value>" |
| 62 | + "<i4>1</i4>" |
| 63 | + "</value>" |
| 64 | + "<value>" |
| 65 | + "<string>a</string>" |
| 66 | + "</value>" |
| 67 | + "</data>" |
| 68 | + "</array>" |
| 69 | + "</value>" |
| 70 | + "</data>" |
| 71 | + "</array>" |
| 72 | + ), |
| 73 | + ), |
| 74 | +] |
| 75 | + |
| 76 | + |
| 77 | +def normalise_dict(d): |
| 78 | + """ |
| 79 | + Recursively convert dict-like object (eg OrderedDict) into plain dict. |
| 80 | + Sorts list values. |
| 81 | + """ |
| 82 | + out = {} |
| 83 | + for k, v in dict(d).items(): |
| 84 | + if hasattr(v, "iteritems"): |
| 85 | + out[k] = normalise_dict(v) |
| 86 | + elif isinstance(v, list): |
| 87 | + out[k] = [] |
| 88 | + for item in sorted(v): |
| 89 | + if hasattr(item, "iteritems"): |
| 90 | + out[k].append(normalise_dict(item)) |
| 91 | + else: |
| 92 | + out[k].append(item) |
| 93 | + else: |
| 94 | + out[k] = v |
| 95 | + return out |
| 96 | + |
| 97 | + |
| 98 | +@pytest.mark.parametrize("expected,data", CASES) |
| 99 | +def test_xml2py(expected, data): |
| 100 | + data = etree.fromstring(data) |
| 101 | + result = xml2py(data) |
| 102 | + assert result == expected |
| 103 | + |
| 104 | + |
| 105 | +@pytest.mark.parametrize("data,expected", CASES) |
| 106 | +def test_py2xml(data, expected): |
| 107 | + a = py2xml(data) |
| 108 | + b = expected |
| 109 | + |
| 110 | + if not isinstance(a, str): |
| 111 | + a = etree.tostring(a, encoding="utf-8") |
| 112 | + if not isinstance(b, str): |
| 113 | + b = etree.tostring(b, encoding="utf-8") |
| 114 | + |
| 115 | + _a = normalise_dict(xmltodict.parse(a)) |
| 116 | + _b = normalise_dict(xmltodict.parse(b)) |
| 117 | + |
| 118 | + assert _a == _b, "\n %s \n not equal \n %s" % (a.decode(), b) |
0 commit comments