diff --git a/ChangeLog.md b/ChangeLog.md index 6f84071f..b2220aa4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,6 +4,9 @@ ## Version XX.XX.XX: +### All: +- Fixed a bug where deserialization of service stats throws a TypeError when the service is unavailable. + ### Blob: - create_from_* and and append_blob_from_* methods will return response_properties which contains the etag and last modified time. diff --git a/azure/storage/_deserialization.py b/azure/storage/_deserialization.py index 36e24e21..95659ad0 100644 --- a/azure/storage/_deserialization.py +++ b/azure/storage/_deserialization.py @@ -184,7 +184,8 @@ def _convert_xml_to_service_stats(response): geo_replication = GeoReplication() geo_replication.status = geo_replication_element.find('Status').text - geo_replication.last_sync_time = parser.parse(geo_replication_element.find('LastSyncTime').text) + last_sync_time = geo_replication_element.find('LastSyncTime').text + geo_replication.last_sync_time = parser.parse(last_sync_time) if last_sync_time else None service_stats = ServiceStats() service_stats.geo_replication = geo_replication diff --git a/tests/test_service_stats.py b/tests/test_service_stats.py index 4ceea382..a879fb15 100644 --- a/tests/test_service_stats.py +++ b/tests/test_service_stats.py @@ -1,4 +1,4 @@ -#------------------------------------------------------------------------- +# ------------------------------------------------------------------------- # Copyright (c) Microsoft. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -#-------------------------------------------------------------------------- +# -------------------------------------------------------------------------- import unittest from azure.storage.blob import BlockBlobService @@ -21,12 +21,18 @@ StorageTestCase, record, ) +from azure.storage.retry import ( + LinearRetry +) -#------------------------------------------------------------------------------ +SERVICE_UNAVAILABLE_RESP_BODY = 'unavailable ' -class ServiceStatsTest(StorageTestCase): - #--Helpers----------------------------------------------------------------- +# --Test Class ----------------------------------------------------------------- +class ServiceStatsTest(StorageTestCase): + # --Helpers----------------------------------------------------------------- def _assert_stats_default(self, stats): self.assertIsNotNone(stats) self.assertIsNotNone(stats.geo_replication) @@ -34,7 +40,18 @@ def _assert_stats_default(self, stats): self.assertEqual(stats.geo_replication.status, 'live') self.assertIsNotNone(stats.geo_replication.last_sync_time) - #--Test cases per service --------------------------------------- + def _assert_stats_unavailable(self, stats): + self.assertIsNotNone(stats) + self.assertIsNotNone(stats.geo_replication) + + self.assertEqual(stats.geo_replication.status, 'unavailable') + self.assertIsNone(stats.geo_replication.last_sync_time) + + @staticmethod + def override_response_body_with_unavailable_status(response): + response.body = SERVICE_UNAVAILABLE_RESP_BODY + + # --Test cases per service --------------------------------------- @record def test_blob_service_stats(self): @@ -47,6 +64,19 @@ def test_blob_service_stats(self): # Assert self._assert_stats_default(stats) + @record + def test_blob_service_stats_when_unavailable(self): + # Arrange + bs = self._create_storage_service(BlockBlobService, self.settings) + bs.response_callback = self.override_response_body_with_unavailable_status + bs.retry = LinearRetry(backoff=1).retry + + # Act + stats = bs.get_blob_service_stats() + + # Assert + self._assert_stats_unavailable(stats) + @record def test_queue_service_stats(self): # Arrange @@ -58,6 +88,19 @@ def test_queue_service_stats(self): # Assert self._assert_stats_default(stats) + @record + def test_queue_service_stats_when_unavailable(self): + # Arrange + qs = self._create_storage_service(QueueService, self.settings) + qs.response_callback = self.override_response_body_with_unavailable_status + qs.retry = LinearRetry(backoff=1).retry + + # Act + stats = qs.get_queue_service_stats() + + # Assert + self._assert_stats_unavailable(stats) + @record def test_table_service_stats(self): # Arrange @@ -69,6 +112,19 @@ def test_table_service_stats(self): # Assert self._assert_stats_default(stats) -#------------------------------------------------------------------------------ + @record + def test_table_service_stats_when_unavailable(self): + # Arrange + ts = self._create_storage_service(TableService, self.settings) + ts.response_callback = self.override_response_body_with_unavailable_status + ts.retry = LinearRetry(backoff=1).retry + + # Act + stats = ts.get_table_service_stats() + + # Assert + self._assert_stats_unavailable(stats) + +# ------------------------------------------------------------------------------ if __name__ == '__main__': unittest.main()