diff --git a/.travis.yml b/.travis.yml index f82d1be9eb..b5e66f6373 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/msrest/serialization.py b/msrest/serialization.py index 3d47c1f4dd..514056e680 100644 --- a/msrest/serialization.py +++ b/msrest/serialization.py @@ -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) @@ -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 @@ -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) @@ -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 @@ -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('_', '/') @@ -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: @@ -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: @@ -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: @@ -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. @@ -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") @@ -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) @@ -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: diff --git a/tests/test_xml_serialization.py b/tests/test_xml_serialization.py index 8288205b11..944c367e09 100644 --- a/tests/test_xml_serialization.py +++ b/tests/test_xml_serialization.py @@ -1,6 +1,6 @@ #-------------------------------------------------------------------------- # -# Copyright (c) Microsoft Corporation. All rights reserved. +# Copyright (c) Microsoft Corporation. All rights reserved. # # The MIT License (MIT) # @@ -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 = """ + + 37 + """ + + 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 = """ @@ -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): @@ -351,7 +367,7 @@ class XmlModel(Model): s = Deserializer({"XmlModel": XmlModel}) result = s(XmlModel, basic_xml, "application/xml") - + assert result.age == 37 class TestXmlSerialization: @@ -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(""" + + 37 + """) + + 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): @@ -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.""" @@ -718,4 +748,4 @@ class XmlModel(Model): rawxml = s.body(mymodel, 'XmlModel') assert_xml_equals(rawxml, basic_xml) - + diff --git a/tox.ini b/tox.ini index be1557afe9..e07b73573f 100644 --- a/tox.ini +++ b/tox.ini @@ -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