diff --git a/AUTHORS.rst b/AUTHORS.rst index 7e0bddf0e9..cda8e2234e 100755 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -183,3 +183,4 @@ Patches and Suggestions - Shmuel Amar (`@shmuelamar `_) - Gary Wu (`@garywu `_) - Ryan Pineo (`@ryanpineo `_) +- Ed Morley (`@edmorley `_) diff --git a/HISTORY.rst b/HISTORY.rst index edd07ae1fa..865169a506 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -6,6 +6,11 @@ Release History dev +++ +**Improvements** + +- ``Response`` is now a context manager, so can be used directly in a `with` statement + without first having to be wrapped by ``contextlib.closing()``. + **Bugfixes** - Resolve installation failure if multiprocessing is not available diff --git a/docs/user/advanced.rst b/docs/user/advanced.rst index 2aac434ca4..a1b6870752 100644 --- a/docs/user/advanced.rst +++ b/docs/user/advanced.rst @@ -301,15 +301,11 @@ release the connection back to the pool unless you consume all the data or call :meth:`Response.close `. This can lead to inefficiency with connections. If you find yourself partially reading request bodies (or not reading them at all) while using ``stream=True``, you should -consider using ``contextlib.closing`` (`documented here`_), like this:: +make the request within a ``with`` statement to ensure it's always closed:: - from contextlib import closing - - with closing(requests.get('http://httpbin.org/get', stream=True)) as r: + with requests.get('http://httpbin.org/get', stream=True) as r: # Do things with the response here. -.. _`documented here`: http://docs.python.org/2/library/contextlib.html#contextlib.closing - .. _keep-alive: Keep-Alive diff --git a/requests/models.py b/requests/models.py index 1375a3affa..2148024f99 100644 --- a/requests/models.py +++ b/requests/models.py @@ -634,6 +634,12 @@ def __init__(self): #: is a response. self.request = None + def __enter__(self): + return self + + def __exit__(self, *args): + self.close() + def __getstate__(self): # Consume everything; accessing the content attribute makes # sure the content has been fully read. diff --git a/tests/test_requests.py b/tests/test_requests.py index b8350cb752..365ffcb2c1 100755 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -1668,6 +1668,12 @@ def test_response_iter_lines(self, httpbin): next(it) assert len(list(it)) == 3 + def test_response_context_manager(self, httpbin): + with requests.get(httpbin('stream/4'), stream=True) as response: + assert isinstance(response, requests.Response) + + assert response.raw.closed + def test_unconsumed_session_response_closes_connection(self, httpbin): s = requests.session()