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