We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Support `io` framework for HTTPResponse
This suggestion is motivated by the following issue that pops up in `requests` (see kennethreitz/requests#1364 - they redirected me here):

```
>>> import io, requests
>>> r = requests.get('http://www.google.com',stream=True)
>>> io.BufferedReader(r.raw).read()
AttributeError: 'HTTPResponse' object has no attribute 'readable'
```

The base problem here is that `requests.packages.urllib3.response.HTTPResponse`  object (that's what `r.raw` is) does not respect the `io` API.  The following _does_ work, however:

```
>>> r = requests.get('http://www.google.com',stream=True)
>>> r.raw.readable=lambda:True
>>> r.raw.closed=False
>>> io.BufferedReader(r.raw).read()
```

Suggesting that the main thing that is neeeded is adding a `readable` method and a `closed` attribute to `HTTPResponse`.  (I think `flush` and `close` are probably also necessary, and maybe also `writable` and `seekable`).

Is there a reason this is not possible, or would it be fine to just add the relevant methods to `HTTPResponse`?


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `urllib3/response.py`
Content:
```
1 # urllib3/response.py
2 # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
3 #
4 # This module is part of urllib3 and is released under
5 # the MIT License: http://www.opensource.org/licenses/mit-license.php
6 
7 
8 import logging
9 import zlib
10 
11 from .exceptions import DecodeError
12 from .packages.six import string_types as basestring, binary_type
13 
14 
15 log = logging.getLogger(__name__)
16 
17 
18 class DeflateDecoder(object):
19 
20     def __init__(self):
21         self._first_try = True
22         self._data = binary_type()
23         self._obj = zlib.decompressobj()
24 
25     def __getattr__(self, name):
26         return getattr(self._obj, name)
27 
28     def decompress(self, data):
29         if not self._first_try:
30             return self._obj.decompress(data)
31 
32         self._data += data
33         try:
34             return self._obj.decompress(data)
35         except zlib.error:
36             self._first_try = False
37             self._obj = zlib.decompressobj(-zlib.MAX_WBITS)
38             try:
39                 return self.decompress(self._data)
40             finally:
41                 self._data = None
42 
43 
44 def _get_decoder(mode):
45     if mode == 'gzip':
46         return zlib.decompressobj(16 + zlib.MAX_WBITS)
47 
48     return DeflateDecoder()
49 
50 
51 class HTTPResponse(object):
52     """
53     HTTP Response container.
54 
55     Backwards-compatible to httplib's HTTPResponse but the response ``body`` is
56     loaded and decoded on-demand when the ``data`` property is accessed.
57 
58     Extra parameters for behaviour not present in httplib.HTTPResponse:
59 
60     :param preload_content:
61         If True, the response's body will be preloaded during construction.
62 
63     :param decode_content:
64         If True, attempts to decode specific content-encoding's based on headers
65         (like 'gzip' and 'deflate') will be skipped and raw data will be used
66         instead.
67 
68     :param original_response:
69         When this HTTPResponse wrapper is generated from an httplib.HTTPResponse
70         object, it's convenient to include the original for debug purposes. It's
71         otherwise unused.
72     """
73 
74     CONTENT_DECODERS = ['gzip', 'deflate']
75 
76     def __init__(self, body='', headers=None, status=0, version=0, reason=None,
77                  strict=0, preload_content=True, decode_content=True,
78                  original_response=None, pool=None, connection=None):
79         self.headers = headers or {}
80         self.status = status
81         self.version = version
82         self.reason = reason
83         self.strict = strict
84         self.decode_content = decode_content
85 
86         self._decoder = None
87         self._body = body if body and isinstance(body, basestring) else None
88         self._fp = None
89         self._original_response = original_response
90 
91         self._pool = pool
92         self._connection = connection
93 
94         if hasattr(body, 'read'):
95             self._fp = body
96 
97         if preload_content and not self._body:
98             self._body = self.read(decode_content=decode_content)
99 
100     def get_redirect_location(self):
101         """
102         Should we redirect and where to?
103 
104         :returns: Truthy redirect location string if we got a redirect status
105             code and valid location. ``None`` if redirect status and no
106             location. ``False`` if not a redirect status code.
107         """
108         if self.status in [301, 302, 303, 307]:
109             return self.headers.get('location')
110 
111         return False
112 
113     def release_conn(self):
114         if not self._pool or not self._connection:
115             return
116 
117         self._pool._put_conn(self._connection)
118         self._connection = None
119 
120     @property
121     def data(self):
122         # For backwords-compat with earlier urllib3 0.4 and earlier.
123         if self._body:
124             return self._body
125 
126         if self._fp:
127             return self.read(cache_content=True)
128 
129     def read(self, amt=None, decode_content=None, cache_content=False):
130         """
131         Similar to :meth:`httplib.HTTPResponse.read`, but with two additional
132         parameters: ``decode_content`` and ``cache_content``.
133 
134         :param amt:
135             How much of the content to read. If specified, caching is skipped
136             because it doesn't make sense to cache partial content as the full
137             response.
138 
139         :param decode_content:
140             If True, will attempt to decode the body based on the
141             'content-encoding' header.
142 
143         :param cache_content:
144             If True, will save the returned data such that the same result is
145             returned despite of the state of the underlying file object. This
146             is useful if you want the ``.data`` property to continue working
147             after having ``.read()`` the file object. (Overridden if ``amt`` is
148             set.)
149         """
150         # Note: content-encoding value should be case-insensitive, per RFC 2616
151         # Section 3.5
152         content_encoding = self.headers.get('content-encoding', '').lower()
153         if self._decoder is None:
154             if content_encoding in self.CONTENT_DECODERS:
155                 self._decoder = _get_decoder(content_encoding)
156         if decode_content is None:
157             decode_content = self.decode_content
158 
159         if self._fp is None:
160             return
161 
162         flush_decoder = False
163 
164         try:
165             if amt is None:
166                 # cStringIO doesn't like amt=None
167                 data = self._fp.read()
168                 flush_decoder = True
169             else:
170                 cache_content = False
171                 data = self._fp.read(amt)
172                 if amt != 0 and not data:  # Platform-specific: Buggy versions of Python.
173                     # Close the connection when no data is returned
174                     #
175                     # This is redundant to what httplib/http.client _should_
176                     # already do.  However, versions of python released before
177                     # December 15, 2012 (http://bugs.python.org/issue16298) do not
178                     # properly close the connection in all cases. There is no harm
179                     # in redundantly calling close.
180                     self._fp.close()
181                     flush_decoder = True
182 
183             try:
184                 if decode_content and self._decoder:
185                     data = self._decoder.decompress(data)
186             except (IOError, zlib.error):
187                 raise DecodeError("Received response with content-encoding: %s, but "
188                                   "failed to decode it." % content_encoding)
189 
190             if flush_decoder and self._decoder:
191                 buf = self._decoder.decompress(binary_type())
192                 data += buf + self._decoder.flush()
193 
194             if cache_content:
195                 self._body = data
196 
197             return data
198 
199         finally:
200             if self._original_response and self._original_response.isclosed():
201                 self.release_conn()
202 
203     @classmethod
204     def from_httplib(ResponseCls, r, **response_kw):
205         """
206         Given an :class:`httplib.HTTPResponse` instance ``r``, return a
207         corresponding :class:`urllib3.response.HTTPResponse` object.
208 
209         Remaining parameters are passed to the HTTPResponse constructor, along
210         with ``original_response=r``.
211         """
212 
213         # Normalize headers between different versions of Python
214         headers = {}
215         for k, v in r.getheaders():
216             # Python 3: Header keys are returned capitalised
217             k = k.lower()
218 
219             has_value = headers.get(k)
220             if has_value: # Python 3: Repeating header keys are unmerged.
221                 v = ', '.join([has_value, v])
222 
223             headers[k] = v
224 
225         # HTTPResponse objects in Python 3 don't have a .strict attribute
226         strict = getattr(r, 'strict', 0)
227         return ResponseCls(body=r,
228                            headers=headers,
229                            status=r.status,
230                            version=r.version,
231                            reason=r.reason,
232                            strict=strict,
233                            original_response=r,
234                            **response_kw)
235 
236     # Backwards-compatibility methods for httplib.HTTPResponse
237     def getheaders(self):
238         return self.headers
239 
240     def getheader(self, name, default=None):
241         return self.headers.get(name, default)
242
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/urllib3/response.py b/urllib3/response.py
--- a/urllib3/response.py
+++ b/urllib3/response.py
@@ -7,6 +7,7 @@
 
 import logging
 import zlib
+import io
 
 from .exceptions import DecodeError
 from .packages.six import string_types as basestring, binary_type
@@ -48,7 +49,7 @@
     return DeflateDecoder()
 
 
-class HTTPResponse(object):
+class HTTPResponse(io.IOBase):
     """
     HTTP Response container.
 
@@ -239,3 +240,35 @@
 
     def getheader(self, name, default=None):
         return self.headers.get(name, default)
+
+    # Overrides from io.IOBase
+    def close(self):
+        if not self.closed:
+            self._fp.close()
+
+    @property
+    def closed(self):
+        if self._fp is None:
+            return True
+        elif hasattr(self._fp, 'closed'):
+            return self._fp.closed
+        elif hasattr(self._fp, 'isclosed'):  # Python 2
+            return self._fp.isclosed()
+        else:
+            return True
+
+    def fileno(self):
+        if self._fp is None:
+            raise IOError("HTTPResponse has no file to get a fileno from")
+        elif hasattr(self._fp, "fileno"):
+            return self._fp.fileno()
+        else:
+            raise IOError("The file-like object  this HTTPResponse is wrapped "
+                          "around has no file descriptor")
+
+    def flush(self):
+        if self._fp is not None and hasattr(self._fp, 'flush'):
+            return self._fp.flush()
+
+    def readable(self):
+        return True

{"golden_diff": "diff --git a/urllib3/response.py b/urllib3/response.py\n--- a/urllib3/response.py\n+++ b/urllib3/response.py\n@@ -7,6 +7,7 @@\n \n import logging\n import zlib\n+import io\n \n from .exceptions import DecodeError\n from .packages.six import string_types as basestring, binary_type\n@@ -48,7 +49,7 @@\n     return DeflateDecoder()\n \n \n-class HTTPResponse(object):\n+class HTTPResponse(io.IOBase):\n     \"\"\"\n     HTTP Response container.\n \n@@ -239,3 +240,35 @@\n \n     def getheader(self, name, default=None):\n         return self.headers.get(name, default)\n+\n+    # Overrides from io.IOBase\n+    def close(self):\n+        if not self.closed:\n+            self._fp.close()\n+\n+    @property\n+    def closed(self):\n+        if self._fp is None:\n+            return True\n+        elif hasattr(self._fp, 'closed'):\n+            return self._fp.closed\n+        elif hasattr(self._fp, 'isclosed'):  # Python 2\n+            return self._fp.isclosed()\n+        else:\n+            return True\n+\n+    def fileno(self):\n+        if self._fp is None:\n+            raise IOError(\"HTTPResponse has no file to get a fileno from\")\n+        elif hasattr(self._fp, \"fileno\"):\n+            return self._fp.fileno()\n+        else:\n+            raise IOError(\"The file-like object  this HTTPResponse is wrapped \"\n+                          \"around has no file descriptor\")\n+\n+    def flush(self):\n+        if self._fp is not None and hasattr(self._fp, 'flush'):\n+            return self._fp.flush()\n+\n+    def readable(self):\n+        return True\n", "issue": "Support `io` framework for HTTPResponse\nThis suggestion is motivated by the following issue that pops up in `requests` (see kennethreitz/requests#1364 - they redirected me here):\n\n```\n>>> import io, requests\n>>> r = requests.get('http://www.google.com',stream=True)\n>>> io.BufferedReader(r.raw).read()\nAttributeError: 'HTTPResponse' object has no attribute 'readable'\n```\n\nThe base problem here is that `requests.packages.urllib3.response.HTTPResponse`  object (that's what `r.raw` is) does not respect the `io` API.  The following _does_ work, however:\n\n```\n>>> r = requests.get('http://www.google.com',stream=True)\n>>> r.raw.readable=lambda:True\n>>> r.raw.closed=False\n>>> io.BufferedReader(r.raw).read()\n```\n\nSuggesting that the main thing that is neeeded is adding a `readable` method and a `closed` attribute to `HTTPResponse`.  (I think `flush` and `close` are probably also necessary, and maybe also `writable` and `seekable`).\n\nIs there a reason this is not possible, or would it be fine to just add the relevant methods to `HTTPResponse`?\n\n", "before_files": [{"content": "# urllib3/response.py\n# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)\n#\n# This module is part of urllib3 and is released under\n# the MIT License: http://www.opensource.org/licenses/mit-license.php\n\n\nimport logging\nimport zlib\n\nfrom .exceptions import DecodeError\nfrom .packages.six import string_types as basestring, binary_type\n\n\nlog = logging.getLogger(__name__)\n\n\nclass DeflateDecoder(object):\n\n    def __init__(self):\n        self._first_try = True\n        self._data = binary_type()\n        self._obj = zlib.decompressobj()\n\n    def __getattr__(self, name):\n        return getattr(self._obj, name)\n\n    def decompress(self, data):\n        if not self._first_try:\n            return self._obj.decompress(data)\n\n        self._data += data\n        try:\n            return self._obj.decompress(data)\n        except zlib.error:\n            self._first_try = False\n            self._obj = zlib.decompressobj(-zlib.MAX_WBITS)\n            try:\n                return self.decompress(self._data)\n            finally:\n                self._data = None\n\n\ndef _get_decoder(mode):\n    if mode == 'gzip':\n        return zlib.decompressobj(16 + zlib.MAX_WBITS)\n\n    return DeflateDecoder()\n\n\nclass HTTPResponse(object):\n    \"\"\"\n    HTTP Response container.\n\n    Backwards-compatible to httplib's HTTPResponse but the response ``body`` is\n    loaded and decoded on-demand when the ``data`` property is accessed.\n\n    Extra parameters for behaviour not present in httplib.HTTPResponse:\n\n    :param preload_content:\n        If True, the response's body will be preloaded during construction.\n\n    :param decode_content:\n        If True, attempts to decode specific content-encoding's based on headers\n        (like 'gzip' and 'deflate') will be skipped and raw data will be used\n        instead.\n\n    :param original_response:\n        When this HTTPResponse wrapper is generated from an httplib.HTTPResponse\n        object, it's convenient to include the original for debug purposes. It's\n        otherwise unused.\n    \"\"\"\n\n    CONTENT_DECODERS = ['gzip', 'deflate']\n\n    def __init__(self, body='', headers=None, status=0, version=0, reason=None,\n                 strict=0, preload_content=True, decode_content=True,\n                 original_response=None, pool=None, connection=None):\n        self.headers = headers or {}\n        self.status = status\n        self.version = version\n        self.reason = reason\n        self.strict = strict\n        self.decode_content = decode_content\n\n        self._decoder = None\n        self._body = body if body and isinstance(body, basestring) else None\n        self._fp = None\n        self._original_response = original_response\n\n        self._pool = pool\n        self._connection = connection\n\n        if hasattr(body, 'read'):\n            self._fp = body\n\n        if preload_content and not self._body:\n            self._body = self.read(decode_content=decode_content)\n\n    def get_redirect_location(self):\n        \"\"\"\n        Should we redirect and where to?\n\n        :returns: Truthy redirect location string if we got a redirect status\n            code and valid location. ``None`` if redirect status and no\n            location. ``False`` if not a redirect status code.\n        \"\"\"\n        if self.status in [301, 302, 303, 307]:\n            return self.headers.get('location')\n\n        return False\n\n    def release_conn(self):\n        if not self._pool or not self._connection:\n            return\n\n        self._pool._put_conn(self._connection)\n        self._connection = None\n\n    @property\n    def data(self):\n        # For backwords-compat with earlier urllib3 0.4 and earlier.\n        if self._body:\n            return self._body\n\n        if self._fp:\n            return self.read(cache_content=True)\n\n    def read(self, amt=None, decode_content=None, cache_content=False):\n        \"\"\"\n        Similar to :meth:`httplib.HTTPResponse.read`, but with two additional\n        parameters: ``decode_content`` and ``cache_content``.\n\n        :param amt:\n            How much of the content to read. If specified, caching is skipped\n            because it doesn't make sense to cache partial content as the full\n            response.\n\n        :param decode_content:\n            If True, will attempt to decode the body based on the\n            'content-encoding' header.\n\n        :param cache_content:\n            If True, will save the returned data such that the same result is\n            returned despite of the state of the underlying file object. This\n            is useful if you want the ``.data`` property to continue working\n            after having ``.read()`` the file object. (Overridden if ``amt`` is\n            set.)\n        \"\"\"\n        # Note: content-encoding value should be case-insensitive, per RFC 2616\n        # Section 3.5\n        content_encoding = self.headers.get('content-encoding', '').lower()\n        if self._decoder is None:\n            if content_encoding in self.CONTENT_DECODERS:\n                self._decoder = _get_decoder(content_encoding)\n        if decode_content is None:\n            decode_content = self.decode_content\n\n        if self._fp is None:\n            return\n\n        flush_decoder = False\n\n        try:\n            if amt is None:\n                # cStringIO doesn't like amt=None\n                data = self._fp.read()\n                flush_decoder = True\n            else:\n                cache_content = False\n                data = self._fp.read(amt)\n                if amt != 0 and not data:  # Platform-specific: Buggy versions of Python.\n                    # Close the connection when no data is returned\n                    #\n                    # This is redundant to what httplib/http.client _should_\n                    # already do.  However, versions of python released before\n                    # December 15, 2012 (http://bugs.python.org/issue16298) do not\n                    # properly close the connection in all cases. There is no harm\n                    # in redundantly calling close.\n                    self._fp.close()\n                    flush_decoder = True\n\n            try:\n                if decode_content and self._decoder:\n                    data = self._decoder.decompress(data)\n            except (IOError, zlib.error):\n                raise DecodeError(\"Received response with content-encoding: %s, but \"\n                                  \"failed to decode it.\" % content_encoding)\n\n            if flush_decoder and self._decoder:\n                buf = self._decoder.decompress(binary_type())\n                data += buf + self._decoder.flush()\n\n            if cache_content:\n                self._body = data\n\n            return data\n\n        finally:\n            if self._original_response and self._original_response.isclosed():\n                self.release_conn()\n\n    @classmethod\n    def from_httplib(ResponseCls, r, **response_kw):\n        \"\"\"\n        Given an :class:`httplib.HTTPResponse` instance ``r``, return a\n        corresponding :class:`urllib3.response.HTTPResponse` object.\n\n        Remaining parameters are passed to the HTTPResponse constructor, along\n        with ``original_response=r``.\n        \"\"\"\n\n        # Normalize headers between different versions of Python\n        headers = {}\n        for k, v in r.getheaders():\n            # Python 3: Header keys are returned capitalised\n            k = k.lower()\n\n            has_value = headers.get(k)\n            if has_value: # Python 3: Repeating header keys are unmerged.\n                v = ', '.join([has_value, v])\n\n            headers[k] = v\n\n        # HTTPResponse objects in Python 3 don't have a .strict attribute\n        strict = getattr(r, 'strict', 0)\n        return ResponseCls(body=r,\n                           headers=headers,\n                           status=r.status,\n                           version=r.version,\n                           reason=r.reason,\n                           strict=strict,\n                           original_response=r,\n                           **response_kw)\n\n    # Backwards-compatibility methods for httplib.HTTPResponse\n    def getheaders(self):\n        return self.headers\n\n    def getheader(self, name, default=None):\n        return self.headers.get(name, default)\n", "path": "urllib3/response.py"}], "after_files": [{"content": "# urllib3/response.py\n# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)\n#\n# This module is part of urllib3 and is released under\n# the MIT License: http://www.opensource.org/licenses/mit-license.php\n\n\nimport logging\nimport zlib\nimport io\n\nfrom .exceptions import DecodeError\nfrom .packages.six import string_types as basestring, binary_type\n\n\nlog = logging.getLogger(__name__)\n\n\nclass DeflateDecoder(object):\n\n    def __init__(self):\n        self._first_try = True\n        self._data = binary_type()\n        self._obj = zlib.decompressobj()\n\n    def __getattr__(self, name):\n        return getattr(self._obj, name)\n\n    def decompress(self, data):\n        if not self._first_try:\n            return self._obj.decompress(data)\n\n        self._data += data\n        try:\n            return self._obj.decompress(data)\n        except zlib.error:\n            self._first_try = False\n            self._obj = zlib.decompressobj(-zlib.MAX_WBITS)\n            try:\n                return self.decompress(self._data)\n            finally:\n                self._data = None\n\n\ndef _get_decoder(mode):\n    if mode == 'gzip':\n        return zlib.decompressobj(16 + zlib.MAX_WBITS)\n\n    return DeflateDecoder()\n\n\nclass HTTPResponse(io.IOBase):\n    \"\"\"\n    HTTP Response container.\n\n    Backwards-compatible to httplib's HTTPResponse but the response ``body`` is\n    loaded and decoded on-demand when the ``data`` property is accessed.\n\n    Extra parameters for behaviour not present in httplib.HTTPResponse:\n\n    :param preload_content:\n        If True, the response's body will be preloaded during construction.\n\n    :param decode_content:\n        If True, attempts to decode specific content-encoding's based on headers\n        (like 'gzip' and 'deflate') will be skipped and raw data will be used\n        instead.\n\n    :param original_response:\n        When this HTTPResponse wrapper is generated from an httplib.HTTPResponse\n        object, it's convenient to include the original for debug purposes. It's\n        otherwise unused.\n    \"\"\"\n\n    CONTENT_DECODERS = ['gzip', 'deflate']\n\n    def __init__(self, body='', headers=None, status=0, version=0, reason=None,\n                 strict=0, preload_content=True, decode_content=True,\n                 original_response=None, pool=None, connection=None):\n        self.headers = headers or {}\n        self.status = status\n        self.version = version\n        self.reason = reason\n        self.strict = strict\n        self.decode_content = decode_content\n\n        self._decoder = None\n        self._body = body if body and isinstance(body, basestring) else None\n        self._fp = None\n        self._original_response = original_response\n\n        self._pool = pool\n        self._connection = connection\n\n        if hasattr(body, 'read'):\n            self._fp = body\n\n        if preload_content and not self._body:\n            self._body = self.read(decode_content=decode_content)\n\n    def get_redirect_location(self):\n        \"\"\"\n        Should we redirect and where to?\n\n        :returns: Truthy redirect location string if we got a redirect status\n            code and valid location. ``None`` if redirect status and no\n            location. ``False`` if not a redirect status code.\n        \"\"\"\n        if self.status in [301, 302, 303, 307]:\n            return self.headers.get('location')\n\n        return False\n\n    def release_conn(self):\n        if not self._pool or not self._connection:\n            return\n\n        self._pool._put_conn(self._connection)\n        self._connection = None\n\n    @property\n    def data(self):\n        # For backwords-compat with earlier urllib3 0.4 and earlier.\n        if self._body:\n            return self._body\n\n        if self._fp:\n            return self.read(cache_content=True)\n\n    def read(self, amt=None, decode_content=None, cache_content=False):\n        \"\"\"\n        Similar to :meth:`httplib.HTTPResponse.read`, but with two additional\n        parameters: ``decode_content`` and ``cache_content``.\n\n        :param amt:\n            How much of the content to read. If specified, caching is skipped\n            because it doesn't make sense to cache partial content as the full\n            response.\n\n        :param decode_content:\n            If True, will attempt to decode the body based on the\n            'content-encoding' header.\n\n        :param cache_content:\n            If True, will save the returned data such that the same result is\n            returned despite of the state of the underlying file object. This\n            is useful if you want the ``.data`` property to continue working\n            after having ``.read()`` the file object. (Overridden if ``amt`` is\n            set.)\n        \"\"\"\n        # Note: content-encoding value should be case-insensitive, per RFC 2616\n        # Section 3.5\n        content_encoding = self.headers.get('content-encoding', '').lower()\n        if self._decoder is None:\n            if content_encoding in self.CONTENT_DECODERS:\n                self._decoder = _get_decoder(content_encoding)\n        if decode_content is None:\n            decode_content = self.decode_content\n\n        if self._fp is None:\n            return\n\n        flush_decoder = False\n\n        try:\n            if amt is None:\n                # cStringIO doesn't like amt=None\n                data = self._fp.read()\n                flush_decoder = True\n            else:\n                cache_content = False\n                data = self._fp.read(amt)\n                if amt != 0 and not data:  # Platform-specific: Buggy versions of Python.\n                    # Close the connection when no data is returned\n                    #\n                    # This is redundant to what httplib/http.client _should_\n                    # already do.  However, versions of python released before\n                    # December 15, 2012 (http://bugs.python.org/issue16298) do not\n                    # properly close the connection in all cases. There is no harm\n                    # in redundantly calling close.\n                    self._fp.close()\n                    flush_decoder = True\n\n            try:\n                if decode_content and self._decoder:\n                    data = self._decoder.decompress(data)\n            except (IOError, zlib.error):\n                raise DecodeError(\"Received response with content-encoding: %s, but \"\n                                  \"failed to decode it.\" % content_encoding)\n\n            if flush_decoder and self._decoder:\n                buf = self._decoder.decompress(binary_type())\n                data += buf + self._decoder.flush()\n\n            if cache_content:\n                self._body = data\n\n            return data\n\n        finally:\n            if self._original_response and self._original_response.isclosed():\n                self.release_conn()\n\n    @classmethod\n    def from_httplib(ResponseCls, r, **response_kw):\n        \"\"\"\n        Given an :class:`httplib.HTTPResponse` instance ``r``, return a\n        corresponding :class:`urllib3.response.HTTPResponse` object.\n\n        Remaining parameters are passed to the HTTPResponse constructor, along\n        with ``original_response=r``.\n        \"\"\"\n\n        # Normalize headers between different versions of Python\n        headers = {}\n        for k, v in r.getheaders():\n            # Python 3: Header keys are returned capitalised\n            k = k.lower()\n\n            has_value = headers.get(k)\n            if has_value: # Python 3: Repeating header keys are unmerged.\n                v = ', '.join([has_value, v])\n\n            headers[k] = v\n\n        # HTTPResponse objects in Python 3 don't have a .strict attribute\n        strict = getattr(r, 'strict', 0)\n        return ResponseCls(body=r,\n                           headers=headers,\n                           status=r.status,\n                           version=r.version,\n                           reason=r.reason,\n                           strict=strict,\n                           original_response=r,\n                           **response_kw)\n\n    # Backwards-compatibility methods for httplib.HTTPResponse\n    def getheaders(self):\n        return self.headers\n\n    def getheader(self, name, default=None):\n        return self.headers.get(name, default)\n\n    # Overrides from io.IOBase\n    def close(self):\n        if not self.closed:\n            self._fp.close()\n\n    @property\n    def closed(self):\n        if self._fp is None:\n            return True\n        elif hasattr(self._fp, 'closed'):\n            return self._fp.closed\n        elif hasattr(self._fp, 'isclosed'):  # Python 2\n            return self._fp.isclosed()\n        else:\n            return True\n\n    def fileno(self):\n        if self._fp is None:\n            raise IOError(\"HTTPResponse has no file to get a fileno from\")\n        elif hasattr(self._fp, \"fileno\"):\n            return self._fp.fileno()\n        else:\n            raise IOError(\"The file-like object  this HTTPResponse is wrapped \"\n                          \"around has no file descriptor\")\n\n    def flush(self):\n        if self._fp is not None and hasattr(self._fp, 'flush'):\n            return self._fp.flush()\n\n    def readable(self):\n        return True\n", "path": "urllib3/response.py"}]}