Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using requests iter_content() to avoid storing response body in RAM. #21

Merged
merged 3 commits into from
Aug 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/latest/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: f74829a8d80ac23fb5f1ba14167f300f
config: 4d96852847ec225f6bda6ce4c0135d77
tags: 645f666f9bcd5a90fca523b33c5a78b7
2 changes: 2 additions & 0 deletions docs/latest/google.resumable_media.requests.download.html
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@
<dt id="google.resumable_media.requests.download.Download.consume">
<code class="descname">consume</code><span class="sig-paren">(</span><em>transport</em><span class="sig-paren">)</span><a class="headerlink" href="#google.resumable_media.requests.download.Download.consume" title="Permalink to this definition">¶</a></dt>
<dd><p>Consume the resource to be downloaded.</p>
<p>If a <code class="docutils literal"><span class="pre">stream</span></code> is attached to this download, then the downloaded
resource will be written to the stream.</p>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
Expand Down
2 changes: 1 addition & 1 deletion docs/latest/searchindex.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions google/resumable_media/requests/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def _get_body(response):


def http_request(transport, method, url, data=None, headers=None,
retry_strategy=_DEFAULT_RETRY_STRATEGY):
retry_strategy=_DEFAULT_RETRY_STRATEGY, **transport_kwargs):
"""Make an HTTP request.

Args:
Expand All @@ -88,11 +88,14 @@ def http_request(transport, method, url, data=None, headers=None,
may also add additional headers).
retry_strategy (~google.resumable_media.common.RetryStrategy): The
strategy to use if the request fails and must be retried.
transport_kwargs (Dict[str, str]): Extra keyword arguments to be
passed along to ``transport.request``.

Returns:
~requests.Response: The return value of ``transport.request()``.
"""
func = functools.partial(
transport.request, method, url, data=data, headers=headers)
transport.request, method, url, data=data, headers=headers,
**transport_kwargs)

This comment was marked as spam.

This comment was marked as spam.

return _helpers.wait_and_retry(
func, RequestsMixin._get_status_code, retry_strategy)
38 changes: 36 additions & 2 deletions google/resumable_media/requests/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
from google.resumable_media.requests import _helpers


_SINGLE_GET_CHUNK_SIZE = 8192

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.



class Download(_helpers.RequestsMixin, _download.Download):
"""Helper to manage downloading a resource from a Google API.

Expand All @@ -45,9 +48,29 @@ class Download(_helpers.RequestsMixin, _download.Download):
end (Optional[int]): The last byte in a range to be downloaded.
"""

def _write_to_stream(self, response):
"""Write response body to a write-able stream.

.. note:

This method assumes that the ``_stream`` attribute is set on the
current download.

Args:
response (~requests.Response): The HTTP response object.
"""
with response:
body_iter = response.iter_content(
chunk_size=_SINGLE_GET_CHUNK_SIZE, decode_unicode=False)
for chunk in body_iter:
self._stream.write(chunk)

def consume(self, transport):
"""Consume the resource to be downloaded.

If a ``stream`` is attached to this download, then the downloaded
resource will be written to the stream.

Args:
transport (~requests.Session): A ``requests`` object which can
make authenticated requests.
Expand All @@ -61,9 +84,20 @@ def consume(self, transport):
"""
method, url, payload, headers = self._prepare_request()
# NOTE: We assume "payload is None" but pass it along anyway.
request_kwargs = {
u'data': payload,
u'headers': headers,
u'retry_strategy': self._retry_strategy,
}
if self._stream is not None:
request_kwargs[u'stream'] = True

result = _helpers.http_request(
transport, method, url, data=payload, headers=headers,
retry_strategy=self._retry_strategy)
transport, method, url, **request_kwargs)

if self._stream is not None:
self._write_to_stream(result)

self._process_response(result)
return result

Expand Down
Loading