From d75a8e83bb4a17286b34daadb1322d881c07f274 Mon Sep 17 00:00:00 2001 From: ZhiQiang Fan Date: Tue, 31 May 2016 03:08:17 +0800 Subject: [PATCH] add default value for http_status in ClientException ClientException is not a virtual base class, hence it can be initialized and string formatted, but the required property 'http_status' is not set by defaut, which will cause AttributeError if we cannot convert a dedicate exception from response. This patch fixes it by adding default value 'N/A' for http_status, and set it with response.status_code when it is a ClientException instance. Change-Id: Ib9920a1f21885917fe7bc4562f1b54602112a473 Closes-Bug: #1586994 --- aodhclient/exceptions.py | 11 +++++-- aodhclient/tests/unit/test_exceptions.py | 37 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 aodhclient/tests/unit/test_exceptions.py diff --git a/aodhclient/exceptions.py b/aodhclient/exceptions.py index 4e238e2..5a12640 100644 --- a/aodhclient/exceptions.py +++ b/aodhclient/exceptions.py @@ -15,6 +15,7 @@ class ClientException(Exception): """The base exception class for all exceptions this library raises.""" message = 'Unknown Error' + http_status = 'N/A' def __init__(self, message=None, request_id=None, url=None, method=None): @@ -181,6 +182,10 @@ def from_response(response, url, method=None): elif content_type.startswith("text/"): kwargs['message'] = response.text - if not kwargs['message']: - del kwargs['message'] - return cls(**kwargs) + if not kwargs.get('message'): + kwargs.pop('message', None) + + exception = cls(**kwargs) + if isinstance(exception, ClientException) and response.status_code: + exception.http_status = response.status_code + return exception diff --git a/aodhclient/tests/unit/test_exceptions.py b/aodhclient/tests/unit/test_exceptions.py new file mode 100644 index 0000000..2fe53fb --- /dev/null +++ b/aodhclient/tests/unit/test_exceptions.py @@ -0,0 +1,37 @@ +# Copyright 2016 Hewlett Packard Enterprise Development Company, L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, 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 mock +from oslotest import base + +from aodhclient import exceptions + + +class AodhclientExceptionsTest(base.BaseTestCase): + def test_string_format_base_exception(self): + # ensure http_status has initial value N/A + self.assertEqual('Unknown Error (HTTP N/A)', + '%s' % exceptions.ClientException()) + + def test_no_match_exception_from_response(self): + resp = mock.MagicMock(status_code=520) + resp.headers = { + 'Content-Type': 'text/plain', + 'x-openstack-request-id': 'fake-request-id' + } + resp.text = 'Of course I still love you' + e = exceptions.from_response(resp, 'http://no.where:2333/v2/alarms') + self.assertIsInstance(e, exceptions.ClientException) + self.assertEqual('Of course I still love you (HTTP 520) ' + '(Request-ID: fake-request-id)', '%s' % e)