diff --git a/.travis.yml b/.travis.yml index cbd76951..b1ab8f9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,26 @@ -sudo: false - language: python +matrix: + include: + - os: linux + python: 2.7 + env: PYTHON=2.7 PANDAS=0.19.2 COVERAGE='false' LINT='true' + - os: linux + python: 3.5 + env: PYTHON=3.5 PANDAS=0.18.1 COVERAGE='true' LINT='false' + - os: linux + python: 3.6 + env: PYTHON=3.6 PANDAS=0.20.1 COVERAGE='false' LINT='false' + - os: linux + python: 3.6 + env: PYTHON=3.6 PANDAS=MASTER COVERAGE='false' LINT='true' env: - - PYTHON=2.7 PANDAS=0.19.2 COVERAGE='false' LINT='true' PYENV_VERSION=2.7.14 - - PYTHON=3.5 PANDAS=0.18.1 COVERAGE='true' LINT='false' PYENV_VERSION=3.5.4 - - PYTHON=3.6 PANDAS=0.20.1 COVERAGE='false' LINT='false' PYENV_VERSION=3.6.1 - - PYTHON=3.6 PANDAS=MASTER COVERAGE='false' LINT='true' PYENV_VERSION=3.6.1 before_install: - echo "before_install" - source ci/travis_process_gbq_encryption.sh install: - # work around https://github.com/travis-ci/travis-ci/issues/8363 - # https://github.com/pre-commit/pre-commit/commit/e3ab8902692e896da9ded42bd4d76ea4e1de359d - - pyenv install -s $PYENV_VERSION - - pyenv global system $PYENV_VERSION # Upgrade setuptools and pip to work around # https://github.com/pypa/setuptools/issues/885 - pip install --upgrade setuptools diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 6600e52c..47a43f9f 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -1,11 +1,14 @@ Changelog ========= -.. _changelog-0.5.1: +.. _changelog-0.6.0: -0.5.1 / (Unreleased) +0.6.0 / 2018-08-15 -------------------- +- Warn when ``dialect`` is not passed in to ``read_gbq``. The default dialect + will be changing from 'legacy' to 'standard' in a future version. + (:issue:`195`) - Use general float with 15 decimal digit precision when writing to local CSV buffer in ``to_gbq``. This prevents numerical overflow in certain edge cases. (:issue:`192`) diff --git a/pandas_gbq/gbq.py b/pandas_gbq/gbq.py index df20e76b..e7642ccd 100644 --- a/pandas_gbq/gbq.py +++ b/pandas_gbq/gbq.py @@ -471,7 +471,7 @@ def _parse_data(schema, rows): def read_gbq(query, project_id=None, index_col=None, col_order=None, reauth=False, private_key=None, auth_local_webserver=False, - dialect='legacy', location=None, configuration=None, + dialect=None, location=None, configuration=None, verbose=None): r"""Load data from Google BigQuery using google-cloud-python @@ -515,6 +515,8 @@ def read_gbq(query, project_id=None, index_col=None, col_order=None, .. versionadded:: 0.2.0 dialect : str, default 'legacy' + Note: The default value is changing to 'standard' in a future verion. + SQL syntax dialect to use. Value can be one of: ``'legacy'`` @@ -552,6 +554,13 @@ def read_gbq(query, project_id=None, index_col=None, col_order=None, df: DataFrame DataFrame representing results of query. """ + if dialect is None: + dialect = 'legacy' + warnings.warn( + 'The default value for dialect is changing to "standard" in a ' + 'future version. Pass in dialect="legacy" to disable this ' + 'warning.', + FutureWarning, stacklevel=2) _test_google_api_imports() @@ -559,7 +568,7 @@ def read_gbq(query, project_id=None, index_col=None, col_order=None, warnings.warn( "verbose is deprecated and will be removed in " "a future version. Set logging level in order to vary " - "verbosity", FutureWarning, stacklevel=1) + "verbosity", FutureWarning, stacklevel=2) if dialect not in ('legacy', 'standard'): raise ValueError("'{0}' is not valid for dialect".format(dialect)) diff --git a/tests/system/test_gbq.py b/tests/system/test_gbq.py index 39b2f4ee..bb91befb 100644 --- a/tests/system/test_gbq.py +++ b/tests/system/test_gbq.py @@ -127,7 +127,8 @@ def test_should_be_able_to_get_results_from_query(self, gbq_connector): def test_should_read(project, credentials): query = 'SELECT "PI" AS valid_string' - df = gbq.read_gbq(query, project_id=project, private_key=credentials) + df = gbq.read_gbq( + query, project_id=project, private_key=credentials, dialect='legacy') tm.assert_frame_equal(df, DataFrame({'valid_string': ['PI']})) @@ -145,25 +146,29 @@ def setup(self, project, credentials): def test_should_properly_handle_valid_strings(self, project_id): query = 'SELECT "PI" AS valid_string' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'valid_string': ['PI']})) def test_should_properly_handle_empty_strings(self, project_id): query = 'SELECT "" AS empty_string' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'empty_string': [""]})) def test_should_properly_handle_null_strings(self, project_id): query = 'SELECT STRING(NULL) AS null_string' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'null_string': [None]})) def test_should_properly_handle_valid_integers(self, project_id): query = 'SELECT INTEGER(3) AS valid_integer' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'valid_integer': [3]})) def test_should_properly_handle_nullable_integers(self, project_id): @@ -171,14 +176,16 @@ def test_should_properly_handle_nullable_integers(self, project_id): (SELECT 1 AS nullable_integer), (SELECT NULL AS nullable_integer)''' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal( df, DataFrame({'nullable_integer': [1, None]}).astype(object)) def test_should_properly_handle_valid_longs(self, project_id): query = 'SELECT 1 << 62 AS valid_long' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal( df, DataFrame({'valid_long': [1 << 62]})) @@ -187,21 +194,24 @@ def test_should_properly_handle_nullable_longs(self, project_id): (SELECT 1 << 62 AS nullable_long), (SELECT NULL AS nullable_long)''' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal( df, DataFrame({'nullable_long': [1 << 62, None]}).astype(object)) def test_should_properly_handle_null_integers(self, project_id): query = 'SELECT INTEGER(NULL) AS null_integer' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'null_integer': [None]})) def test_should_properly_handle_valid_floats(self, project_id): from math import pi query = 'SELECT PI() AS valid_float' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame( {'valid_float': [pi]})) @@ -211,7 +221,8 @@ def test_should_properly_handle_nullable_floats(self, project_id): (SELECT PI() AS nullable_float), (SELECT NULL AS nullable_float)''' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal( df, DataFrame({'nullable_float': [pi, None]})) @@ -219,7 +230,8 @@ def test_should_properly_handle_valid_doubles(self, project_id): from math import pi query = 'SELECT PI() * POW(10, 307) AS valid_double' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame( {'valid_double': [pi * 10 ** 307]})) @@ -229,27 +241,31 @@ def test_should_properly_handle_nullable_doubles(self, project_id): (SELECT PI() * POW(10, 307) AS nullable_double), (SELECT NULL AS nullable_double)''' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal( df, DataFrame({'nullable_double': [pi * 10 ** 307, None]})) def test_should_properly_handle_null_floats(self, project_id): query = 'SELECT FLOAT(NULL) AS null_float' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'null_float': [np.nan]})) def test_should_properly_handle_timestamp_unix_epoch(self, project_id): query = 'SELECT TIMESTAMP("1970-01-01 00:00:00") AS unix_epoch' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame( {'unix_epoch': [np.datetime64('1970-01-01T00:00:00.000000Z')]})) def test_should_properly_handle_arbitrary_timestamp(self, project_id): query = 'SELECT TIMESTAMP("2004-09-15 05:00:00") AS valid_timestamp' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({ 'valid_timestamp': [np.datetime64('2004-09-15T05:00:00.000000Z')] })) @@ -257,25 +273,29 @@ def test_should_properly_handle_arbitrary_timestamp(self, project_id): def test_should_properly_handle_null_timestamp(self, project_id): query = 'SELECT TIMESTAMP(NULL) AS null_timestamp' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'null_timestamp': [NaT]})) def test_should_properly_handle_true_boolean(self, project_id): query = 'SELECT BOOLEAN(TRUE) AS true_boolean' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'true_boolean': [True]})) def test_should_properly_handle_false_boolean(self, project_id): query = 'SELECT BOOLEAN(FALSE) AS false_boolean' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'false_boolean': [False]})) def test_should_properly_handle_null_boolean(self, project_id): query = 'SELECT BOOLEAN(NULL) AS null_boolean' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'null_boolean': [None]})) def test_should_properly_handle_nullable_booleans(self, project_id): @@ -283,7 +303,8 @@ def test_should_properly_handle_nullable_booleans(self, project_id): (SELECT BOOLEAN(TRUE) AS nullable_boolean), (SELECT NULL AS nullable_boolean)''' df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal( df, DataFrame({'nullable_boolean': [True, None]}).astype(object)) @@ -300,14 +321,16 @@ def test_unicode_string_conversion_and_normalization(self, project_id): query = 'SELECT "{0}" AS unicode_string'.format(unicode_string) df = gbq.read_gbq(query, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') tm.assert_frame_equal(df, correct_test_datatype) def test_index_column(self, project_id): query = "SELECT 'a' AS string_1, 'b' AS string_2" result_frame = gbq.read_gbq(query, project_id=project_id, index_col="string_1", - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') correct_frame = DataFrame( {'string_1': ['a'], 'string_2': ['b']}).set_index("string_1") assert result_frame.index.name == correct_frame.index.name @@ -317,7 +340,8 @@ def test_column_order(self, project_id): col_order = ['string_3', 'string_1', 'string_2'] result_frame = gbq.read_gbq(query, project_id=project_id, col_order=col_order, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') correct_frame = DataFrame({'string_1': ['a'], 'string_2': [ 'b'], 'string_3': ['c']})[col_order] tm.assert_frame_equal(result_frame, correct_frame) @@ -330,14 +354,16 @@ def test_read_gbq_raises_invalid_column_order(self, project_id): with pytest.raises(gbq.InvalidColumnOrder): gbq.read_gbq(query, project_id=project_id, col_order=col_order, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') def test_column_order_plus_index(self, project_id): query = "SELECT 'a' AS string_1, 'b' AS string_2, 'c' AS string_3" col_order = ['string_3', 'string_2'] result_frame = gbq.read_gbq(query, project_id=project_id, index_col='string_1', col_order=col_order, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') correct_frame = DataFrame( {'string_1': ['a'], 'string_2': ['b'], 'string_3': ['c']}) correct_frame.set_index('string_1', inplace=True) @@ -352,13 +378,15 @@ def test_read_gbq_raises_invalid_index_column(self, project_id): with pytest.raises(gbq.InvalidIndexColumn): gbq.read_gbq(query, project_id=project_id, index_col='string_bbb', col_order=col_order, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') def test_malformed_query(self, project_id): with pytest.raises(gbq.GenericGBQException): gbq.read_gbq("SELCET * FORM [publicdata:samples.shakespeare]", project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') def test_bad_project_id(self): with pytest.raises(gbq.GenericGBQException): @@ -370,7 +398,8 @@ def test_bad_table_name(self, project_id): with pytest.raises(gbq.GenericGBQException): gbq.read_gbq("SELECT * FROM [publicdata:samples.nope]", project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') def test_download_dataset_larger_than_200k_rows(self, project_id): test_size = 200005 @@ -380,7 +409,8 @@ def test_download_dataset_larger_than_200k_rows(self, project_id): "GROUP EACH BY id ORDER BY id ASC LIMIT {0}" .format(test_size), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert len(df.drop_duplicates()) == test_size def test_zero_rows(self, project_id): @@ -390,7 +420,8 @@ def test_zero_rows(self, project_id): "FROM [publicdata:samples.wikipedia] " "WHERE timestamp=-9999999", project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') page_array = np.zeros( (0,), dtype=[('title', object), ('id', np.dtype(int)), ('is_bot', np.dtype(bool)), ('ts', 'M8[ns]')]) @@ -420,10 +451,11 @@ def test_standard_sql(self, project_id): "`publicdata.samples.wikipedia` LIMIT 10" # Test that a standard sql statement fails when using - # the legacy SQL dialect (default value) + # the legacy SQL dialect. with pytest.raises(gbq.GenericGBQException): gbq.read_gbq(standard_sql, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') # Test that a standard sql statement succeeds when # setting dialect='standard' @@ -432,21 +464,6 @@ def test_standard_sql(self, project_id): private_key=self.credentials) assert len(df.drop_duplicates()) == 10 - def test_invalid_option_for_sql_dialect(self, project_id): - sql_statement = "SELECT DISTINCT id FROM " \ - "`publicdata.samples.wikipedia` LIMIT 10" - - # Test that an invalid option for `dialect` raises ValueError - with pytest.raises(ValueError): - gbq.read_gbq(sql_statement, project_id=project_id, - dialect='invalid', - private_key=self.credentials) - - # Test that a correct option for dialect succeeds - # to make sure ValueError was due to invalid dialect - gbq.read_gbq(sql_statement, project_id=project_id, - dialect='standard', private_key=self.credentials) - def test_query_with_parameters(self, project_id): sql_statement = "SELECT @param1 + @param2 AS valid_result" config = { @@ -479,13 +496,15 @@ def test_query_with_parameters(self, project_id): # when parameters are not supplied via configuration with pytest.raises(ValueError): gbq.read_gbq(sql_statement, project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') # Test that the query is successful because we have supplied # the correct query parameters via the 'config' option df = gbq.read_gbq(sql_statement, project_id=project_id, private_key=self.credentials, - configuration=config) + configuration=config, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'valid_result': [3]})) def test_query_inside_configuration(self, project_id): @@ -502,11 +521,13 @@ def test_query_inside_configuration(self, project_id): with pytest.raises(ValueError): gbq.read_gbq(query_no_use, project_id=project_id, private_key=self.credentials, - configuration=config) + configuration=config, + dialect='legacy') df = gbq.read_gbq(None, project_id=project_id, private_key=self.credentials, - configuration=config) + configuration=config, + dialect='legacy') tm.assert_frame_equal(df, DataFrame({'valid_string': ['PI']})) def test_configuration_without_query(self, project_id): @@ -530,7 +551,8 @@ def test_configuration_without_query(self, project_id): with pytest.raises(ValueError): gbq.read_gbq(sql_statement, project_id=project_id, private_key=self.credentials, - configuration=config) + configuration=config, + dialect='legacy') def test_configuration_raises_value_error_with_multiple_config( self, project_id): @@ -549,7 +571,8 @@ def test_configuration_raises_value_error_with_multiple_config( with pytest.raises(ValueError): gbq.read_gbq(sql_statement, project_id=project_id, private_key=self.credentials, - configuration=config) + configuration=config, + dialect='legacy') def test_timeout_configuration(self, project_id): sql_statement = 'SELECT 1' @@ -562,7 +585,8 @@ def test_timeout_configuration(self, project_id): with pytest.raises(gbq.QueryTimeout): gbq.read_gbq(sql_statement, project_id=project_id, private_key=self.credentials, - configuration=config) + configuration=config, + dialect='legacy') def test_query_response_bytes(self): assert self.gbq_connector.sizeof_fmt(999) == "999.0 B" @@ -689,7 +713,8 @@ def test_upload_data(self, project_id): result = gbq.read_gbq("SELECT COUNT(*) AS num_rows FROM {0}" .format(self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert result['num_rows'][0] == test_size def test_upload_data_if_table_exists_fail(self, project_id): @@ -725,7 +750,8 @@ def test_upload_data_if_table_exists_append(self, project_id): result = gbq.read_gbq("SELECT COUNT(*) AS num_rows FROM {0}" .format(self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert result['num_rows'][0] == test_size * 2 # Try inserting with a different schema, confirm failure @@ -754,7 +780,8 @@ def test_upload_subset_columns_if_table_exists_append(self, project_id): result = gbq.read_gbq("SELECT COUNT(*) AS num_rows FROM {0}" .format(self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert result['num_rows'][0] == test_size * 2 def test_upload_data_if_table_exists_replace(self, project_id): @@ -775,7 +802,8 @@ def test_upload_data_if_table_exists_replace(self, project_id): result = gbq.read_gbq("SELECT COUNT(*) AS num_rows FROM {0}" .format(self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert result['num_rows'][0] == 5 def test_upload_data_if_table_exists_raises_value_error(self, project_id): @@ -818,7 +846,8 @@ def test_upload_chinese_unicode_data(self, project_id): result_df = gbq.read_gbq( "SELECT * FROM {0}".format(self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert len(result_df) == test_size @@ -851,7 +880,8 @@ def test_upload_other_unicode_data(self, project_id): result_df = gbq.read_gbq("SELECT * FROM {0}".format( self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert len(result_df) == test_size @@ -879,10 +909,11 @@ def test_upload_mixed_float_and_int(self, project_id): project_id=project_id, private_key=self.credentials) - result_df = gbq.read_gbq("SELECT * FROM {0}".format( - self.destination_table + test_id), + result_df = gbq.read_gbq( + 'SELECT * FROM {0}'.format(self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert len(result_df) == test_size @@ -1173,10 +1204,11 @@ def test_upload_data_with_timestamp(self, project_id): project_id=project_id, private_key=self.credentials) - result_df = gbq.read_gbq("SELECT * FROM {0}".format( - self.destination_table + test_id), + result_df = gbq.read_gbq( + 'SELECT * FROM {0}'.format(self.destination_table + test_id), project_id=project_id, - private_key=self.credentials) + private_key=self.credentials, + dialect='legacy') assert len(result_df) == test_size diff --git a/tests/unit/test_gbq.py b/tests/unit/test_gbq.py index d3560450..f308d9f4 100644 --- a/tests/unit/test_gbq.py +++ b/tests/unit/test_gbq.py @@ -190,12 +190,12 @@ def test_read_gbq_with_no_project_id_given_should_fail(monkeypatch): auth, 'get_application_default_credentials', mock_none_credentials) with pytest.raises(ValueError) as exception: - gbq.read_gbq('SELECT 1') + gbq.read_gbq('SELECT 1', dialect='standard') assert 'Could not determine project ID' in str(exception) def test_read_gbq_with_inferred_project_id(monkeypatch): - df = gbq.read_gbq('SELECT 1') + df = gbq.read_gbq('SELECT 1', dialect='standard') assert df is not None @@ -214,32 +214,35 @@ def test_that_parse_data_works_properly(): def test_read_gbq_with_invalid_private_key_json_should_fail(): with pytest.raises(pandas_gbq.exceptions.InvalidPrivateKeyFormat): - gbq.read_gbq('SELECT 1', project_id='x', private_key='y') + gbq.read_gbq( + 'SELECT 1', dialect='standard', project_id='x', private_key='y') def test_read_gbq_with_empty_private_key_json_should_fail(): with pytest.raises(pandas_gbq.exceptions.InvalidPrivateKeyFormat): - gbq.read_gbq('SELECT 1', project_id='x', private_key='{}') + gbq.read_gbq( + 'SELECT 1', dialect='standard', project_id='x', private_key='{}') def test_read_gbq_with_private_key_json_wrong_types_should_fail(): with pytest.raises(pandas_gbq.exceptions.InvalidPrivateKeyFormat): gbq.read_gbq( - 'SELECT 1', project_id='x', + 'SELECT 1', dialect='standard', project_id='x', private_key='{ "client_email" : 1, "private_key" : True }') def test_read_gbq_with_empty_private_key_file_should_fail(): with tm.ensure_clean() as empty_file_path: with pytest.raises(pandas_gbq.exceptions.InvalidPrivateKeyFormat): - gbq.read_gbq('SELECT 1', project_id='x', + gbq.read_gbq('SELECT 1', dialect='standard', project_id='x', private_key=empty_file_path) def test_read_gbq_with_corrupted_private_key_json_should_fail(): with pytest.raises(pandas_gbq.exceptions.InvalidPrivateKeyFormat): gbq.read_gbq( - 'SELECT 1', project_id='x', private_key='99999999999999999') + 'SELECT 1', dialect='standard', project_id='x', + private_key='99999999999999999') def test_read_gbq_with_verbose_new_pandas_warns_deprecation(min_bq_version): @@ -272,7 +275,7 @@ def test_read_gbq_wo_verbose_w_new_pandas_no_warnings(recwarn, min_bq_version): 'pkg_resources.Distribution.parsed_version', new_callable=mock.PropertyMock) as mock_version: mock_version.side_effect = [min_bq_version, pandas_version] - gbq.read_gbq('SELECT 1', project_id='my-project') + gbq.read_gbq('SELECT 1', project_id='my-project', dialect='standard') assert len(recwarn) == 0 @@ -283,10 +286,23 @@ def test_read_gbq_with_verbose_old_pandas_no_warnings(recwarn, min_bq_version): 'pkg_resources.Distribution.parsed_version', new_callable=mock.PropertyMock) as mock_version: mock_version.side_effect = [min_bq_version, pandas_version] - gbq.read_gbq('SELECT 1', project_id='my-project', verbose=True) + gbq.read_gbq( + 'SELECT 1', project_id='my-project', dialect='standard', + verbose=True) assert len(recwarn) == 0 +def test_read_gbq_with_invalid_dialect(): + with pytest.raises(ValueError) as excinfo: + gbq.read_gbq('SELECT 1', dialect='invalid') + assert 'is not valid for dialect' in str(excinfo.value) + + +def test_read_gbq_without_dialect_warns_future_change(): + with pytest.warns(FutureWarning): + gbq.read_gbq('SELECT 1') + + def test_generate_bq_schema_deprecated(): # 11121 Deprecation of generate_bq_schema with pytest.warns(FutureWarning):