Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ _autorest_install: &_autorest_install
- sudo apt-get install libunwind8-dev
- nvm install 7
- npm install # Install test server pre-requisites
- cd node_modules/@microsoft.azure/autorest.testserver
- npm start &
jobs:
include:
- stage: MyPy
Expand Down
25 changes: 23 additions & 2 deletions msrest/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,8 @@ def serialize_object(self, attr, **kwargs):
"""
if attr is None:
return None
if isinstance(attr, ET.Element):
return attr
obj_type = type(attr)
if obj_type in self.basic_types:
return self.serialize_basic(attr, self.basic_types[obj_type], **kwargs)
Expand Down Expand Up @@ -1410,8 +1412,6 @@ def deserialize_data(self, data, data_type):
if data_type in self.deserialize_type:
if isinstance(data, self.deserialize_expected_types.get(data_type, tuple())):
return data
if isinstance(data, ET.Element):
data = data.text
data_val = self.deserialize_type[data_type](data)
return data_val

Expand Down Expand Up @@ -1474,6 +1474,9 @@ def deserialize_object(self, attr, **kwargs):
"""
if attr is None:
return None
if isinstance(attr, ET.Element):
# Do no recurse on XML, just return the tree as-is
return attr
if isinstance(attr, basestring):
return self.deserialize_basic(attr, 'str')
obj_type = type(attr)
Expand Down Expand Up @@ -1597,6 +1600,8 @@ def deserialize_bytearray(attr):
:rtype: bytearray
:raises: TypeError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
return bytearray(b64decode(attr))

@staticmethod
Expand All @@ -1607,6 +1612,8 @@ def deserialize_base64(attr):
:rtype: bytearray
:raises: TypeError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
padding = '=' * (3 - (len(attr) + 3) % 4)
attr = attr + padding
encoded = attr.replace('-', '+').replace('_', '/')
Expand All @@ -1620,6 +1627,8 @@ def deserialize_decimal(attr):
:rtype: Decimal
:raises: DeserializationError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
try:
return decimal.Decimal(attr)
except decimal.DecimalException as err:
Expand All @@ -1634,6 +1643,8 @@ def deserialize_long(attr):
:rtype: long or int
:raises: ValueError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
try:
return long(attr)
except NameError:
Expand All @@ -1647,6 +1658,8 @@ def deserialize_duration(attr):
:rtype: TimeDelta
:raises: DeserializationError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
try:
duration = isodate.parse_duration(attr)
except(ValueError, OverflowError, AttributeError) as err:
Expand All @@ -1663,6 +1676,8 @@ def deserialize_date(attr):
:rtype: Date
:raises: DeserializationError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
if re.search(r"[^\W\d_]", attr, re.I + re.U):
raise DeserializationError("Date must have only digits and -. Received: %s" % attr)
# This must NOT use defaultmonth/defaultday. Using None ensure this raises an exception.
Expand All @@ -1676,6 +1691,8 @@ def deserialize_rfc(attr):
:rtype: Datetime
:raises: DeserializationError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
try:
date_obj = datetime.datetime.strptime(
attr, "%a, %d %b %Y %H:%M:%S %Z")
Expand All @@ -1695,6 +1712,8 @@ def deserialize_iso(attr):
:rtype: Datetime
:raises: DeserializationError if string format invalid.
"""
if isinstance(attr, ET.Element):
attr = attr.text
try:
attr = attr.upper()
match = Deserializer.valid_date.match(attr)
Expand Down Expand Up @@ -1731,6 +1750,8 @@ def deserialize_unix(attr):
:rtype: Datetime
:raises: DeserializationError if format invalid
"""
if isinstance(attr, ET.Element):
attr = int(attr.text)
try:
date_obj = datetime.datetime.fromtimestamp(attr, TZ_UTC)
except ValueError as err:
Expand Down
42 changes: 36 additions & 6 deletions tests/test_xml_serialization.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#--------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# The MIT License (MIT)
#
Expand Down Expand Up @@ -65,10 +65,26 @@ class XmlModel(Model):

s = Deserializer({"XmlModel": XmlModel})
result = s(XmlModel, basic_xml, "application/xml")

assert result.age == 37
assert result.country == "france"

def test_object(self):
basic_xml = """<?xml version="1.0"?>
<Data country="france">
<Age>37</Age>
</Data>"""

s = Deserializer()
result = s('object', basic_xml, "application/xml")

# Should be a XML tree
assert result.tag == "Data"
assert result.get("country") == "france"
for child in result:
assert child.tag == "Age"
assert child.text == "37"

def test_basic_empty(self):
"""Test an basic XML with an empty node."""
basic_xml = """<?xml version="1.0"?>
Expand All @@ -86,7 +102,7 @@ class XmlModel(Model):

s = Deserializer({"XmlModel": XmlModel})
result = s(XmlModel, basic_xml, "application/xml")

assert result.age == ""

def test_basic_empty_list(self):
Expand Down Expand Up @@ -351,7 +367,7 @@ class XmlModel(Model):

s = Deserializer({"XmlModel": XmlModel})
result = s(XmlModel, basic_xml, "application/xml")

assert result.age == 37

class TestXmlSerialization:
Expand Down Expand Up @@ -382,6 +398,20 @@ class XmlModel(Model):

assert_xml_equals(rawxml, basic_xml)

def test_object(self):
"""Test serialize object as is.
"""
basic_xml = ET.fromstring("""<?xml version="1.0"?>
<Data country="france">
<Age>37</Age>
</Data>""")

s = Serializer()
rawxml = s.body(basic_xml, 'object')

# It should actually be the same object, should not even try to touch it
assert rawxml is basic_xml

@pytest.mark.skipif(sys.version_info < (3,6),
reason="Unstable before python3.6 for some reasons")
def test_type_basic(self):
Expand Down Expand Up @@ -409,7 +439,7 @@ class XmlModel(Model):
s = Serializer({"XmlModel": XmlModel})
rawxml = s.body(mymodel, 'XmlModel')

assert_xml_equals(rawxml, basic_xml)
assert_xml_equals(rawxml, basic_xml)

def test_direct_array(self):
"""Test an ultra basic XML."""
Expand Down Expand Up @@ -718,4 +748,4 @@ class XmlModel(Model):
rawxml = s.body(mymodel, 'XmlModel')

assert_xml_equals(rawxml, basic_xml)

6 changes: 3 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ deps=
commands=
pipenv install --dev --skip-lock
pytest --cov=msrest tests/
autorest: coverage run -a -m unittest discover -s "autorest.python/test/vanilla/AcceptanceTests" -p "*" -v
coverage report --fail-under=40 --omit=test*,*.tox*.py,*/AcceptanceTests/*
coverage xml --omit=test*,*.tox*.py
autorest: pytest --cov=msrest --cov-append autorest.python/test/vanilla/
coverage report --fail-under=40
coverage xml