Skip to content

Commit 6dc55fd

Browse files
author
Jon Wayne Parrott
authored
BigQuery & Storage: use client http for resumable media (googleapis#3705)
* BigQuery: Use client transport for resumable media * Storage: Use client transport for resumable media
1 parent 963d997 commit 6dc55fd

File tree

4 files changed

+93
-138
lines changed

4 files changed

+93
-138
lines changed

bigquery/google/cloud/bigquery/table.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
import six
2121

22-
import google.auth.transport.requests
2322
from google import resumable_media
2423
from google.resumable_media.requests import MultipartUpload
2524
from google.resumable_media.requests import ResumableUpload
@@ -823,8 +822,8 @@ def insert_data(self,
823822

824823
return errors
825824

826-
def _make_transport(self, client):
827-
"""Make an authenticated transport with a client's credentials.
825+
def _get_transport(self, client):
826+
"""Return the client's transport.
828827
829828
:type client: :class:`~google.cloud.bigquery.client.Client`
830829
:param client: The client to use.
@@ -834,10 +833,7 @@ def _make_transport(self, client):
834833
:returns: The transport (with credentials) that will
835834
make authenticated requests.
836835
"""
837-
# Create a ``requests`` transport with the client's credentials.
838-
transport = google.auth.transport.requests.AuthorizedSession(
839-
client._credentials)
840-
return transport
836+
return client._http
841837

842838
def _initiate_resumable_upload(self, client, stream,
843839
metadata, num_retries):
@@ -865,7 +861,7 @@ def _initiate_resumable_upload(self, client, stream,
865861
* The ``transport`` used to initiate the upload.
866862
"""
867863
chunk_size = _DEFAULT_CHUNKSIZE
868-
transport = self._make_transport(client)
864+
transport = self._get_transport(client)
869865
headers = _get_upload_headers(client._connection.USER_AGENT)
870866
upload_url = _RESUMABLE_URL_TEMPLATE.format(project=self.project)
871867
upload = ResumableUpload(upload_url, chunk_size, headers=headers)
@@ -941,7 +937,7 @@ def _do_multipart_upload(self, client, stream, metadata,
941937
msg = _READ_LESS_THAN_SIZE.format(size, len(data))
942938
raise ValueError(msg)
943939

944-
transport = self._make_transport(client)
940+
transport = self._get_transport(client)
945941
headers = _get_upload_headers(client._connection.USER_AGENT)
946942

947943
upload_url = _MULTIPART_URL_TEMPLATE.format(project=self.project)

bigquery/tests/unit/test_table.py

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,14 +1561,14 @@ def _row_data(row):
15611561
self.assertEqual(req['path'], '/%s' % PATH)
15621562
self.assertEqual(req['data'], SENT)
15631563

1564-
@mock.patch('google.auth.transport.requests.AuthorizedSession')
1565-
def test__make_transport(self, session_factory):
1566-
client = mock.Mock(spec=[u'_credentials'])
1564+
def test__get_transport(self):
1565+
client = mock.Mock(spec=[u'_credentials', '_http'])
1566+
client._http = mock.sentinel.http
15671567
table = self._make_one(self.TABLE_NAME, None)
1568-
transport = table._make_transport(client)
15691568

1570-
self.assertIs(transport, session_factory.return_value)
1571-
session_factory.assert_called_once_with(client._credentials)
1569+
transport = table._get_transport(client)
1570+
1571+
self.assertIs(transport, mock.sentinel.http)
15721572

15731573
@staticmethod
15741574
def _mock_requests_response(status_code, headers, content=b''):
@@ -1600,8 +1600,7 @@ def _initiate_resumable_upload_helper(self, num_retries=None):
16001600
response_headers = {'location': resumable_url}
16011601
fake_transport = self._mock_transport(
16021602
http_client.OK, response_headers)
1603-
table._make_transport = mock.Mock(
1604-
return_value=fake_transport, spec=[])
1603+
client._http = fake_transport
16051604

16061605
# Create some mock arguments and call the method under test.
16071606
data = b'goodbye gudbi gootbee'
@@ -1640,7 +1639,6 @@ def _initiate_resumable_upload_helper(self, num_retries=None):
16401639
self.assertEqual(stream.tell(), 0)
16411640

16421641
# Check the mocks.
1643-
table._make_transport.assert_called_once_with(client)
16441642
request_headers = expected_headers.copy()
16451643
request_headers['x-upload-content-type'] = _GENERIC_CONTENT_TYPE
16461644
fake_transport.request.assert_called_once_with(
@@ -1668,7 +1666,7 @@ def _do_multipart_upload_success_helper(
16681666

16691667
# Create mocks to be checked for doing transport.
16701668
fake_transport = self._mock_transport(http_client.OK, {})
1671-
table._make_transport = mock.Mock(return_value=fake_transport, spec=[])
1669+
client._http = fake_transport
16721670

16731671
# Create some mock arguments.
16741672
data = b'Bzzzz-zap \x00\x01\xf4'
@@ -1682,7 +1680,6 @@ def _do_multipart_upload_success_helper(
16821680
# Check the mocks and the returned value.
16831681
self.assertIs(response, fake_transport.request.return_value)
16841682
self.assertEqual(stream.tell(), size)
1685-
table._make_transport.assert_called_once_with(client)
16861683
get_boundary.assert_called_once_with()
16871684

16881685
upload_url = (
@@ -1723,7 +1720,7 @@ class TestTableUpload(object):
17231720
# rather than `unittest`-style.
17241721

17251722
@staticmethod
1726-
def _make_table():
1723+
def _make_table(transport=None):
17271724
from google.cloud.bigquery import _http
17281725
from google.cloud.bigquery import client
17291726
from google.cloud.bigquery import dataset
@@ -1733,6 +1730,7 @@ def _make_table():
17331730
client = mock.create_autospec(client.Client, instance=True)
17341731
client._connection = connection
17351732
client._credentials = mock.sentinel.credentials
1733+
client._http = transport
17361734
client.project = 'project_id'
17371735

17381736
dataset = dataset.Dataset('test_dataset', client)
@@ -1955,57 +1953,54 @@ def _make_resumable_upload_responses(cls, size):
19551953
return [initial_response, data_response, final_response]
19561954

19571955
@staticmethod
1958-
def _make_transport_patch(table, responses=None):
1959-
"""Patch a table's _make_transport method to return given responses."""
1956+
def _make_transport(responses=None):
19601957
import google.auth.transport.requests
19611958

19621959
transport = mock.create_autospec(
19631960
google.auth.transport.requests.AuthorizedSession, instance=True)
19641961
transport.request.side_effect = responses
1965-
return mock.patch.object(
1966-
table, '_make_transport', return_value=transport, autospec=True)
1962+
return transport
19671963

19681964
def test__do_resumable_upload(self):
1969-
table = self._make_table()
19701965
file_obj = self._make_file_obj()
19711966
file_obj_len = len(file_obj.getvalue())
1972-
responses = self._make_resumable_upload_responses(file_obj_len)
1967+
transport = self._make_transport(
1968+
self._make_resumable_upload_responses(file_obj_len))
1969+
table = self._make_table(transport)
19731970

1974-
with self._make_transport_patch(table, responses) as transport:
1975-
result = table._do_resumable_upload(
1976-
table._dataset._client,
1977-
file_obj,
1978-
self.EXPECTED_CONFIGURATION,
1979-
None)
1971+
result = table._do_resumable_upload(
1972+
table._dataset._client,
1973+
file_obj,
1974+
self.EXPECTED_CONFIGURATION,
1975+
None)
19801976

19811977
content = result.content.decode('utf-8')
19821978
assert json.loads(content) == {'size': file_obj_len}
19831979

19841980
# Verify that configuration data was passed in with the initial
19851981
# request.
1986-
transport.return_value.request.assert_any_call(
1982+
transport.request.assert_any_call(
19871983
'POST',
19881984
mock.ANY,
19891985
data=json.dumps(self.EXPECTED_CONFIGURATION).encode('utf-8'),
19901986
headers=mock.ANY)
19911987

19921988
def test__do_multipart_upload(self):
1993-
table = self._make_table()
1989+
transport = self._make_transport([self._make_response(http_client.OK)])
1990+
table = self._make_table(transport)
19941991
file_obj = self._make_file_obj()
19951992
file_obj_len = len(file_obj.getvalue())
1996-
responses = [self._make_response(http_client.OK)]
19971993

1998-
with self._make_transport_patch(table, responses) as transport:
1999-
table._do_multipart_upload(
2000-
table._dataset._client,
2001-
file_obj,
2002-
self.EXPECTED_CONFIGURATION,
2003-
file_obj_len,
2004-
None)
1994+
table._do_multipart_upload(
1995+
table._dataset._client,
1996+
file_obj,
1997+
self.EXPECTED_CONFIGURATION,
1998+
file_obj_len,
1999+
None)
20052000

20062001
# Verify that configuration data was passed in with the initial
20072002
# request.
2008-
request_args = transport.return_value.request.mock_calls[0][2]
2003+
request_args = transport.request.mock_calls[0][2]
20092004
request_data = request_args['data'].decode('utf-8')
20102005
request_headers = request_args['headers']
20112006

storage/google/cloud/storage/blob.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636

3737
from six.moves.urllib.parse import quote
3838

39-
import google.auth.transport.requests
4039
from google import resumable_media
4140
from google.resumable_media.requests import ChunkedDownload
4241
from google.resumable_media.requests import Download
@@ -361,8 +360,8 @@ def delete(self, client=None):
361360
"""
362361
return self.bucket.delete_blob(self.name, client=client)
363362

364-
def _make_transport(self, client):
365-
"""Make an authenticated transport with a client's credentials.
363+
def _get_transport(self, client):
364+
"""Return the client's transport.
366365
367366
:type client: :class:`~google.cloud.storage.client.Client`
368367
:param client: (Optional) The client to use. If not passed, falls back
@@ -374,10 +373,7 @@ def _make_transport(self, client):
374373
make authenticated requests.
375374
"""
376375
client = self._require_client(client)
377-
# Create a ``requests`` transport with the client's credentials.
378-
transport = google.auth.transport.requests.AuthorizedSession(
379-
client._credentials)
380-
return transport
376+
return client._http
381377

382378
def _get_download_url(self):
383379
"""Get the download URL for the current blob.
@@ -463,7 +459,7 @@ def download_to_file(self, file_obj, client=None):
463459
"""
464460
download_url = self._get_download_url()
465461
headers = _get_encryption_headers(self._encryption_key)
466-
transport = self._make_transport(client)
462+
transport = self._get_transport(client)
467463

468464
try:
469465
self._do_download(transport, file_obj, download_url, headers)
@@ -638,7 +634,7 @@ def _do_multipart_upload(self, client, stream, content_type,
638634
msg = _READ_LESS_THAN_SIZE.format(size, len(data))
639635
raise ValueError(msg)
640636

641-
transport = self._make_transport(client)
637+
transport = self._get_transport(client)
642638
info = self._get_upload_arguments(content_type)
643639
headers, object_metadata, content_type = info
644640

@@ -708,7 +704,7 @@ def _initiate_resumable_upload(self, client, stream, content_type,
708704
if chunk_size is None:
709705
chunk_size = self.chunk_size
710706

711-
transport = self._make_transport(client)
707+
transport = self._get_transport(client)
712708
info = self._get_upload_arguments(content_type)
713709
headers, object_metadata, content_type = info
714710
if extra_headers is not None:

0 commit comments

Comments
 (0)