Skip to content

Conversation

@shuoweil
Copy link
Contributor

@shuoweil shuoweil commented Oct 4, 2025

Previously, SQL queries in anywidget mode would fall back to deferred execution, showing a dry run instead of an interactive table.

This change enables the display of DataFrames containing JSON columns when using the anywidget representation mode.

Due to a limitation in Apache Arrow (#45262), JSON columns are not natively supported by the to_pandas_batches() method, which is used by the anywidget backend. This change implements a workaround by automatically converting JSON columns to strings before rendering the table in anywidget. A warning is issued to inform users of this temporary conversion.

Key changes include:
(1) Updated DataFrame.repr_html() to detect JSON columns using bigframes.dtypes.contains_db_dtypes_json_dtype() and apply a conversion to string when in anywidget mode using _apply_unary_op(ops.json_ops.ToJSONString()).
Simplified JSON-to-string casting in scalar_op_registry.py by unconditionally using to_json_string(x) for JSON-to-string conversions, replacing the previous conditional logic that distinguished between safe and unsafe casting modes.
(2) Updated TableWidget.init() to detect and convert JSON columns to strings before processing, ensuring compatibility with the Arrow-based to_pandas_batches() method.
(3) Added comprehensive system tests including test_json_column_anywidget_mode(), test_struct_column_anywidget_mode(), and test_sql_anywidget_mode() to verify the display of JSON and STRUCT columns in anywidget mode.
(4) Updated anywidget_mode.ipynb notebook with an example demonstrating the display of generative AI results from AI.GENERATE, which returns JSON columns, showing the automatic conversion to strings for display.
(5) Removed test test_json_astype_others_raise_error[to_string] that expected JSON-to-string conversions to raise errors in strict mode, as this behavior is no longer supported with the simplified casting logic.

Fixes #<448126500 and 453561268> 🦕

@shuoweil shuoweil self-assigned this Oct 4, 2025
@shuoweil shuoweil requested review from a team as code owners October 4, 2025 07:39
@product-auto-label product-auto-label bot added size: s Pull request size is small. api: bigquery Issues related to the googleapis/python-bigquery-dataframes API. labels Oct 4, 2025
@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@product-auto-label product-auto-label bot added size: m Pull request size is medium. and removed size: s Pull request size is small. labels Oct 4, 2025
Copy link
Collaborator

@tswast tswast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In b/448126500 I suggest investigating the errors that happen when visualizing STRUCT columns, but this PR doesn't test such cases.

@shuoweil shuoweil force-pushed the shuowei-anywidget-col branch 2 times, most recently from 43a938c to 4a33ccf Compare October 9, 2025 06:43
@shuoweil shuoweil requested a review from tswast October 9, 2025 06:45
@shuoweil shuoweil force-pushed the shuowei-anywidget-col branch from 30dfa7d to 237c134 Compare October 15, 2025 19:45
@shuoweil shuoweil requested a review from tswast October 15, 2025 20:51
Comment on lines 786 to 788
# anywdiget mode uses the same display logic as the "deferred" mode
# for faster execution
if opts.repr_mode in ("deferred", "anywidget"):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's revert this.

@shuoweil shuoweil force-pushed the shuowei-anywidget-col branch from f18fd9e to 8601e52 Compare October 20, 2025 08:20
@product-auto-label product-auto-label bot added size: l Pull request size is large. and removed size: m Pull request size is medium. labels Oct 21, 2025
@shuoweil shuoweil force-pushed the shuowei-anywidget-col branch from 533541a to 860db3e Compare October 21, 2025 01:57
@product-auto-label product-auto-label bot added size: m Pull request size is medium. size: l Pull request size is large. and removed size: l Pull request size is large. size: m Pull request size is medium. labels Oct 21, 2025
@shuoweil shuoweil changed the title perf: Default to interactive display for SQL in anywidget mode feat: Display JSON columns in anywidget mode Oct 21, 2025
@shuoweil shuoweil requested a review from tswast October 21, 2025 04:24
Previously, SQL queries in anywidget mode would fall back to deferred execution, showing a dry run instead of an interactive table.

This change modifies the display logic to directly use the anywidget interactive display for SQL queries, providing a more consistent and responsive user experience. A test case has been added to verify this behavior.
Adds a test case to verify that a DataFrame with a STRUCT column is
correctly displayed in anywidget mode.

This test confirms that displaying a STRUCT column does not raise an
exception that would trigger the fallback to the deferred representation.
It mocks `IPython.display.display` to capture the `TableWidget` instance
and asserts that the rendered HTML contains the expected string
representation of the STRUCT data.
This commit fixes an AttributeError that occurred when displaying a
DataFrame with a JSON column in anywidget mode. The dtype check
was incorrect and has been updated. Additionally, the SQL compilation
for casting JSON to string has been corrected to use TO_JSON_STRING.
@shuoweil shuoweil force-pushed the shuowei-anywidget-col branch from 36e58ba to 48ba1a0 Compare October 21, 2025 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: bigquery Issues related to the googleapis/python-bigquery-dataframes API. size: l Pull request size is large.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants