Skip to content

fix: Correct DataFrame widget rendering in Colab - #2319

Merged
tswast merged 7 commits into
mainfrom
shuowei-anywidget-fix-display-colab
Dec 12, 2025
Merged

fix: Correct DataFrame widget rendering in Colab#2319
tswast merged 7 commits into
mainfrom
shuowei-anywidget-fix-display-colab

Conversation

@shuoweil

@shuoweilshuoweil commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

This PR fix the _get_anywidget_bundle method. Previously, when the underlying widget's repr_mimebundle method returned a (data, metadata) tuple, the code was only extracting the data portion and discarding the metadata. This resulted in the widget not rendering correctly in environments like Colab, which rely on this metadata.

The change corrects this by properly unpacking the tuple into widget_repr and widget_metadata. The method now preserves the metadata and returns it along with the data, ensuring that the necessary information for widget rendering is passed on.

We also revert commit 4df3428 to reapply "refactor: Migrate DataFrame display to use IPython's repr_mimebundle() protocol for anywidget mode (#2271)"

A testcase is added to verify this new change. We also verified at colab: screen/AzGa5RMTJnMH5NH

Fixes #<466155761> 🦕

@shuoweil
shuoweil requested review from a team and tswastDecember 9, 2025 23:48
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@shuoweilshuoweil assigned shuoweil and unassigned chelsea-linDec 9, 2025
@product-auto-labelproduct-auto-labelBot added size: xl Pull request size is extra large. api: bigquery Issues related to the googleapis/python-bigquery-dataframes API. labels Dec 9, 2025
@shuoweil
shuoweil marked this pull request as draft December 9, 2025 23:48
@shuoweil
shuoweil marked this pull request as ready for review December 10, 2025 00:08

# Handle both tuple (data, metadata) and dict returns
if isinstance(widget_repr_result, tuple):
widget_repr, widget_metadata = widget_repr_result

@shuoweilshuoweilDec 10, 2025

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Even though this PR is a large one, the only difference from #2271 is this added metadata part. PR 2271 discards metadata, which causes the widget is not displayed at colab notebook. I modify the method to ensure metadata is preserved and returned. Verified at: screen/AjTEQC8SrSfMqhN

860 861 # Handle both tuple (data, metadata) and dict returns 862 if isinstance(widget_repr_result, tuple): 863 - widget_repr = dict(widget_repr_result[0]) # Extract data dict from tuple 863 + widget_repr, widget_metadata = widget_repr_result 864 else: 865 - widget_repr = dict(widget_repr_result) 865 + widget_repr = widget_repr_result 866 + widget_metadata = None 867 868 + widget_repr = dict(widget_repr) 869 + 870 # At this point, we have already executed the query as part of the 871 # widget construction. Let's use the information available to render 872 # the HTML and plain text versions. 876 widget._cached_data, widget.row_count 877 ) 878 879 + if widget_metadata is not None: 880 + return widget_repr, widget_metadata 881 return widget_repr 882 

@tswasttswast left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks! Some small changes requested.

I've tested this in Jupyter, VS Code, and BQ Studio as well, and it works great.

Image

Even though, we're using Anywidget, I couldn't get it to work on Marimo. marimo-team/marimo#5099 (comment) I've filed b/467647693 to track this (very low priority).

Comment threadbigframes/dataframe.py Outdated
# At this point, we have already executed the query as part of the
# widget construction. Let's use the information available to render
# the HTML and plain text versions.
widget_repr["text/html"] = widget.table_html

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I notice that when I reload the notebook in VS Code and Jupyter, I miss out on the fact that there are additional pages / rows. Let's call the create HTML representation function here, too.

P.S. Here's the minimal notebook I'm using for testing:

importbigframes.pandasasbpdbpd.options.display.repr_mode="anywidget"df=bpd._read_gbq_colab("select * from `bigquery-public-data.usa_names.usa_1910_2013` where name like '%T%';")
df

Comment threadbigframes/dataframe.py Outdated
df[col] = df[col].blob._get_runtime(mode="R", with_metadata=True)
return df, blob_cols

def _get_anywidget_bundle(self, include=None, exclude=None):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's add a return type here, which is a tuple with two dictionaries.

Comment threadbigframes/dataframe.py Outdated
else:
blob_cols = []
widget_repr = widget_repr_result
widget_metadata = None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we can simplify our return type by constructing an empty dictionary here.

Comment threadbigframes/dataframe.py Outdated
Comment on lines +879 to +881
if widget_metadata is not None:
return widget_repr, widget_metadata
return widget_repr

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We can simplify this to always return a tuple if we set widget_metadata to an empty dictionary instead of None.

@product-auto-labelproduct-auto-labelBot added size: l Pull request size is large. and removed size: xl Pull request size is extra large. labels Dec 10, 2025
@shuoweil

Copy link
Copy Markdown
ContributorAuthor

I've tested this in Jupyter, VS Code, and BQ Studio as well, and it works great.

Image Even though, we're using Anywidget, I couldn't get it to work on Marimo. [marimo-team/marimo#5099 (comment)](https://github.com/marimo-team/marimo/issues/5099#issuecomment-3637697554) I've filed b/467647693 to track this (very low priority).

I added a TODO as well.

@shuoweil
shuoweil requested a review from tswastDecember 11, 2025 00:05
@shuoweil

Copy link
Copy Markdown
ContributorAuthor

Upon checking, failed e2e and doctest are not related to my change.

@shuoweil
shuoweilforce-pushed the shuowei-anywidget-fix-display-colab branch from 93ccb3a to 63c15ddCompareDecember 12, 2025 04:31
@tswast
tswast merged commit 7f1d3df into mainDec 12, 2025
24 of 25 checks passed
@tswast
tswast deleted the shuowei-anywidget-fix-display-colab branch December 12, 2025 15:58
@ldetmerldetmer mentioned this pull request Jan 6, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: bigqueryIssues related to the googleapis/python-bigquery-dataframes API.size: lPull request size is large.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@shuoweil@tswast@chelsea-lin