add httplib.HTTPResponse proxy to the response property of the RawResponse cls instead of exposing the requests' response class directly
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/2fcd275b Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/2fcd275b Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/2fcd275b Branch: refs/heads/trunk Commit: 2fcd275bac3732c3a7d0e25286403dcc9a784ec6 Parents: d979b92 Author: Anthony Shaw <anthonys...@apache.org> Authored: Tue Jan 10 20:54:10 2017 +1100 Committer: Anthony Shaw <anthonys...@apache.org> Committed: Tue Jan 10 20:54:10 2017 +1100 ---------------------------------------------------------------------- libcloud/common/base.py | 6 ++-- libcloud/httplib_ssl.py | 46 ++++++++++++++++++++++++++++- libcloud/test/test_response_classes.py | 27 ++++++++++++----- libcloud/utils/loggingconnection.py | 5 ++-- 4 files changed, 71 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/2fcd275b/libcloud/common/base.py ---------------------------------------------------------------------- diff --git a/libcloud/common/base.py b/libcloud/common/base.py index d1b26d7..d33872e 100644 --- a/libcloud/common/base.py +++ b/libcloud/common/base.py @@ -46,7 +46,7 @@ from libcloud.utils.compression import decompress_data from libcloud.common.exceptions import exception_from_message from libcloud.common.types import LibcloudError, MalformedResponseError -from libcloud.httplib_ssl import LibcloudConnection +from libcloud.httplib_ssl import LibcloudConnection, HttpLibResponseProxy __all__ = [ 'RETRY_FAILED_HTTP_REQUESTS', @@ -271,7 +271,6 @@ class XmlResponse(Response): class RawResponse(Response): - def __init__(self, connection, response=None): """ :param connection: Parent connection object. @@ -308,7 +307,8 @@ class RawResponse(Response): def response(self): if not self._response: response = self.connection.connection.getresponse() - self._response, self.body = response, response.text + self._response = HttpLibResponseProxy(response) + self.body = response.text if not self.success(): self.parse_error() return self._response http://git-wip-us.apache.org/repos/asf/libcloud/blob/2fcd275b/libcloud/httplib_ssl.py ---------------------------------------------------------------------- diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py index c88d3ce..8bd9d89 100644 --- a/libcloud/httplib_ssl.py +++ b/libcloud/httplib_ssl.py @@ -24,7 +24,7 @@ import warnings import requests import libcloud.security -from libcloud.utils.py3 import urlparse +from libcloud.utils.py3 import urlparse, PY3 __all__ = [ @@ -238,6 +238,50 @@ class LibcloudConnection(LibcloudBaseConnection): self.response.close() +class HttpLibResponseProxy(object): + """ + Provides a proxy pattern around the :class:`requests.Reponse` + object to a :class:`httplib.HTTPResponse` object + """ + def __init__(self, response): + self._response = response + + def read(self, amt=None): + return self._response.text + + def getheader(self, name, default=None): + """ + Get the contents of the header name, or default + if there is no matching header. + """ + if name in self._response.headers.keys(): + return self._response.headers[name] + else: + return default + + def getheaders(self): + """ + Return a list of (header, value) tuples. + """ + if PY3: + return list(self._response.headers.items()) + else: + return self._response.headers.items() + + @property + def status(self): + return self._response.status_code + + @property + def reason(self): + return self._response.reason + + @property + def version(self): + # requests doesn't expose this + return '11' + + def get_socket_error_exception(ssl_version, exc): """ Function which intercepts socket.error exceptions and re-throws an http://git-wip-us.apache.org/repos/asf/libcloud/blob/2fcd275b/libcloud/test/test_response_classes.py ---------------------------------------------------------------------- diff --git a/libcloud/test/test_response_classes.py b/libcloud/test/test_response_classes.py index d1e1179..3572bcb 100644 --- a/libcloud/test/test_response_classes.py +++ b/libcloud/test/test_response_classes.py @@ -19,7 +19,7 @@ import unittest import requests import requests_mock -from libcloud.common.base import XmlResponse, JsonResponse, RawResponse, Connection +from libcloud.common.base import XmlResponse, JsonResponse, Connection from libcloud.common.types import MalformedResponseError from libcloud.httplib_ssl import LibcloudConnection @@ -95,17 +95,30 @@ class ResponseClassesTests(unittest.TestCase): self.assertEqual(parsed, '') def test_RawResponse_class_read_method(self): + """ + Test that the RawResponse class includes a response + property which exhibits the same properties and methods + as httplib.HTTPResponse for backward compat <1.5.0 + """ TEST_DATA = '1234abcd' - + conn = Connection(host='mock.com', port=80, secure=False) conn.connect() - adapter = requests_mock.Adapter() - conn.connection.session.mount('mock', adapter) - adapter.register_uri('GET', 'http://test.com/raw_data', text=TEST_DATA) - - response = conn.request('/raw_data', raw=True) + + with requests_mock.Mocker() as m: + m.register_uri('GET', 'http://mock.com/raw_data', text=TEST_DATA, + headers={'test': 'value'}) + response = conn.request('/raw_data', raw=True) data = response.response.read() self.assertEqual(data, TEST_DATA) + header_value = response.response.getheader('test') + self.assertEqual(header_value, 'value') + + headers = response.response.getheaders() + self.assertEqual(headers, [('test', 'value')]) + + self.assertEqual(response.response.status, 200) + if __name__ == '__main__': sys.exit(unittest.main()) http://git-wip-us.apache.org/repos/asf/libcloud/blob/2fcd275b/libcloud/utils/loggingconnection.py ---------------------------------------------------------------------- diff --git a/libcloud/utils/loggingconnection.py b/libcloud/utils/loggingconnection.py index 4e4174a..3ee09ad 100644 --- a/libcloud/utils/loggingconnection.py +++ b/libcloud/utils/loggingconnection.py @@ -27,7 +27,8 @@ import sys import os from libcloud.common.base import (LibcloudConnection, - HTTPResponse) + HTTPResponse, + HttpLibResponseProxy) from libcloud.utils.py3 import httplib from libcloud.utils.py3 import PY3 from libcloud.utils.py3 import StringIO @@ -172,7 +173,7 @@ class LoggingConnection(LibcloudConnection): return " ".join(cmd) def getresponse(self): - r = LibcloudConnection.getresponse(self) + r = HttpLibResponseProxy(LibcloudConnection.getresponse(self)) if self.log is not None: r, rv = self._log_response(r) self.log.write(rv + "\n")