Skip to content

Commit 74f754d

Browse files
author
Jon Wayne Parrott
committed
BigQuery: replace httplib2 with Requests
1 parent 976c5f4 commit 74f754d

File tree

8 files changed

+26
-50
lines changed

8 files changed

+26
-50
lines changed

bigquery/google/cloud/bigquery/client.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ class Client(ClientWithProject):
6464
passed), falls back to the default inferred from the
6565
environment.
6666
67-
:type _http: :class:`~httplib2.Http`
67+
:type _http: :class:`~requests.Session`
6868
:param _http: (Optional) HTTP object to make requests. Can be any object
6969
that defines ``request()`` with the same interface as
70-
:meth:`~httplib2.Http.request`. If not passed, an
70+
:meth:`requests.Session.request`. If not passed, an
7171
``_http`` object is created that is bound to the
7272
``credentials`` for the current object.
7373
This parameter should be considered private, and could

bigquery/google/cloud/bigquery/dataset.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ def _parse_access_grants(access):
364364
def _set_properties(self, api_response):
365365
"""Update properties from resource in body of ``api_response``
366366
367-
:type api_response: httplib2.Response
367+
:type api_response: dict
368368
:param api_response: response returned from an API call.
369369
"""
370370
self._properties.clear()

bigquery/google/cloud/bigquery/job.py

+3-10
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
"""Define API Jobs."""
1616

17-
import collections
1817
import threading
1918

2019
import six
@@ -58,8 +57,6 @@
5857
'tableUnavailable': http_client.BAD_REQUEST,
5958
}
6059

61-
_FakeResponse = collections.namedtuple('_FakeResponse', ['status'])
62-
6360

6461
def _error_result_to_exception(error_result):
6562
"""Maps BigQuery error reasons to an exception.
@@ -80,12 +77,8 @@ def _error_result_to_exception(error_result):
8077
status_code = _ERROR_REASON_TO_EXCEPTION.get(
8178
reason, http_client.INTERNAL_SERVER_ERROR)
8279
# make_exception expects an httplib2 response object.
83-
fake_response = _FakeResponse(status=status_code)
84-
return exceptions.make_exception(
85-
fake_response,
86-
error_result.get('message', ''),
87-
error_info=error_result,
88-
use_json=False)
80+
return exceptions.from_http_status(
81+
status_code, error_result.get('message', ''), errors=[error_result])
8982

9083

9184
class Compression(_EnumProperty):
@@ -307,7 +300,7 @@ def _scrub_local_properties(self, cleaned):
307300
def _set_properties(self, api_response):
308301
"""Update properties from resource in body of ``api_response``
309302
310-
:type api_response: httplib2.Response
303+
:type api_response: dict
311304
:param api_response: response returned from an API call
312305
"""
313306
cleaned = api_response.copy()

bigquery/google/cloud/bigquery/query.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ def schema(self):
310310
def _set_properties(self, api_response):
311311
"""Update properties from resource in body of ``api_response``
312312
313-
:type api_response: httplib2.Response
313+
:type api_response: dict
314314
:param api_response: response returned from an API call
315315
"""
316316
self._properties.clear()

bigquery/google/cloud/bigquery/table.py

+4-25
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,16 @@
1717
import datetime
1818
import os
1919

20-
import httplib2
2120
import six
2221

2322
import google.auth.transport.requests
2423
from google import resumable_media
2524
from google.resumable_media.requests import MultipartUpload
2625
from google.resumable_media.requests import ResumableUpload
2726

27+
from google.cloud import exceptions
2828
from google.cloud._helpers import _datetime_from_microseconds
2929
from google.cloud._helpers import _millis_from_datetime
30-
from google.cloud.exceptions import NotFound
31-
from google.cloud.exceptions import make_exception
3230
from google.cloud.iterator import HTTPIterator
3331
from google.cloud.bigquery.schema import SchemaField
3432
from google.cloud.bigquery._helpers import _item_to_row
@@ -474,7 +472,7 @@ def _require_client(self, client):
474472
def _set_properties(self, api_response):
475473
"""Update properties from resource in body of ``api_response``
476474
477-
:type api_response: httplib2.Response
475+
:type api_response: dict
478476
:param api_response: response returned from an API call
479477
"""
480478
self._properties.clear()
@@ -563,7 +561,7 @@ def exists(self, client=None):
563561
try:
564562
client._connection.api_request(method='GET', path=self.path,
565563
query_params={'fields': 'id'})
566-
except NotFound:
564+
except exceptions.NotFound:
567565
return False
568566
else:
569567
return True
@@ -1113,7 +1111,7 @@ def upload_from_file(self,
11131111
client, file_obj, metadata, size, num_retries)
11141112
return client.job_from_resource(created_json)
11151113
except resumable_media.InvalidResponse as exc:
1116-
_raise_from_invalid_response(exc)
1114+
raise exceptions.from_http_response(exc.response)
11171115
# pylint: enable=too-many-arguments,too-many-locals
11181116

11191117

@@ -1298,22 +1296,3 @@ def _get_upload_metadata(source_format, schema, dataset, name):
12981296
'load': load_config,
12991297
},
13001298
}
1301-
1302-
1303-
def _raise_from_invalid_response(error, error_info=None):
1304-
"""Re-wrap and raise an ``InvalidResponse`` exception.
1305-
1306-
:type error: :exc:`google.resumable_media.InvalidResponse`
1307-
:param error: A caught exception from the ``google-resumable-media``
1308-
library.
1309-
1310-
:type error_info: str
1311-
:param error_info: (Optional) Extra information about the failed request.
1312-
1313-
:raises: :class:`~google.cloud.exceptions.GoogleCloudError` corresponding
1314-
to the failed status code
1315-
"""
1316-
response = error.response
1317-
faux_response = httplib2.Response({'status': response.status_code})
1318-
raise make_exception(faux_response, response.content,
1319-
error_info=error_info, use_json=False)

bigquery/tests/unit/test__http.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import unittest
1616

1717
import mock
18+
import requests
1819

1920

2021
class TestConnection(unittest.TestCase):
@@ -55,10 +56,12 @@ def test_extra_headers(self):
5556
from google.cloud import _http as base_http
5657
from google.cloud.bigquery import _http as MUT
5758

58-
http = mock.Mock(spec=['request'])
59-
response = mock.Mock(status=200, spec=['status'])
59+
http = mock.create_autospec(requests.Session, instance=True)
60+
response = requests.Response()
61+
response.status_code = 200
6062
data = b'brent-spiner'
61-
http.request.return_value = response, data
63+
response._content = data
64+
http.request.return_value = response
6265
client = mock.Mock(_http=http, spec=['_http'])
6366

6467
conn = self._make_one(client)
@@ -68,15 +71,14 @@ def test_extra_headers(self):
6871
self.assertEqual(result, data)
6972

7073
expected_headers = {
71-
'Content-Length': str(len(req_data)),
7274
'Accept-Encoding': 'gzip',
7375
base_http.CLIENT_INFO_HEADER: MUT._CLIENT_INFO,
7476
'User-Agent': conn.USER_AGENT,
7577
}
7678
expected_uri = conn.build_api_url('/rainbow')
7779
http.request.assert_called_once_with(
78-
body=req_data,
80+
data=req_data,
7981
headers=expected_headers,
8082
method='GET',
81-
uri=expected_uri,
83+
url=expected_uri,
8284
)

bigquery/tests/unit/test_job.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def test_simple(self):
3131
exception = self._call_fut(error_result)
3232
self.assertEqual(exception.code, http_client.BAD_REQUEST)
3333
self.assertTrue(exception.message.startswith('bad request'))
34-
self.assertIn("'reason': 'invalid'", exception.message)
34+
self.assertIn(error_result, exception.errors)
3535

3636
def test_missing_reason(self):
3737
error_result = {}

bigquery/tests/unit/test_table.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1744,9 +1744,11 @@ def _make_table():
17441744
def _make_response(status_code, content='', headers={}):
17451745
"""Make a mock HTTP response."""
17461746
import requests
1747-
response = mock.create_autospec(requests.Response, instance=True)
1748-
response.content = content.encode('utf-8')
1749-
response.headers = headers
1747+
response = requests.Response()
1748+
response.request = requests.Request(
1749+
'POST', 'http://example.com').prepare()
1750+
response._content = content.encode('utf-8')
1751+
response.headers.update(headers)
17501752
response.status_code = status_code
17511753
return response
17521754

@@ -1921,7 +1923,7 @@ def test_upload_from_file_failure(self):
19211923
table.upload_from_file(
19221924
file_obj, source_format='CSV', rewind=True)
19231925

1924-
assert exc_info.value.message == response.content.decode('utf-8')
1926+
assert response.text in exc_info.value.message
19251927
assert exc_info.value.errors == []
19261928

19271929
def test_upload_from_file_bad_mode(self):

0 commit comments

Comments
 (0)