diff --git a/bigframes/display/html.py b/bigframes/display/html.py index ef34985c8e..4d439ff2d8 100644 --- a/bigframes/display/html.py +++ b/bigframes/display/html.py @@ -361,7 +361,7 @@ def repr_mimebundle( if opts.repr_mode == "deferred": return repr_mimebundle_deferred(obj) - if opts.repr_mode == "anywidget": + if opts.render_mode == "anywidget" or opts.repr_mode == "anywidget": try: with bigframes.option_context("display.progress_bar", None): with warnings.catch_warnings(): @@ -380,4 +380,8 @@ def repr_mimebundle( f"Falling back to static HTML. Error: {traceback.format_exc()}" ) - return repr_mimebundle_head(obj) + bundle = repr_mimebundle_head(obj) + if opts.render_mode == "plaintext": + bundle.pop("text/html", None) + + return bundle diff --git a/notebooks/dataframes/anywidget_mode.ipynb b/notebooks/dataframes/anywidget_mode.ipynb index e9491610ac..a0efa571a7 100644 --- a/notebooks/dataframes/anywidget_mode.ipynb +++ b/notebooks/dataframes/anywidget_mode.ipynb @@ -63,7 +63,7 @@ "outputs": [], "source": [ "bpd.options.bigquery.ordering_mode = \"partial\"\n", - "bpd.options.display.repr_mode = \"anywidget\"" + "bpd.options.display.render_mode = \"anywidget\"" ] }, { @@ -89,20 +89,10 @@ "id": "f289d250", "metadata": {}, "outputs": [ - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "data": { "text/html": [ - "✅ Completed. \n", + "\n", " Query processed 0 Bytes in a moment of slot time.\n", " " ], @@ -117,17 +107,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "state gender year name number\n", - " AL F 1910 Lillian 99\n", - " AL F 1910 Ruby 204\n", - " AL F 1910 Helen 76\n", - " AL F 1910 Eunice 41\n", - " AR F 1910 Dora 42\n", - " CA F 1910 Edna 62\n", - " CA F 1910 Helen 239\n", - " CO F 1910 Alice 46\n", - " FL F 1910 Willie 71\n", - " FL F 1910 Thelma 65\n", + "state gender year name number\n", + " AL F 1910 Cora 61\n", + " AL F 1910 Anna 74\n", + " AR F 1910 Willie 132\n", + " CO F 1910 Anna 42\n", + " FL F 1910 Louise 70\n", + " GA F 1910 Catherine 57\n", + " IL F 1910 Jessie 43\n", + " IN F 1910 Anna 100\n", + " IN F 1910 Pauline 77\n", + " IN F 1910 Beulah 39\n", "...\n", "\n", "[5552452 rows x 5 columns]\n" @@ -145,30 +135,10 @@ "id": "220340b0", "metadata": {}, "outputs": [ - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6fb22be7f21f4d1dacd76dc62a1a7818", + "model_id": "d75a0d81724f4776ae1a592369e78946", "version_major": 2, "version_minor": 1 }, @@ -204,80 +174,80 @@ " AL\n", " F\n", " 1910\n", - " Lillian\n", - " 99\n", + " Annie\n", + " 482\n", " \n", " \n", " 1\n", " AL\n", " F\n", " 1910\n", - " Ruby\n", - " 204\n", + " Myrtle\n", + " 104\n", " \n", " \n", " 2\n", - " AL\n", + " AR\n", " F\n", " 1910\n", - " Helen\n", - " 76\n", + " Lillian\n", + " 56\n", " \n", " \n", " 3\n", - " AL\n", + " CT\n", " F\n", " 1910\n", - " Eunice\n", - " 41\n", + " Anne\n", + " 38\n", " \n", " \n", " 4\n", - " AR\n", + " CT\n", " F\n", " 1910\n", - " Dora\n", - " 42\n", + " Frances\n", + " 45\n", " \n", " \n", " 5\n", - " CA\n", + " FL\n", " F\n", " 1910\n", - " Edna\n", - " 62\n", + " Margaret\n", + " 53\n", " \n", " \n", " 6\n", - " CA\n", + " GA\n", " F\n", " 1910\n", - " Helen\n", - " 239\n", + " Mae\n", + " 73\n", " \n", " \n", " 7\n", - " CO\n", + " GA\n", " F\n", " 1910\n", - " Alice\n", - " 46\n", + " Beatrice\n", + " 96\n", " \n", " \n", " 8\n", - " FL\n", + " GA\n", " F\n", " 1910\n", - " Willie\n", - " 71\n", + " Lola\n", + " 47\n", " \n", " \n", " 9\n", - " FL\n", + " IA\n", " F\n", " 1910\n", - " Thelma\n", - " 65\n", + " Viola\n", + " 49\n", " \n", " \n", "\n", @@ -285,17 +255,17 @@ "[5552452 rows x 5 columns in total]" ], "text/plain": [ - "state gender year name number\n", - " AL F 1910 Lillian 99\n", - " AL F 1910 Ruby 204\n", - " AL F 1910 Helen 76\n", - " AL F 1910 Eunice 41\n", - " AR F 1910 Dora 42\n", - " CA F 1910 Edna 62\n", - " CA F 1910 Helen 239\n", - " CO F 1910 Alice 46\n", - " FL F 1910 Willie 71\n", - " FL F 1910 Thelma 65\n", + "state gender year name number\n", + " AL F 1910 Annie 482\n", + " AL F 1910 Myrtle 104\n", + " AR F 1910 Lillian 56\n", + " CT F 1910 Anne 38\n", + " CT F 1910 Frances 45\n", + " FL F 1910 Margaret 53\n", + " GA F 1910 Mae 73\n", + " GA F 1910 Beatrice 96\n", + " GA F 1910 Lola 47\n", + " IA F 1910 Viola 49\n", "...\n", "\n", "[5552452 rows x 5 columns]" @@ -328,8 +298,8 @@ { "data": { "text/html": [ - "✅ Completed. \n", - " Query processed 171.4 MB in 41 seconds of slot time. [Job bigframes-dev:US.492b5260-9f44-495c-be09-2ae1324a986c details]\n", + "\n", + " Query processed 171.4 MB in 46 seconds of slot time. [Job bigframes-dev:US.dcf260e0-eaad-4979-9ec6-12f2436698e4 details]\n", " " ], "text/plain": [ @@ -342,7 +312,7 @@ { "data": { "text/html": [ - "✅ Completed. \n", + "\n", " Query processed 88.8 MB in a moment of slot time.\n", " " ], @@ -353,16 +323,6 @@ "metadata": {}, "output_type": "display_data" }, - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "name": "stdout", "output_type": "stream", @@ -404,38 +364,10 @@ "id": "da23e0f3", "metadata": {}, "outputs": [ - { - "data": { - "text/html": [ - "✅ Completed. \n", - " Query processed 88.8 MB in 2 seconds of slot time. [Job bigframes-dev:US.job_gsx0h2jHoOSYwqGKUS3lAYLf_qi3 details]\n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "✅ Completed. \n", - " Query processed 88.8 MB in 3 seconds of slot time. [Job bigframes-dev:US.job_1VivAJ2InPdg5RXjWfvAJ1B0oxO3 details]\n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "7d82208e7e5e40dd9dbf64c4c561cab3", + "model_id": "8e1b0e50cacb4315a231913b321cff55", "version_major": 2, "version_minor": 1 }, @@ -533,34 +465,6 @@ "id": "6920d49b", "metadata": {}, "outputs": [ - { - "data": { - "text/html": [ - "✅ Completed. \n", - " Query processed 215.9 MB in 10 seconds of slot time. [Job bigframes-dev:US.job_cmNyG5sJ1IDCyFINx7teExQOZ6UQ details]\n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "✅ Completed. \n", - " Query processed 215.9 MB in 8 seconds of slot time. [Job bigframes-dev:US.job_aQvP3Sn04Ss4flSLaLhm0sKzFvrd details]\n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "name": "stdout", "output_type": "stream", @@ -571,12 +475,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "52d11291ba1d42e6b544acbd86eef6cf", + "model_id": "b7f188a72de440359e402d8e41de26a9", "version_major": 2, "version_minor": 1 }, "text/plain": [ - "" + "" ] }, "execution_count": 8, @@ -648,34 +552,6 @@ "id": "a9d5d13a", "metadata": {}, "outputs": [ - { - "data": { - "text/html": [ - "✅ Completed. \n", - " Query processed 215.9 MB in a moment of slot time.\n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "✅ Completed. \n", - " Query processed 215.9 MB in a moment of slot time.\n", - " " - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, { "name": "stdout", "output_type": "stream", @@ -686,12 +562,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "32c61c84740d45a0ac37202a76c7c14e", + "model_id": "cf507362c97b4ccf9084997d03d65290", "version_major": 2, "version_minor": 1 }, "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -734,8 +610,8 @@ { "data": { "text/html": [ - "✅ Completed. \n", - " Query processed 85.9 kB in 21 seconds of slot time.\n", + "\n", + " Query processed 85.9 kB in 28 seconds of slot time.\n", " " ], "text/plain": [ @@ -745,54 +621,10 @@ "metadata": {}, "output_type": "display_data" }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/usr/local/google/home/shuowei/src/python-bigquery-dataframes/bigframes/dtypes.py:987: JSONDtypeWarning: JSON columns will be represented as pandas.ArrowDtype(pyarrow.json_())\n", - "instead of using `db_dtypes` in the future when available in pandas\n", - "(https://github.com/pandas-dev/pandas/issues/60958) and pyarrow.\n", - " warnings.warn(msg, bigframes.exceptions.JSONDtypeWarning)\n" - ] - }, - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/usr/local/google/home/shuowei/src/python-bigquery-dataframes/bigframes/dtypes.py:987: JSONDtypeWarning: JSON columns will be represented as pandas.ArrowDtype(pyarrow.json_())\n", - "instead of using `db_dtypes` in the future when available in pandas\n", - "(https://github.com/pandas-dev/pandas/issues/60958) and pyarrow.\n", - " warnings.warn(msg, bigframes.exceptions.JSONDtypeWarning)\n", - "/usr/local/google/home/shuowei/src/python-bigquery-dataframes/bigframes/dtypes.py:987: JSONDtypeWarning: JSON columns will be represented as pandas.ArrowDtype(pyarrow.json_())\n", - "instead of using `db_dtypes` in the future when available in pandas\n", - "(https://github.com/pandas-dev/pandas/issues/60958) and pyarrow.\n", - " warnings.warn(msg, bigframes.exceptions.JSONDtypeWarning)\n" - ] - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "9d60a47296214553bb10c434b5ee8330", + "model_id": "b9dd4b812443455ba32ec71723331a10", "version_major": 2, "version_minor": 1 }, @@ -858,16 +690,16 @@ " EU\n", " DE\n", " 03.10.2018\n", - " H05B 6/12\n", - " <NA>\n", - " 18165514.3\n", - " 03.04.2018\n", - " 30.03.2017\n", + " G06F 11/30\n", " <NA>\n", - " BSH Hausger√§te GmbH\n", - " Acero Acero, Jesus\n", - " VORRICHTUNG ZUR INDUKTIVEN ENERGIE√úBERTRAGUNG\n", - " EP 3 383 141 A2\n", + " 18157347.8\n", + " 19.02.2018\n", + " 31.03.2017\n", + " Hoffmann Eitle\n", + " FUJITSU LIMITED\n", + " Kukihara, Kensuke\n", + " METHOD EXECUTED BY A COMPUTER, INFORMATION PRO...\n", + " EP 3 382 553 A1\n", " \n", " \n", " 2\n", @@ -876,16 +708,16 @@ " EU\n", " DE\n", " 03.10.2018\n", - " H01L 21/20\n", - " <NA>\n", - " 18166536.5\n", - " 16.02.2016\n", + " A01K 31/00\n", " <NA>\n", - " Scheider, Sascha et al\n", - " EV Group E. Thallner GmbH\n", - " Kurz, Florian\n", - " VORRICHTUNG ZUM BONDEN VON SUBSTRATEN\n", - " EP 3 382 744 A1\n", + " 18171005.4\n", + " 05.02.2015\n", + " 05.02.2014\n", + " Stork Bamberger Patentanw√§lte\n", + " Linco Food Systems A/S\n", + " Thrane, Uffe\n", + " MASTH√ÑHNCHENCONTAINER ALS BESTANDTEIL EINER E...\n", + " EP 3 381 276 A1\n", " \n", " \n", " 3\n", @@ -894,16 +726,16 @@ " EU\n", " DE\n", " 03.10.2018\n", - " G06F 11/30\n", + " H05B 6/12\n", " <NA>\n", - " 18157347.8\n", - " 19.02.2018\n", - " 31.03.2017\n", - " Hoffmann Eitle\n", - " FUJITSU LIMITED\n", - " Kukihara, Kensuke\n", - " METHOD EXECUTED BY A COMPUTER, INFORMATION PRO...\n", - " EP 3 382 553 A1\n", + " 18165514.3\n", + " 03.04.2018\n", + " 30.03.2017\n", + " <NA>\n", + " BSH Hausger√§te GmbH\n", + " Acero Acero, Jesus\n", + " VORRICHTUNG ZUR INDUKTIVEN ENERGIE√úBERTRAGUNG\n", + " EP 3 383 141 A2\n", " \n", " \n", " 4\n", @@ -912,16 +744,16 @@ " EU\n", " DE\n", " 03.10.2018\n", - " A01K 31/00\n", + " H01L 21/20\n", " <NA>\n", - " 18171005.4\n", - " 05.02.2015\n", - " 05.02.2014\n", - " Stork Bamberger Patentanw√§lte\n", - " Linco Food Systems A/S\n", - " Thrane, Uffe\n", - " MASTH√ÑHNCHENCONTAINER ALS BESTANDTEIL EINER E...\n", - " EP 3 381 276 A1\n", + " 18166536.5\n", + " 16.02.2016\n", + " <NA>\n", + " Scheider, Sascha et al\n", + " EV Group E. Thallner GmbH\n", + " Kurz, Florian\n", + " VORRICHTUNG ZUM BONDEN VON SUBSTRATEN\n", + " EP 3 382 744 A1\n", " \n", " \n", "\n", @@ -945,31 +777,31 @@ "\n", " publication_date class_international class_us application_number \\\n", "0 29.08.018 E04H 6/12 18157874.1 \n", - "1 03.10.2018 H05B 6/12 18165514.3 \n", - "2 03.10.2018 H01L 21/20 18166536.5 \n", - "3 03.10.2018 G06F 11/30 18157347.8 \n", - "4 03.10.2018 A01K 31/00 18171005.4 \n", + "1 03.10.2018 G06F 11/30 18157347.8 \n", + "2 03.10.2018 A01K 31/00 18171005.4 \n", + "3 03.10.2018 H05B 6/12 18165514.3 \n", + "4 03.10.2018 H01L 21/20 18166536.5 \n", "\n", " filing_date priority_date_eu representative_line_1_eu \\\n", "0 21.02.2018 22.02.2017 Liedtke & Partner Patentanw√§lte \n", - "1 03.04.2018 30.03.2017 \n", - "2 16.02.2016 Scheider, Sascha et al \n", - "3 19.02.2018 31.03.2017 Hoffmann Eitle \n", - "4 05.02.2015 05.02.2014 Stork Bamberger Patentanw√§lte \n", + "1 19.02.2018 31.03.2017 Hoffmann Eitle \n", + "2 05.02.2015 05.02.2014 Stork Bamberger Patentanw√§lte \n", + "3 03.04.2018 30.03.2017 \n", + "4 16.02.2016 Scheider, Sascha et al \n", "\n", " applicant_line_1 inventor_line_1 \\\n", "0 SHB Hebezeugbau GmbH VOLGER, Alexander \n", - "1 BSH Hausger√§te GmbH Acero Acero, Jesus \n", - "2 EV Group E. Thallner GmbH Kurz, Florian \n", - "3 FUJITSU LIMITED Kukihara, Kensuke \n", - "4 Linco Food Systems A/S Thrane, Uffe \n", + "1 FUJITSU LIMITED Kukihara, Kensuke \n", + "2 Linco Food Systems A/S Thrane, Uffe \n", + "3 BSH Hausger√§te GmbH Acero Acero, Jesus \n", + "4 EV Group E. Thallner GmbH Kurz, Florian \n", "\n", " title_line_1 number \n", "0 STEUERUNGSSYSTEM F√úR AUTOMATISCHE PARKH√ÑUSER EP 3 366 869 A1 \n", - "1 VORRICHTUNG ZUR INDUKTIVEN ENERGIE√úBERTRAGUNG EP 3 383 141 A2 \n", - "2 VORRICHTUNG ZUM BONDEN VON SUBSTRATEN EP 3 382 744 A1 \n", - "3 METHOD EXECUTED BY A COMPUTER, INFORMATION PRO... EP 3 382 553 A1 \n", - "4 MASTH√ÑHNCHENCONTAINER ALS BESTANDTEIL EINER E... EP 3 381 276 A1 \n", + "1 METHOD EXECUTED BY A COMPUTER, INFORMATION PRO... EP 3 382 553 A1 \n", + "2 MASTH√ÑHNCHENCONTAINER ALS BESTANDTEIL EINER E... EP 3 381 276 A1 \n", + "3 VORRICHTUNG ZUR INDUKTIVEN ENERGIE√úBERTRAGUNG EP 3 383 141 A2 \n", + "4 VORRICHTUNG ZUM BONDEN VON SUBSTRATEN EP 3 382 744 A1 \n", "\n", "[5 rows x 15 columns]" ] @@ -995,7 +827,7 @@ ], "metadata": { "kernelspec": { - "display_name": "venv", + "display_name": "venv (3.13.0)", "language": "python", "name": "python3" }, diff --git a/notebooks/ml/timeseries_analysis.ipynb b/notebooks/ml/timeseries_analysis.ipynb index 01c5a20efa..84959b3632 100644 --- a/notebooks/ml/timeseries_analysis.ipynb +++ b/notebooks/ml/timeseries_analysis.ipynb @@ -12,14 +12,14 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "c0b2db75", "metadata": {}, "outputs": [], "source": [ "import bigframes.pandas as bpd\n", "from bigframes.ml import forecasting\n", - "bpd.options.display.repr_mode = \"anywidget\"" + "bpd.options.display.render_mode = \"anywidget\"" ] }, { @@ -1113,7 +1113,7 @@ ], "metadata": { "kernelspec": { - "display_name": "venv", + "display_name": "venv (3.13.0)", "language": "python", "name": "python3" }, diff --git a/tests/system/small/test_anywidget.py b/tests/system/small/test_anywidget.py index fad8f5b2b5..9716d10d9b 100644 --- a/tests/system/small/test_anywidget.py +++ b/tests/system/small/test_anywidget.py @@ -70,7 +70,7 @@ def table_widget(paginated_bf_df: bigframes.dataframe.DataFrame): from bigframes.display import TableWidget with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): # Delay context manager cleanup of `max_rows` until after tests finish. yield TableWidget(paginated_bf_df) @@ -100,7 +100,7 @@ def small_widget(small_bf_df): """Helper fixture for tests using a DataFrame smaller than the page size.""" from bigframes.display import TableWidget - with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 5): + with bf.option_context("display.render_mode", "anywidget", "display.max_rows", 5): yield TableWidget(small_bf_df) @@ -126,7 +126,9 @@ def unknown_row_count_widget(session): mock_batches.return_value = blocks.PandasBatches( batches_iterator, total_rows=None ) - with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2): + with bf.option_context( + "display.render_mode", "anywidget", "display.max_rows", 2 + ): widget = TableWidget(bf_df) yield widget @@ -206,7 +208,7 @@ def test_widget_initialization_should_calculate_total_row_count( from bigframes.display import TableWidget with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): widget = TableWidget(paginated_bf_df) @@ -316,7 +318,7 @@ def test_widget_pagination_should_work_with_custom_page_size( ): """Test that a widget paginates correctly with a custom page size.""" with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 3 + "display.render_mode", "anywidget", "display.max_rows", 3 ): from bigframes.display import TableWidget @@ -370,7 +372,7 @@ def test_global_options_change_should_not_affect_existing_widget_page_size( then the widget's page size should remain unchanged. """ with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): from bigframes.display import TableWidget @@ -395,7 +397,7 @@ def test_widget_with_empty_dataframe_should_have_zero_row_count( then its row_count should be 0. """ - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): from bigframes.display import TableWidget widget = TableWidget(empty_bf_df) @@ -421,7 +423,7 @@ def test_widget_with_empty_dataframe_should_render_table_headers( """ - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): from bigframes.display import TableWidget @@ -550,7 +552,7 @@ def test_widget_row_count_should_be_immutable_after_creation( # Use a context manager to ensure the option is reset with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): widget = TableWidget(paginated_bf_df) initial_row_count = widget.row_count @@ -585,7 +587,7 @@ def test_widget_should_show_error_on_batch_failure( ) # Create the TableWidget under the error condition. - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): from bigframes.display import TableWidget # The widget should handle the faulty data from the mock without crashing. @@ -609,7 +611,7 @@ def test_widget_row_count_reflects_actual_data_available( # Set up display options that define a page size. with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): widget = TableWidget(paginated_bf_df) @@ -639,7 +641,7 @@ def test_widget_with_unknown_row_count_should_auto_navigate_to_last_page( bf_df = session.read_pandas(test_data) with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): widget = TableWidget(bf_df) @@ -681,7 +683,7 @@ def test_widget_with_unknown_row_count_should_set_none_state_for_frontend( bf_df = session.read_pandas(test_data) with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): widget = TableWidget(bf_df) @@ -718,7 +720,7 @@ def test_widget_with_unknown_row_count_should_allow_forward_navigation( bf_df = session.read_pandas(test_data) with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): widget = TableWidget(bf_df) widget.row_count = None @@ -755,7 +757,7 @@ def test_widget_with_unknown_row_count_empty_dataframe( empty_data = pd.DataFrame(columns=["id", "value"]) bf_df = session.read_pandas(empty_data) - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): widget = TableWidget(bf_df) widget.row_count = None @@ -908,7 +910,7 @@ def test_repr_mimebundle_should_fallback_to_html_if_anywidget_is_unavailable( Test that _repr_mimebundle_ falls back to static html when anywidget is not available. """ with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 2 + "display.render_mode", "anywidget", "display.max_rows", 2 ): # Mock the ANYWIDGET_INSTALLED flag to simulate absence of anywidget with mock.patch("bigframes.display.anywidget._ANYWIDGET_INSTALLED", False): @@ -927,7 +929,7 @@ def test_repr_mimebundle_should_return_widget_view_if_anywidget_is_available( """ Test that _repr_mimebundle_ returns a widget view when anywidget is available. """ - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): bundle = paginated_bf_df._repr_mimebundle_() assert isinstance(bundle, tuple) data, metadata = bundle @@ -943,7 +945,7 @@ def test_repr_in_anywidget_mode_should_not_be_deferred( Test that repr(df) is not deferred in anywidget mode. This is to ensure that print(df) works as expected. """ - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): representation = repr(paginated_bf_df) assert "Computation deferred" not in representation assert "page_1_row_1" in representation @@ -954,7 +956,7 @@ def test_dataframe_repr_mimebundle_should_return_widget_with_metadata_in_anywidg session: bigframes.Session, # Add session as a fixture ): """Test that _repr_mimebundle_ returns a widget view with metadata when anywidget is available.""" - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): # Create a real DataFrame object (or a mock that behaves like one minimally) # for _repr_mimebundle_ to operate on. test_df = bigframes.dataframe.DataFrame( @@ -1051,7 +1053,7 @@ def test_widget_with_default_index_should_display_index_column_with_empty_header from bigframes.display.anywidget import TableWidget - with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2): + with bf.option_context("display.render_mode", "anywidget", "display.max_rows", 2): widget = TableWidget(paginated_bf_df) html = widget.table_html @@ -1075,7 +1077,7 @@ def test_widget_with_custom_index_should_display_index_column( """ from bigframes.display.anywidget import TableWidget - with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2): + with bf.option_context("display.render_mode", "anywidget", "display.max_rows", 2): widget = TableWidget(custom_index_bf_df) html = widget.table_html @@ -1095,7 +1097,7 @@ def test_widget_with_custom_index_pagination_preserves_index( """ from bigframes.display.anywidget import TableWidget - with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2): + with bf.option_context("display.render_mode", "anywidget", "display.max_rows", 2): widget = TableWidget(custom_index_bf_df) widget.page = 1 # Navigate to page 2 @@ -1116,7 +1118,7 @@ def test_widget_with_custom_index_matches_pandas_output( """ from bigframes.display.anywidget import TableWidget - with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 3): + with bf.option_context("display.render_mode", "anywidget", "display.max_rows", 3): widget = TableWidget(custom_index_bf_df) html = widget.table_html @@ -1137,7 +1139,7 @@ def test_series_anywidget_integration_with_notebook_display( """Test Series display integration in Jupyter-like environment.""" pytest.importorskip("anywidget") - with bf.option_context("display.repr_mode", "anywidget"): + with bf.option_context("display.render_mode", "anywidget"): series = paginated_bf_df["value"] # Test the full display pipeline @@ -1162,7 +1164,7 @@ def test_series_different_data_types_anywidget(session: bf.Session): ) bf_df = session.read_pandas(test_data) - with bf.option_context("display.repr_mode", "anywidget"): + with bf.option_context("display.render_mode", "anywidget"): for col_name in test_data.columns: series = bf_df[col_name] widget = bigframes.display.TableWidget(series.to_frame()) diff --git a/tests/system/small/test_progress_bar.py b/tests/system/small/test_progress_bar.py index d726bfde2c..b6b4b795ce 100644 --- a/tests/system/small/test_progress_bar.py +++ b/tests/system/small/test_progress_bar.py @@ -151,7 +151,7 @@ def test_query_job_dry_run_series(penguins_df_default_index: bf.dataframe.DataFr def test_repr_anywidget_dataframe(penguins_df_default_index: bf.dataframe.DataFrame): pytest.importorskip("anywidget") - with bf.option_context("display.repr_mode", "anywidget"): + with bf.option_context("display.render_mode", "anywidget"): actual_repr = repr(penguins_df_default_index) assert "species" in actual_repr assert "island" in actual_repr @@ -160,7 +160,7 @@ def test_repr_anywidget_dataframe(penguins_df_default_index: bf.dataframe.DataFr def test_repr_anywidget_index(penguins_df_default_index: bf.dataframe.DataFrame): pytest.importorskip("anywidget") - with bf.option_context("display.repr_mode", "anywidget"): + with bf.option_context("display.render_mode", "anywidget"): index = penguins_df_default_index.index actual_repr = repr(index) # In non-interactive environments, should still get a useful summary. diff --git a/tests/unit/display/test_anywidget.py b/tests/unit/display/test_anywidget.py index 252ba8100e..d8c8c64ceb 100644 --- a/tests/unit/display/test_anywidget.py +++ b/tests/unit/display/test_anywidget.py @@ -43,7 +43,7 @@ def test_navigation_to_invalid_page_resets_to_valid_page_without_deadlock(): # We mock _initial_load to avoid complex setup with mock.patch.object(TableWidget, "_initial_load"): with bigframes.option_context( - "display.repr_mode", "anywidget", "display.max_rows", 10 + "display.render_mode", "anywidget", "display.max_rows", 10 ): widget = TableWidget(mock_df) @@ -130,7 +130,7 @@ def test_sorting_single_column(mock_df): """Test that the widget can be sorted by a single column.""" from bigframes.display.anywidget import TableWidget - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): widget = TableWidget(mock_df) # Verify initial state @@ -149,7 +149,7 @@ def test_sorting_multi_column(mock_df): """Test that the widget can be sorted by multiple columns.""" from bigframes.display.anywidget import TableWidget - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): widget = TableWidget(mock_df) # Apply multi-column sort @@ -165,7 +165,7 @@ def test_page_size_change_resets_sort(mock_df): """Test that changing the page size resets the sorting.""" from bigframes.display.anywidget import TableWidget - with bigframes.option_context("display.repr_mode", "anywidget"): + with bigframes.option_context("display.render_mode", "anywidget"): widget = TableWidget(mock_df) # Set sort state diff --git a/tests/unit/display/test_render_mode.py b/tests/unit/display/test_render_mode.py new file mode 100644 index 0000000000..3aa418ce3e --- /dev/null +++ b/tests/unit/display/test_render_mode.py @@ -0,0 +1,107 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest.mock as mock + +import bigframes.display.html as bf_html +import bigframes.pandas as bpd + + +def test_render_mode_options(): + assert bpd.options.display.render_mode == "html" + + with bpd.option_context("display.render_mode", "plaintext"): + assert bpd.options.display.render_mode == "plaintext" + + with bpd.option_context("display.render_mode", "html"): + assert bpd.options.display.render_mode == "html" + + with bpd.option_context("display.render_mode", "anywidget"): + assert bpd.options.display.render_mode == "anywidget" + + +def test_repr_mimebundle_selection_logic(): + mock_obj = mock.Mock() + + # Mocking dependencies + with mock.patch( + "bigframes.display.html.repr_mimebundle_head" + ) as mock_head, mock.patch( + "bigframes.display.html.get_anywidget_bundle" + ) as mock_anywidget, mock.patch( + "bigframes.display.html.repr_mimebundle_deferred" + ) as mock_deferred: + + mock_head.side_effect = lambda obj: {"text/plain": "plain", "text/html": "html"} + mock_anywidget.return_value = ( + { + "application/vnd.jupyter.widget-view+json": {}, + "text/plain": "plain", + "text/html": "html", + }, + {}, + ) + mock_deferred.return_value = {"text/plain": "deferred"} + + # Test deferred repr_mode + with bpd.option_context("display.repr_mode", "deferred"): + bundle = bf_html.repr_mimebundle(mock_obj) + assert bundle == {"text/plain": "deferred"} + mock_deferred.assert_called_once() + mock_head.assert_not_called() + + mock_deferred.reset_mock() + + # Test plaintext render_mode + with bpd.option_context("display.render_mode", "plaintext"): + bundle = bf_html.repr_mimebundle(mock_obj) + assert "text/plain" in bundle + assert "text/html" not in bundle + mock_head.assert_called_once() + + mock_head.reset_mock() + + # Test html render_mode + with bpd.option_context("display.render_mode", "html"): + bundle = bf_html.repr_mimebundle(mock_obj) + assert "text/plain" in bundle + assert "text/html" in bundle + mock_head.assert_called_once() + + mock_head.reset_mock() + + # Test anywidget render_mode + with bpd.option_context("display.render_mode", "anywidget"): + bundle = bf_html.repr_mimebundle(mock_obj) + assert "application/vnd.jupyter.widget-view+json" in bundle[0] + mock_anywidget.assert_called_once() + mock_head.assert_not_called() + + mock_anywidget.reset_mock() + + # Test anywidget repr_mode (backward compatibility) + with bpd.option_context("display.repr_mode", "anywidget"): + bundle = bf_html.repr_mimebundle(mock_obj) + assert "application/vnd.jupyter.widget-view+json" in bundle[0] + mock_anywidget.assert_called_once() + mock_head.assert_not_called() + + mock_anywidget.reset_mock() + + # Test default render_mode (should be "html") + bundle = bf_html.repr_mimebundle(mock_obj) + assert "text/plain" in bundle + assert "text/html" in bundle + mock_head.assert_called_once() + mock_anywidget.assert_not_called() diff --git a/third_party/bigframes_vendored/pandas/core/config_init.py b/third_party/bigframes_vendored/pandas/core/config_init.py index 9ffd1ed59f..15425b6a98 100644 --- a/third_party/bigframes_vendored/pandas/core/config_init.py +++ b/third_party/bigframes_vendored/pandas/core/config_init.py @@ -126,12 +126,29 @@ class DisplayOptions: objects can still be computed with methods that explicitly execute and download results. + `anywidget` + Display as interactive widget using `anywidget` library. + **Examples:** >>> import bigframes.pandas as bpd >>> bpd.options.display.repr_mode = "deferred" # doctest: +SKIP """ + render_mode: Literal["plaintext", "html", "anywidget"] = "html" + """ + Determines how to visualize a DataFrame or Series. Default "html". + + `plaintext` + Display as plain text. + + `html` + Display as HTML table. + + `anywidget` + Display as interactive widget using `anywidget` library. + """ + max_colwidth: Optional[int] = 50 """ The maximum width in characters of a column in the repr. Default 50.