Skip to content
Open
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
4 changes: 3 additions & 1 deletion google/resumable_media/_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class DownloadBase(object):
the downloaded resource can be written to.
start (int): The first byte in a range to be downloaded.
end (int): The last byte in a range to be downloaded.
user_agent (Optional[str]) : Custom user agent to be sent
headers (Optional[Mapping[str, str]]): Extra headers that should
be sent with the request, e.g. headers for encrypted data.

Expand All @@ -51,11 +52,12 @@ class DownloadBase(object):
"""

def __init__(self, media_url, stream=None,
start=None, end=None, headers=None):
start=None, end=None, user_agent=None, headers=None):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any particular reason to put user_agent before headers?

Copy link
Owner Author

@sumit-ql sumit-ql Jul 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing as such, i thought of having str argument(user_agent) before a dict(headers) looks good.

self.media_url = media_url
self._stream = stream
self.start = start
self.end = end
self.user_agent = user_agent
if headers is None:
headers = {}
self._headers = headers
Expand Down
3 changes: 3 additions & 0 deletions google/resumable_media/requests/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class Download(_helpers.RequestsMixin, _download.Download):
end (int): The last byte in a range to be downloaded. If not
provided, but ``start`` is provided, will download from the
``start`` to the end of the media.
user_agent (Optional[str]) : Custom user agent to be sent
headers (Optional[Mapping[str, str]]): Extra headers that should
be sent with the request, e.g. headers for encrypted data.

Expand Down Expand Up @@ -156,6 +157,8 @@ def consume(self, transport):
finished.
"""
method, url, payload, headers = self._prepare_request()
if self.user_agent is not None:
headers[u'User-Agent'] = self.user_agent
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure which way is better, to have the if check here or simply allow headers[u'User-Agent'] have a None value.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not set user_agent as None if api caller doesnt provide user-agent. In that case, user_agent would be 'python-requests/2.18.' which is set by the underlying requests lib.

# NOTE: We assume "payload is None" but pass it along anyway.
request_kwargs = {
u'data': payload,
Expand Down
15 changes: 12 additions & 3 deletions tests/unit/requests/test_download.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,11 @@ def test__write_to_stream_with_hash_check_fail(self):
decode_unicode=False)

def _consume_helper(
self, stream=None, end=65536, headers=None, chunks=(),
response_headers=None):
self, stream=None, end=65536, user_agent=None, headers=None,
chunks=(), response_headers=None):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same idea as in the first comment.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as comment in first.

download = download_mod.Download(
EXAMPLE_URL, stream=stream, end=end, headers=headers)
EXAMPLE_URL, stream=stream, end=end, user_agent=user_agent,
headers=headers)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing...

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

transport = mock.Mock(spec=[u'request'])
transport.request.return_value = _mock_response(
chunks=chunks, headers=response_headers)
Expand Down Expand Up @@ -234,6 +235,14 @@ def test_consume_with_headers(self):
# Make sure the headers have been modified.
assert headers == {u'range': range_bytes}

def test_consume_with_user_agent(self):
headers = {}
end = 16383
user_agent = "Custom-User-Agent-1.0"
range_bytes = u'bytes={:d}-{:d}'.format(0, end)
self._consume_helper(end=end, user_agent=user_agent, headers=headers)
assert headers == {u'range': range_bytes, u'User-Agent': user_agent}


class TestChunkedDownload(object):

Expand Down
5 changes: 4 additions & 1 deletion tests/unit/test__download.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,24 @@ def test_constructor_defaults(self):
assert download._stream is None
assert download.start is None
assert download.end is None
assert download.user_agent is None
assert download._headers == {}
assert not download._finished
_check_retry_strategy(download)

def test_constructor_explicit(self):
start = 11
end = 10001
user_agent = 'custome-user-agent-1.0'
headers = {u'foof': u'barf'}
download = _download.DownloadBase(
EXAMPLE_URL, stream=mock.sentinel.stream,
start=start, end=end, headers=headers)
start=start, end=end, user_agent=user_agent, headers=headers)
assert download.media_url == EXAMPLE_URL
assert download._stream is mock.sentinel.stream
assert download.start == start
assert download.end == end
assert download.user_agent == user_agent
assert download._headers is headers
assert not download._finished
_check_retry_strategy(download)
Expand Down