- Notifications
You must be signed in to change notification settings - Fork63
fix: Resolve AttributeError in TableWidget and improve initialization#1937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Merged
Uh oh!
There was an error while loading.Please reload this page.
Merged
Changes fromall commits
Commits
Show all changes
45 commits Select commitHold shift + click to select a range
dd4853d remove expensive len() call
shuoweil6afa44b add testcase
shuoweil878e350 fix a typo
shuoweil01781df change how row_count is updated
shuoweil5496e74 testcase stil fails, need to merged in 1888
shuoweil0b364b0 update the method of using PandasBatches.total_rows
shuoweil858488d change tests in read_gbq_colab
shuoweil91b2c5e polish comment
shuoweil0b50d0c fix a test
shuoweil7549f74 change code and update more testcase
shuoweilaa25d1e remove unneeded except
shuoweila8cc856 add assert for total_rows
shuoweilf6789e5 get actual row_counts
shuoweil9a5ad86 avoid two query calls
shuoweil1d70cfd remove double query when display widget
shuoweil223183a get row count directly
shuoweilac55b50 restore notebook
shuoweilb498ad5 restore notebook change
shuoweil90c5e35 remove duplicated code
shuoweilfad499c minor updates
shuoweil635e821 still have zero total rows issue
shuoweil9db0a2a now large dataset can get the correct row counts
shuoweilf6609cf benchmark change
shuoweildc332ef revert a benchmark
shuoweil47193f1 revert executor change
shuoweilf4b6336 raising a NotImplementedError when the row count is none
shuoweil085687f change return type
shuoweil1767bdc Revert accidental change of dataframe.ipynb
shuoweilc9f27a1 remove unnecessary execution in benchmark
shuoweile7bbea1 remove row_count check
shuoweil3bb0114 remove extra execute_result
shuoweil9e5c8be remove unnecessary tests
shuoweil50c92a5 Fix: Address review comments on PandasBatches and docstring
shuoweil8f33c05 Revert: Revert import change in read_gbq_colab benchmark
shuoweil9c450f2 Revert: Revert unnecessary changes in read_gbq_colab benchmarks
shuoweil885bf89 Remove notebooks/Untitled-2.ipynb
shuoweil9a793e8 Remove notebooks/multimodal/audio_transcribe_partial_ordering.ipynb
shuoweil37eab08 remove unnecessary change
shuoweil058b7b7 revert typo
shuoweilbedfed4 add todo
shuoweil02cf227 change docstring
shuoweilaf9a4e8 revert changes to tests/benchmark/read_gbq_colab
shuoweil93dbb4d merge change
shuoweil76cdec6 update how we handle invalid row count
shuoweild4e1e76 eliminate duplated flags
shuoweilFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -23,13 +23,14 @@ | ||
| import pandas as pd | ||
| import bigframes | ||
| from bigframes.core import blocks | ||
| import bigframes.dataframe | ||
| import bigframes.display.html | ||
| # anywidget and traitlets are optional dependencies. We don't want the import of | ||
| #thismodule to fail if they aren't installed, though. Instead, we try to | ||
| #limit the surface thatthese packages could affect. This makes unit testing | ||
| #easier and ensures we don'taccidentally make these required packages. | ||
| try: | ||
| import anywidget | ||
| import traitlets | ||
| @@ -46,9 +47,21 @@ | ||
| class TableWidget(WIDGET_BASE): | ||
| """An interactive, paginated table widget for BigFrames DataFrames. | ||
| This widget provides a user-friendly way to display and navigate through | ||
| large BigQuery DataFrames within a Jupyter environment. | ||
| """ | ||
| page = traitlets.Int(0).tag(sync=True) | ||
| page_size = traitlets.Int(0).tag(sync=True) | ||
| row_count = traitlets.Int(0).tag(sync=True) | ||
| table_html = traitlets.Unicode().tag(sync=True) | ||
| _initial_load_complete = traitlets.Bool(False).tag(sync=True) | ||
| _batches: Optional[blocks.PandasBatches] = None | ||
| _error_message = traitlets.Unicode(allow_none=True, default_value=None).tag( | ||
| sync=True | ||
| ) | ||
| def __init__(self, dataframe: bigframes.dataframe.DataFrame): | ||
| """Initialize the TableWidget. | ||
| @@ -61,10 +74,11 @@ def __init__(self, dataframe: bigframes.dataframe.DataFrame): | ||
| "Please `pip install anywidget traitlets` or `pip install 'bigframes[anywidget]'` to use TableWidget." | ||
| ) | ||
| self._dataframe = dataframe | ||
| super().__init__() | ||
| # Initialize attributes that might be needed by observers first | ||
| self._table_id = str(uuid.uuid4()) | ||
| self._all_data_loaded = False | ||
| self._batch_iter: Optional[Iterator[pd.DataFrame]] = None | ||
| @@ -73,9 +87,6 @@ def __init__(self, dataframe: bigframes.dataframe.DataFrame): | ||
| # respect display options for initial page size | ||
| initial_page_size = bigframes.options.display.max_rows | ||
shuoweil marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
| # set traitlets properties that trigger observers | ||
| self.page_size = initial_page_size | ||
| @@ -84,12 +95,21 @@ def __init__(self, dataframe: bigframes.dataframe.DataFrame): | ||
| # TODO(b/428238610): Start iterating over the result of `to_pandas_batches()` | ||
| # before we get here so that the count might already be cached. | ||
| # TODO(b/452747934): Allow row_count to be None and check to see if | ||
| # there are multiple pages and show "page 1 of many" in this case | ||
| self._reset_batches_for_new_page_size() | ||
| if self._batches is None or self._batches.total_rows is None: | ||
| self._error_message = "Could not determine total row count. Data might be unavailable or an error occurred." | ||
| self.row_count = 0 | ||
| else: | ||
| self.row_count = self._batches.total_rows | ||
| # get the initial page | ||
| self._set_table_html() | ||
| # Signals to the frontend that the initial data load is complete. | ||
| # Also used as a guard to prevent observers from firing during initialization. | ||
| self._initial_load_complete = True | ||
| @functools.cached_property | ||
| def _esm(self): | ||
| """Load JavaScript code from external file.""" | ||
| @@ -100,11 +120,6 @@ def _css(self): | ||
| """Load CSS code from external file.""" | ||
| return resources.read_text(bigframes.display, "table_widget.css") | ||
| @traitlets.validate("page") | ||
| def _validate_page(self, proposal: Dict[str, Any]) -> int: | ||
| """Validate and clamp the page number to a valid range. | ||
| @@ -171,7 +186,10 @@ def _get_next_batch(self) -> bool: | ||
| def _batch_iterator(self) -> Iterator[pd.DataFrame]: | ||
| """Lazily initializes and returns the batch iterator.""" | ||
| if self._batch_iter is None: | ||
| if self._batches is None: | ||
| self._batch_iter = iter([]) | ||
| else: | ||
| self._batch_iter = iter(self._batches) | ||
| return self._batch_iter | ||
| @property | ||
| @@ -181,15 +199,22 @@ def _cached_data(self) -> pd.DataFrame: | ||
| return pd.DataFrame(columns=self._dataframe.columns) | ||
| return pd.concat(self._cached_batches, ignore_index=True) | ||
| def _reset_batches_for_new_page_size(self) -> None: | ||
| """Reset the batch iterator when page size changes.""" | ||
| self._batches = self._dataframe._to_pandas_batches(page_size=self.page_size) | ||
| self._cached_batches = [] | ||
| self._batch_iter = None | ||
| self._all_data_loaded = False | ||
| def _set_table_html(self) -> None: | ||
| """Sets the current html data based on the current page and page size.""" | ||
| if self._error_message: | ||
| self.table_html = ( | ||
| f"<div class='bigframes-error-message'>{self._error_message}</div>" | ||
| ) | ||
| return | ||
| start = self.page * self.page_size | ||
| end = start + self.page_size | ||
| @@ -211,13 +236,17 @@ def _set_table_html(self): | ||
| ) | ||
| @traitlets.observe("page") | ||
| def _page_changed(self, _change: Dict[str, Any]) -> None: | ||
| """Handler for when the page number is changed from the frontend.""" | ||
| if not self._initial_load_complete: | ||
| return | ||
| self._set_table_html() | ||
| @traitlets.observe("page_size") | ||
| def _page_size_changed(self, _change: Dict[str, Any]) -> None: | ||
| """Handler for when the page size is changed from the frontend.""" | ||
| if not self._initial_load_complete: | ||
| return | ||
| # Reset the page to 0 when page size changes to avoid invalid page states | ||
| self.page = 0 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.