|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 |
|
3 | 3 | import os |
4 | | -import re |
5 | 4 | import sys |
6 | 5 | from datetime import datetime |
7 | 6 | from random import randint |
|
13 | 12 | import pytz |
14 | 13 | from pandas import DataFrame, NaT, compat |
15 | 14 | from pandas.compat import range, u |
16 | | -from pandas.compat.numpy import np_datetime64_compat |
17 | 15 |
|
18 | 16 | from pandas_gbq import gbq |
19 | 17 |
|
20 | 18 | try: |
21 | 19 | import mock |
22 | | -except ImportError: |
| 20 | +except ImportError: # pragma: NO COVER |
23 | 21 | from unittest import mock |
24 | 22 |
|
25 | 23 | TABLE_ID = 'new_test' |
@@ -280,233 +278,7 @@ def test_get_user_account_credentials_returns_credentials(self): |
280 | 278 | assert isinstance(credentials, Credentials) |
281 | 279 |
|
282 | 280 |
|
283 | | -class TestGBQUnit(object): |
284 | | - |
285 | | - @pytest.fixture(autouse=True) |
286 | | - def mock_bigquery_client(self, monkeypatch): |
287 | | - import google.cloud.bigquery |
288 | | - import google.cloud.bigquery.table |
289 | | - mock_client = mock.create_autospec(google.cloud.bigquery.Client) |
290 | | - # Mock out SELECT 1 query results. |
291 | | - mock_query = mock.create_autospec(google.cloud.bigquery.QueryJob) |
292 | | - mock_query.state = 'DONE' |
293 | | - mock_rows = mock.create_autospec( |
294 | | - google.cloud.bigquery.table.RowIterator) |
295 | | - mock_rows.total_rows = 1 |
296 | | - mock_rows.schema = [ |
297 | | - google.cloud.bigquery.SchemaField('_f0', 'INTEGER')] |
298 | | - mock_rows.__iter__.return_value = [(1,)] |
299 | | - mock_query.result.return_value = mock_rows |
300 | | - mock_client.query.return_value = mock_query |
301 | | - monkeypatch.setattr( |
302 | | - gbq.GbqConnector, 'get_client', lambda _: mock_client) |
303 | | - |
304 | | - @pytest.fixture(autouse=True) |
305 | | - def no_auth(self, monkeypatch): |
306 | | - import google.auth.credentials |
307 | | - mock_credentials = mock.create_autospec( |
308 | | - google.auth.credentials.Credentials) |
309 | | - monkeypatch.setattr( |
310 | | - gbq.GbqConnector, |
311 | | - 'get_application_default_credentials', |
312 | | - lambda _: mock_credentials) |
313 | | - monkeypatch.setattr( |
314 | | - gbq.GbqConnector, |
315 | | - 'get_user_account_credentials', |
316 | | - lambda _: mock_credentials) |
317 | | - |
318 | | - def test_should_return_credentials_path_set_by_env_var(self): |
319 | | - env = {'PANDAS_GBQ_CREDENTIALS_FILE': '/tmp/dummy.dat'} |
320 | | - with mock.patch.dict('os.environ', env): |
321 | | - assert gbq._get_credentials_file() == '/tmp/dummy.dat' |
322 | | - |
323 | | - @pytest.mark.parametrize( |
324 | | - ('input', 'type_', 'expected'), [ |
325 | | - (1, 'INTEGER', int(1)), |
326 | | - (1, 'FLOAT', float(1)), |
327 | | - pytest.param('false', 'BOOLEAN', False, marks=pytest.mark.xfail), |
328 | | - pytest.param( |
329 | | - '0e9', 'TIMESTAMP', |
330 | | - np_datetime64_compat('1970-01-01T00:00:00Z'), |
331 | | - marks=pytest.mark.xfail), |
332 | | - ('STRING', 'STRING', 'STRING'), |
333 | | - ]) |
334 | | - def test_should_return_bigquery_correctly_typed( |
335 | | - self, input, type_, expected): |
336 | | - result = gbq._parse_data( |
337 | | - dict(fields=[dict(name='x', type=type_, mode='NULLABLE')]), |
338 | | - rows=[[input]]).iloc[0, 0] |
339 | | - assert result == expected |
340 | | - |
341 | | - def test_to_gbq_should_fail_if_invalid_table_name_passed(self): |
342 | | - with pytest.raises(gbq.NotFoundException): |
343 | | - gbq.to_gbq(DataFrame(), 'invalid_table_name', project_id="1234") |
344 | | - |
345 | | - def test_to_gbq_with_no_project_id_given_should_fail(self): |
346 | | - with pytest.raises(TypeError): |
347 | | - gbq.to_gbq(DataFrame(), 'dataset.tablename') |
348 | | - |
349 | | - def test_to_gbq_with_verbose_new_pandas_warns_deprecation(self): |
350 | | - import pkg_resources |
351 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
352 | | - pandas_version = pkg_resources.parse_version('0.23.0') |
353 | | - with pytest.warns(FutureWarning), \ |
354 | | - mock.patch( |
355 | | - 'pkg_resources.Distribution.parsed_version', |
356 | | - new_callable=mock.PropertyMock) as mock_version: |
357 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
358 | | - try: |
359 | | - gbq.to_gbq( |
360 | | - DataFrame(), |
361 | | - 'dataset.tablename', |
362 | | - project_id='my-project', |
363 | | - verbose=True) |
364 | | - except gbq.TableCreationError: |
365 | | - pass |
366 | | - |
367 | | - def test_to_gbq_with_not_verbose_new_pandas_warns_deprecation(self): |
368 | | - import pkg_resources |
369 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
370 | | - pandas_version = pkg_resources.parse_version('0.23.0') |
371 | | - with pytest.warns(FutureWarning), \ |
372 | | - mock.patch( |
373 | | - 'pkg_resources.Distribution.parsed_version', |
374 | | - new_callable=mock.PropertyMock) as mock_version: |
375 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
376 | | - try: |
377 | | - gbq.to_gbq( |
378 | | - DataFrame(), |
379 | | - 'dataset.tablename', |
380 | | - project_id='my-project', |
381 | | - verbose=False) |
382 | | - except gbq.TableCreationError: |
383 | | - pass |
384 | | - |
385 | | - def test_to_gbq_wo_verbose_w_new_pandas_no_warnings(self, recwarn): |
386 | | - import pkg_resources |
387 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
388 | | - pandas_version = pkg_resources.parse_version('0.23.0') |
389 | | - with mock.patch( |
390 | | - 'pkg_resources.Distribution.parsed_version', |
391 | | - new_callable=mock.PropertyMock) as mock_version: |
392 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
393 | | - try: |
394 | | - gbq.to_gbq( |
395 | | - DataFrame(), 'dataset.tablename', project_id='my-project') |
396 | | - except gbq.TableCreationError: |
397 | | - pass |
398 | | - assert len(recwarn) == 0 |
399 | | - |
400 | | - def test_to_gbq_with_verbose_old_pandas_no_warnings(self, recwarn): |
401 | | - import pkg_resources |
402 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
403 | | - pandas_version = pkg_resources.parse_version('0.22.0') |
404 | | - with mock.patch( |
405 | | - 'pkg_resources.Distribution.parsed_version', |
406 | | - new_callable=mock.PropertyMock) as mock_version: |
407 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
408 | | - try: |
409 | | - gbq.to_gbq( |
410 | | - DataFrame(), |
411 | | - 'dataset.tablename', |
412 | | - project_id='my-project', |
413 | | - verbose=True) |
414 | | - except gbq.TableCreationError: |
415 | | - pass |
416 | | - assert len(recwarn) == 0 |
417 | | - |
418 | | - def test_read_gbq_with_no_project_id_given_should_fail(self): |
419 | | - with pytest.raises(TypeError): |
420 | | - gbq.read_gbq('SELECT 1') |
421 | | - |
422 | | - def test_that_parse_data_works_properly(self): |
423 | | - |
424 | | - from google.cloud.bigquery.table import Row |
425 | | - test_schema = {'fields': [ |
426 | | - {'mode': 'NULLABLE', 'name': 'column_x', 'type': 'STRING'}]} |
427 | | - field_to_index = {'column_x': 0} |
428 | | - values = ('row_value',) |
429 | | - test_page = [Row(values, field_to_index)] |
430 | | - |
431 | | - test_output = gbq._parse_data(test_schema, test_page) |
432 | | - correct_output = DataFrame({'column_x': ['row_value']}) |
433 | | - tm.assert_frame_equal(test_output, correct_output) |
434 | | - |
435 | | - def test_read_gbq_with_invalid_private_key_json_should_fail(self): |
436 | | - with pytest.raises(gbq.InvalidPrivateKeyFormat): |
437 | | - gbq.read_gbq('SELECT 1', project_id='x', private_key='y') |
438 | | - |
439 | | - def test_read_gbq_with_empty_private_key_json_should_fail(self): |
440 | | - with pytest.raises(gbq.InvalidPrivateKeyFormat): |
441 | | - gbq.read_gbq('SELECT 1', project_id='x', private_key='{}') |
442 | | - |
443 | | - def test_read_gbq_with_private_key_json_wrong_types_should_fail(self): |
444 | | - with pytest.raises(gbq.InvalidPrivateKeyFormat): |
445 | | - gbq.read_gbq( |
446 | | - 'SELECT 1', project_id='x', |
447 | | - private_key='{ "client_email" : 1, "private_key" : True }') |
448 | | - |
449 | | - def test_read_gbq_with_empty_private_key_file_should_fail(self): |
450 | | - with tm.ensure_clean() as empty_file_path: |
451 | | - with pytest.raises(gbq.InvalidPrivateKeyFormat): |
452 | | - gbq.read_gbq('SELECT 1', project_id='x', |
453 | | - private_key=empty_file_path) |
454 | | - |
455 | | - def test_read_gbq_with_corrupted_private_key_json_should_fail(self): |
456 | | - _skip_if_no_private_key_contents() |
457 | | - |
458 | | - with pytest.raises(gbq.InvalidPrivateKeyFormat): |
459 | | - gbq.read_gbq( |
460 | | - 'SELECT 1', project_id='x', |
461 | | - private_key=re.sub('[a-z]', '9', _get_private_key_contents())) |
462 | | - |
463 | | - def test_read_gbq_with_verbose_new_pandas_warns_deprecation(self): |
464 | | - import pkg_resources |
465 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
466 | | - pandas_version = pkg_resources.parse_version('0.23.0') |
467 | | - with pytest.warns(FutureWarning), \ |
468 | | - mock.patch( |
469 | | - 'pkg_resources.Distribution.parsed_version', |
470 | | - new_callable=mock.PropertyMock) as mock_version: |
471 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
472 | | - gbq.read_gbq('SELECT 1', project_id='my-project', verbose=True) |
473 | | - |
474 | | - def test_read_gbq_with_not_verbose_new_pandas_warns_deprecation(self): |
475 | | - import pkg_resources |
476 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
477 | | - pandas_version = pkg_resources.parse_version('0.23.0') |
478 | | - with pytest.warns(FutureWarning), \ |
479 | | - mock.patch( |
480 | | - 'pkg_resources.Distribution.parsed_version', |
481 | | - new_callable=mock.PropertyMock) as mock_version: |
482 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
483 | | - gbq.read_gbq('SELECT 1', project_id='my-project', verbose=False) |
484 | | - |
485 | | - def test_read_gbq_wo_verbose_w_new_pandas_no_warnings(self, recwarn): |
486 | | - import pkg_resources |
487 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
488 | | - pandas_version = pkg_resources.parse_version('0.23.0') |
489 | | - with mock.patch( |
490 | | - 'pkg_resources.Distribution.parsed_version', |
491 | | - new_callable=mock.PropertyMock) as mock_version: |
492 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
493 | | - gbq.read_gbq('SELECT 1', project_id='my-project') |
494 | | - assert len(recwarn) == 0 |
495 | | - |
496 | | - def test_read_gbq_with_verbose_old_pandas_no_warnings(self, recwarn): |
497 | | - import pkg_resources |
498 | | - min_bq_version = pkg_resources.parse_version('0.29.0') |
499 | | - pandas_version = pkg_resources.parse_version('0.22.0') |
500 | | - with mock.patch( |
501 | | - 'pkg_resources.Distribution.parsed_version', |
502 | | - new_callable=mock.PropertyMock) as mock_version: |
503 | | - mock_version.side_effect = [min_bq_version, pandas_version] |
504 | | - gbq.read_gbq('SELECT 1', project_id='my-project', verbose=True) |
505 | | - assert len(recwarn) == 0 |
506 | | - |
507 | | - |
508 | 281 | def test_should_read(project, credentials): |
509 | | - |
510 | 282 | query = 'SELECT "PI" AS valid_string' |
511 | 283 | df = gbq.read_gbq(query, project_id=project, private_key=credentials) |
512 | 284 | tm.assert_frame_equal(df, DataFrame({'valid_string': ['PI']})) |
|
0 commit comments