raise_exc default in Adapter

It can be annoying to have to say raise_exc=False (or use try/except) on
every call when talking to an API where 4xx response codes are
useful/normal/informative or where the preferred coding style is to use
conditionals rather than try/except.

With this change, the Adapter constructor takes a new kwarg, raise_exc.
It defaults to None, and the existing behavior is unchanged.  If set to
a boolean value, that is used as the default for requests.  Specifying
raise_exc to the primitives (get, head, put, post, patch, delete,
request) at any point along the chain will still take precedence.

Change-Id: Ie291c3cb891467728d8ca33cf62afdab37c82f34
Closes-Bug: #1776501
This commit is contained in:
Eric Fried 2018-06-12 10:48:39 -05:00
parent 36ed4c11cb
commit 51bfa030b1
2 changed files with 36 additions and 1 deletions

View File

@ -88,6 +88,10 @@ class Adapter(object):
should be retried (optional,
defaults to HTTP 503, has no effect
when status_code_retries is 0).
:param bool raise_exc: If True, requests returning failing HTTP responses
will raise an exception; if False, the response is
returned. This can be overridden on a per-request
basis via the kwarg of the same name.
"""
client_name = None
@ -102,7 +106,7 @@ class Adapter(object):
global_request_id=None,
min_version=None, max_version=None,
default_microversion=None, status_code_retries=None,
retriable_status_codes=None):
retriable_status_codes=None, raise_exc=None):
if version and (min_version or max_version):
raise TypeError(
"version is mutually exclusive with min_version and"
@ -131,6 +135,7 @@ class Adapter(object):
self.default_microversion = default_microversion
self.status_code_retries = status_code_retries
self.retriable_status_codes = retriable_status_codes
self.raise_exc = raise_exc
self.global_request_id = global_request_id
@ -202,6 +207,9 @@ class Adapter(object):
kwargs.setdefault('headers', {}).setdefault(
"X-OpenStack-Request-ID", self.global_request_id)
if self.raise_exc is not None:
kwargs.setdefault('raise_exc', self.raise_exc)
return self.session.request(url, method, **kwargs)
def get_token(self, auth=None):

View File

@ -1580,6 +1580,33 @@ class AdapterTest(utils.TestCase):
validate({'default_microversion': '1.2'}, {'microversion': '1.5'},
{'microversion': '1.5'})
def test_raise_exc_override(self):
sess = client_session.Session()
url = 'http://url'
def validate(adap_kwargs, get_kwargs, exp_kwargs):
with mock.patch.object(sess, 'request') as m:
adapter.Adapter(sess, **adap_kwargs).get(url, **get_kwargs)
m.assert_called_once_with(url, 'GET', endpoint_filter={},
**exp_kwargs)
# No raise_exc in Adapter or get()
validate({}, {}, {})
# Set in Adapter, unset in get()
validate({'raise_exc': True}, {}, {'raise_exc': True})
validate({'raise_exc': False}, {}, {'raise_exc': False})
# Unset in Adapter, set in get()
validate({}, {'raise_exc': True}, {'raise_exc': True})
validate({}, {'raise_exc': False}, {'raise_exc': False})
# Setting in get() overrides the one in Adapter
validate({'raise_exc': True}, {'raise_exc': False},
{'raise_exc': False})
validate({'raise_exc': False}, {'raise_exc': True},
{'raise_exc': True})
class TCPKeepAliveAdapterTest(utils.TestCase):