Skip to content

Commit b089397

Browse files
committed
Merge pull request tylertreat#71 from kamatama41/json-key
Add support for JSON key authorization
2 parents f69fe34 + 0d57668 commit b089397

File tree

3 files changed

+52
-4
lines changed

3 files changed

+52
-4
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ key = 'key.pem'
2626
client = get_client(project_id, service_account=service_account,
2727
private_key_file=key, readonly=True)
2828

29+
# JSON key provided by Google
30+
json_key = 'key.json'
31+
32+
client = get_client(project_id, json_key_file=json_key, readonly=True)
33+
2934
# Submit an async query.
3035
job_id, _results = client.query('SELECT * FROM dataset.my_table LIMIT 1000')
3136

bigquery/client.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@
4444

4545

4646
def get_client(project_id, credentials=None, service_account=None,
47-
private_key=None, private_key_file=None, readonly=True,
48-
swallow_results=True):
47+
private_key=None, private_key_file=None,
48+
json_key=None, json_key_file=None,
49+
readonly=True, swallow_results=True):
4950
"""Return a singleton instance of BigQueryClient. Either
5051
AssertionCredentials or a service account and private key combination need
5152
to be provided in order to authenticate requests to BigQuery.
@@ -60,6 +61,9 @@ def get_client(project_id, credentials=None, service_account=None,
6061
private_key_file: the name of the file containing the private key
6162
associated with the service account in PKCS12 or PEM
6263
format.
64+
json_key: the JSON key associated with the service account
65+
json_key_file: the name of the JSON key file associated with
66+
the service account
6367
readonly: bool indicating if BigQuery access is read-only. Has no
6468
effect if credentials are provided.
6569
swallow_results: If set to false then return the actual response value
@@ -70,13 +74,21 @@ def get_client(project_id, credentials=None, service_account=None,
7074
"""
7175

7276
if not credentials:
73-
assert service_account and (private_key or private_key_file), \
74-
'Must provide AssertionCredentials or service account and key'
77+
assert (service_account and (private_key or private_key_file)) or (json_key or json_key_file), \
78+
'Must provide AssertionCredentials or service account and P12 key or JSON key'
7579

7680
if private_key_file:
7781
with open(private_key_file, 'rb') as key_file:
7882
private_key = key_file.read()
7983

84+
if json_key_file:
85+
with open(json_key_file, 'rb') as key_file:
86+
json_key = json.loads(key_file.read())
87+
88+
if json_key:
89+
service_account = json_key['client_email']
90+
private_key = json_key['private_key']
91+
8092
bq_service = _get_bq_service(credentials=credentials,
8193
service_account=service_account,
8294
private_key=private_key,

bigquery/tests/test_client.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,37 @@ def test_initialize_key_file(self, mock_open, mock_build,
135135
self.assertEquals(mock_bq, bq_client.bigquery)
136136
self.assertEquals(project_id, bq_client.project_id)
137137

138+
@mock.patch('bigquery.client._credentials')
139+
@mock.patch('bigquery.client.build')
140+
@mock.patch('__builtin__.open' if six.PY2 else 'builtins.open')
141+
def test_initialize_json_key_file(self, mock_open, mock_build, mock_return_cred):
142+
"""Ensure that a BigQueryClient is initialized and returned with
143+
read/write permissions using a JSON key file.
144+
"""
145+
from bigquery.client import BIGQUERY_SCOPE
146+
import json
147+
148+
mock_cred = mock.Mock()
149+
mock_http = mock.Mock()
150+
mock_cred.return_value.authorize.return_value = mock_http
151+
mock_bq = mock.Mock()
152+
mock_build.return_value = mock_bq
153+
json_key_file = 'key.json'
154+
json_key = {'client_email': 'mail', 'private_key': 'pkey'}
155+
mock_open.return_value.__enter__.return_value.read.return_value = json.dumps(json_key)
156+
project_id = 'project'
157+
mock_return_cred.return_value = mock_cred
158+
159+
bq_client = client.get_client(project_id, json_key_file=json_key_file, readonly=False)
160+
161+
mock_open.assert_called_once_with(json_key_file, 'rb')
162+
mock_return_cred.assert_called_once_with()
163+
mock_cred.assert_called_once_with(json_key['client_email'], json_key['private_key'], scope=BIGQUERY_SCOPE)
164+
self.assertTrue(mock_cred.return_value.authorize.called)
165+
mock_build.assert_called_once_with('bigquery', 'v2', http=mock_http)
166+
self.assertEquals(mock_bq, bq_client.bigquery)
167+
self.assertEquals(project_id, bq_client.project_id)
168+
138169

139170
class TestQuery(unittest.TestCase):
140171

0 commit comments

Comments
 (0)