From 5004d08c6af93471686ccb319c69cd38c7893042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Thu, 12 Dec 2024 15:38:50 -0600 Subject: [PATCH] feat: `to_gbq` fails with `TypeError` if passing in a bigframes DataFrame object (#833) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: `to_gbq` fails with `TypeError` if passing in a bigframes DataFrame object * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- pandas_gbq/gbq.py | 8 ++++++++ tests/unit/test_to_gbq.py | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/pandas_gbq/gbq.py b/pandas_gbq/gbq.py index b04ad131..feffd858 100644 --- a/pandas_gbq/gbq.py +++ b/pandas_gbq/gbq.py @@ -1091,6 +1091,14 @@ def to_gbq( .. versionadded:: 0.23.3 """ + # If we get a bigframes.pandas.DataFrame object, it may be possible to use + # the code paths here, but it could potentially be quite expensive because + # of the queries involved in type detection. It would be safer just to + # fail early if there are bigframes-y methods available. + # https://github.com/googleapis/python-bigquery-pandas/issues/824 + if hasattr(dataframe, "to_pandas") and hasattr(dataframe, "to_gbq"): + raise TypeError(f"Expected a pandas.DataFrame, but got {repr(type(dataframe))}") + _test_google_api_imports() from google.api_core import exceptions as google_exceptions diff --git a/tests/unit/test_to_gbq.py b/tests/unit/test_to_gbq.py index 60ea8025..f4012dc8 100644 --- a/tests/unit/test_to_gbq.py +++ b/tests/unit/test_to_gbq.py @@ -11,6 +11,16 @@ from pandas_gbq import gbq +class FakeDataFrame: + """A fake bigframes DataFrame to avoid depending on bigframes.""" + + def to_gbq(self): + """Fake to_gbq() to mimic a bigframes object.""" + + def to_pandas(self): + """Fake to_pandas() to mimic a bigframes object.""" + + @pytest.fixture def expected_load_method(mock_bigquery_client): return mock_bigquery_client.load_table_from_dataframe @@ -66,6 +76,15 @@ def test_to_gbq_load_method_translates_exception( expected_load_method.assert_called_once() +def test_to_gbq_with_bigframes_raises_typeerror(): + dataframe = FakeDataFrame() + + with pytest.raises( + TypeError, match=r"Expected a pandas.DataFrame, but got .+FakeDataFrame" + ): + gbq.to_gbq(dataframe, "my_dataset.my_table", project_id="myproj") + + def test_to_gbq_with_if_exists_append(mock_bigquery_client, expected_load_method): from google.cloud.bigquery import SchemaField