diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 30281c3d..ffa62f1a 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -1,6 +1,12 @@ Changelog ========= +0.4.1 / 2018-04-05 +------------------ + +- Only show ``verbose`` deprecation warning if Pandas version does not + populate it. (:issue:`157`) + 0.4.0 / 2018-04-03 ------------------ diff --git a/pandas_gbq/gbq.py b/pandas_gbq/gbq.py index cca6d211..f8bbaf22 100644 --- a/pandas_gbq/gbq.py +++ b/pandas_gbq/gbq.py @@ -14,10 +14,11 @@ BIGQUERY_INSTALLED_VERSION = None +SHOW_VERBOSE_DEPRECATION = False def _check_google_client_version(): - global BIGQUERY_INSTALLED_VERSION + global BIGQUERY_INSTALLED_VERSION, SHOW_VERBOSE_DEPRECATION try: import pkg_resources @@ -36,6 +37,14 @@ def _check_google_client_version(): 'current version {1}'.format( bigquery_minimum_version, BIGQUERY_INSTALLED_VERSION)) + # Add check for Pandas version before showing deprecation warning. + # https://github.com/pydata/pandas-gbq/issues/157 + pandas_installed_version = pkg_resources.get_distribution( + 'pandas').parsed_version + pandas_version_wo_verbosity = pkg_resources.parse_version('0.23.0') + SHOW_VERBOSE_DEPRECATION = ( + pandas_installed_version >= pandas_version_wo_verbosity) + def _test_google_api_imports(): @@ -791,14 +800,15 @@ def read_gbq(query, project_id=None, index_col=None, col_order=None, DataFrame representing results of query """ - if verbose is not None: + + _test_google_api_imports() + + if verbose is not None and SHOW_VERBOSE_DEPRECATION: warnings.warn( "verbose is deprecated and will be removed in " "a future version. Set logging level in order to vary " "verbosity", FutureWarning, stacklevel=1) - _test_google_api_imports() - if not project_id: raise TypeError("Missing required parameter: project_id") @@ -920,7 +930,7 @@ def to_gbq(dataframe, destination_table, project_id, chunksize=None, _test_google_api_imports() - if verbose is not None: + if verbose is not None and SHOW_VERBOSE_DEPRECATION: warnings.warn( "verbose is deprecated and will be removed in " "a future version. Set logging level in order to vary " diff --git a/pandas_gbq/tests/test_gbq.py b/pandas_gbq/tests/test_gbq.py index abb670ef..93c48b0c 100644 --- a/pandas_gbq/tests/test_gbq.py +++ b/pandas_gbq/tests/test_gbq.py @@ -282,8 +282,40 @@ def test_get_user_account_credentials_returns_credentials(self): class TestGBQUnit(object): - def test_should_return_credentials_path_set_by_env_var(self): + @pytest.fixture(autouse=True) + def mock_bigquery_client(self, monkeypatch): + import google.cloud.bigquery + import google.cloud.bigquery.table + mock_client = mock.create_autospec(google.cloud.bigquery.Client) + # Mock out SELECT 1 query results. + mock_query = mock.create_autospec(google.cloud.bigquery.QueryJob) + mock_query.state = 'DONE' + mock_rows = mock.create_autospec( + google.cloud.bigquery.table.RowIterator) + mock_rows.total_rows = 1 + mock_rows.schema = [ + google.cloud.bigquery.SchemaField('_f0', 'INTEGER')] + mock_rows.__iter__.return_value = [(1,)] + mock_query.result.return_value = mock_rows + mock_client.query.return_value = mock_query + monkeypatch.setattr( + gbq.GbqConnector, 'get_client', lambda _: mock_client) + + @pytest.fixture(autouse=True) + def no_auth(self, monkeypatch): + import google.auth.credentials + mock_credentials = mock.create_autospec( + google.auth.credentials.Credentials) + monkeypatch.setattr( + gbq.GbqConnector, + 'get_application_default_credentials', + lambda _: mock_credentials) + monkeypatch.setattr( + gbq.GbqConnector, + 'get_user_account_credentials', + lambda _: mock_credentials) + def test_should_return_credentials_path_set_by_env_var(self): env = {'PANDAS_GBQ_CREDENTIALS_FILE': '/tmp/dummy.dat'} with mock.patch.dict('os.environ', env): assert gbq._get_credentials_file() == '/tmp/dummy.dat' @@ -314,6 +346,75 @@ def test_to_gbq_with_no_project_id_given_should_fail(self): with pytest.raises(TypeError): gbq.to_gbq(DataFrame(), 'dataset.tablename') + def test_to_gbq_with_verbose_new_pandas_warns_deprecation(self): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.23.0') + with pytest.warns(FutureWarning), \ + mock.patch( + 'pkg_resources.Distribution.parsed_version', + new_callable=mock.PropertyMock) as mock_version: + mock_version.side_effect = [min_bq_version, pandas_version] + try: + gbq.to_gbq( + DataFrame(), + 'dataset.tablename', + project_id='my-project', + verbose=True) + except gbq.TableCreationError: + pass + + def test_to_gbq_with_not_verbose_new_pandas_warns_deprecation(self): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.23.0') + with pytest.warns(FutureWarning), \ + mock.patch( + 'pkg_resources.Distribution.parsed_version', + new_callable=mock.PropertyMock) as mock_version: + mock_version.side_effect = [min_bq_version, pandas_version] + try: + gbq.to_gbq( + DataFrame(), + 'dataset.tablename', + project_id='my-project', + verbose=False) + except gbq.TableCreationError: + pass + + def test_to_gbq_wo_verbose_w_new_pandas_no_warnings(self, recwarn): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.23.0') + with mock.patch( + 'pkg_resources.Distribution.parsed_version', + new_callable=mock.PropertyMock) as mock_version: + mock_version.side_effect = [min_bq_version, pandas_version] + try: + gbq.to_gbq( + DataFrame(), 'dataset.tablename', project_id='my-project') + except gbq.TableCreationError: + pass + assert len(recwarn) == 0 + + def test_to_gbq_with_verbose_old_pandas_no_warnings(self, recwarn): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.22.0') + with mock.patch( + 'pkg_resources.Distribution.parsed_version', + new_callable=mock.PropertyMock) as mock_version: + mock_version.side_effect = [min_bq_version, pandas_version] + try: + gbq.to_gbq( + DataFrame(), + 'dataset.tablename', + project_id='my-project', + verbose=True) + except gbq.TableCreationError: + pass + assert len(recwarn) == 0 + def test_read_gbq_with_no_project_id_given_should_fail(self): with pytest.raises(TypeError): gbq.read_gbq('SELECT 1') @@ -359,6 +460,50 @@ def test_read_gbq_with_corrupted_private_key_json_should_fail(self): 'SELECT 1', project_id='x', private_key=re.sub('[a-z]', '9', _get_private_key_contents())) + def test_read_gbq_with_verbose_new_pandas_warns_deprecation(self): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.23.0') + with pytest.warns(FutureWarning), \ + mock.patch( + '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) + + def test_read_gbq_with_not_verbose_new_pandas_warns_deprecation(self): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.23.0') + with pytest.warns(FutureWarning), \ + mock.patch( + '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=False) + + def test_read_gbq_wo_verbose_w_new_pandas_no_warnings(self, recwarn): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.23.0') + with mock.patch( + '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') + assert len(recwarn) == 0 + + def test_read_gbq_with_verbose_old_pandas_no_warnings(self, recwarn): + import pkg_resources + min_bq_version = pkg_resources.parse_version('0.29.0') + pandas_version = pkg_resources.parse_version('0.22.0') + with mock.patch( + '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) + assert len(recwarn) == 0 + def test_should_read(project, credentials):