Skip to content

Commit 8306129

Browse files
committed
testcase stil fails, need to merged in 1888
1 parent d3c4d77 commit 8306129

File tree

2 files changed

+57
-71
lines changed

2 files changed

+57
-71
lines changed

bigframes/display/anywidget.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,35 @@ def __init__(self, dataframe: bigframes.dataframe.DataFrame):
6464
super().__init__()
6565
self._dataframe = dataframe
6666

67-
# Initialize attributes that might be needed by observers FIRST
67+
# Initialize attributes that might be needed by observers first
6868
self._table_id = str(uuid.uuid4())
6969
self._all_data_loaded = False
7070
self._batch_iter: Optional[Iterator[pd.DataFrame]] = None
7171
self._cached_batches: List[pd.DataFrame] = []
7272

73-
# respect display options for initial page size
73+
# Respect display options for initial page size
7474
initial_page_size = bigframes.options.display.max_rows
7575

76-
# Initialize data fetching attributes.
77-
self._batches = dataframe.to_pandas_batches(page_size=initial_page_size)
76+
try:
77+
# Fetches initial data batches and row count for display.
78+
# `to_pandas_batches` provides an iterable of pandas DataFrames
79+
# and eagerly retrieves the total row count
80+
self._batches = dataframe.to_pandas_batches(
81+
page_size=initial_page_size,
82+
)
7883

79-
# Get total rows efficiently by executing the query once
80-
execute_result = dataframe._block.session._executor.execute(
81-
dataframe._block.expr, ordered=True
82-
)
83-
self.row_count = execute_result.total_rows or 0
84+
# Access the total_rows property directly
85+
self.row_count = self._batches.total_rows or 0
86+
self.page_size = initial_page_size
8487

85-
# set traitlets properties that trigger observers
86-
self.page_size = initial_page_size
88+
# Generates the initial HTML table content
89+
self._set_table_html()
8790

88-
# get the initial page
89-
self._set_table_html()
91+
except Exception:
92+
self.row_count = 0
93+
self.page_size = initial_page_size
94+
self._batches = iter([])
95+
self.table_html = ""
9096

9197
@functools.cached_property
9298
def _esm(self):

tests/system/small/test_anywidget.py

Lines changed: 38 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import typing
16-
1715
import pandas as pd
1816
import pytest
1917

@@ -112,29 +110,20 @@ def empty_bf_df(
112110
return session.read_pandas(empty_pandas_df)
113111

114112

115-
def mock_execute_total_rows_is_none(self, schema, *args, **kwargs):
116-
"""Mocks an execution result where the total row count is missing."""
117-
from bigframes.session.executor import ExecuteResult
118-
119-
return ExecuteResult(
120-
iter([]), # arrow_batches
121-
schema=schema,
122-
query_job=None,
123-
total_bytes=None,
124-
total_rows=None, # The specific failure condition for this case
125-
)
126-
127-
128-
def mock_execute_batches_are_invalid(self, schema, *args, **kwargs):
129-
"""Mocks an execution result where the batch data is an invalid type."""
113+
def mock_execute_result_with_params(
114+
self, schema, total_rows_val, arrow_batches_val, *args, **kwargs
115+
):
116+
"""
117+
Mocks an execution result with configurable total_rows and arrow_batches.
118+
"""
130119
from bigframes.session.executor import ExecuteResult
131120

132121
return ExecuteResult(
133-
None, # Invalid type for arrow_batches, which should be an iterator
122+
iter(arrow_batches_val),
134123
schema=schema,
135124
query_job=None,
136125
total_bytes=None,
137-
total_rows=100, # A valid row count, as the error is in the batch data
126+
total_rows=total_rows_val,
138127
)
139128

140129

@@ -475,25 +464,27 @@ def test_widget_row_count_should_be_immutable_after_creation(
475464
"""
476465
from bigframes.display import TableWidget
477466

467+
# Use a context manager to ensure the option is reset
478468
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2):
479469
widget = TableWidget(paginated_bf_df)
480470
initial_row_count = widget.row_count
481-
assert initial_row_count == EXPECTED_ROW_COUNT
482471

483472
# Change a global option that could influence row count
484473
bf.options.display.max_rows = 10
485474

486-
# The widget's row count was fixed at creation and should not change.
475+
# Verify the row count remains immutable.
487476
assert widget.row_count == initial_row_count
488477

489478

490479
@pytest.mark.parametrize(
491-
"mock_function",
480+
"total_rows_param, arrow_batches_param",
492481
[
493-
mock_execute_total_rows_is_none,
494-
mock_execute_batches_are_invalid,
482+
# Corresponds to mock_execute_total_rows_is_none
483+
(None, []),
484+
# Corresponds to mock_execute_batches_are_invalid (assuming empty list
485+
# for invalid batches for now)
486+
(100, []),
495487
],
496-
# 'ids' provides descriptive names for each test run in the pytest report.
497488
ids=[
498489
"when_total_rows_is_None",
499490
"when_arrow_batches_are_invalid",
@@ -502,65 +493,54 @@ def test_widget_row_count_should_be_immutable_after_creation(
502493
def test_widget_should_fallback_to_zero_rows_on_error(
503494
paginated_bf_df: bf.dataframe.DataFrame,
504495
monkeypatch: pytest.MonkeyPatch,
505-
mock_function,
496+
total_rows_param,
497+
arrow_batches_param,
506498
):
507499
"""
508500
Given an internal component fails to return valid execution data,
509501
when the TableWidget is created, its row_count should safely fall back to 0.
510502
"""
511-
# The 'self' argument is automatically handled when monkeypatch calls the method.
512-
# We use a lambda to pass the DataFrame's schema to our mock function.
503+
# Patch the executor's 'execute' method to simulate an error.
513504
monkeypatch.setattr(
514505
"bigframes.session.bq_caching_executor.BigQueryCachingExecutor.execute",
515-
lambda self, *args, **kwargs: mock_function(
516-
self, paginated_bf_df._block.expr.schema, *args, **kwargs
506+
lambda self, *args, **kwargs: mock_execute_result_with_params(
507+
self,
508+
paginated_bf_df._block.expr.schema,
509+
total_rows_param,
510+
arrow_batches_param,
511+
*args,
512+
**kwargs
517513
),
518514
)
519515

516+
# Create the TableWidget under the error condition.
520517
with bf.option_context("display.repr_mode", "anywidget"):
521518
from bigframes.display import TableWidget
522519

523520
# The widget should handle the faulty data from the mock without crashing.
524521
widget = TableWidget(paginated_bf_df)
525522

526-
# The key assertion: The widget safely defaults to 0 rows.
523+
# The widget safely defaults to 0 rows.
527524
assert widget.row_count == 0
528525

529526

530-
@pytest.mark.parametrize(
531-
"max_results, expected_rows",
532-
[
533-
(None, EXPECTED_ROW_COUNT),
534-
(3, 3),
535-
(10, EXPECTED_ROW_COUNT),
536-
],
537-
ids=["no_limit", "limit_is_less_than_total", "limit_is_greater_than_total"],
538-
)
539-
def test_widget_row_count_should_respect_max_results_on_creation(
527+
def test_widget_row_count_reflects_actual_data_available(
540528
paginated_bf_df: bf.dataframe.DataFrame,
541-
max_results: typing.Optional[int],
542-
expected_rows: int,
543529
):
544530
"""
545-
Given a max_results value, when a TableWidget is created with custom batches,
546-
its row_count should be correctly capped by that value.
531+
Test that widget row_count reflects the actual data available,
532+
regardless of theoretical limits.
547533
"""
548-
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2):
549-
from bigframes.core.blocks import PandasBatches
550-
from bigframes.display import TableWidget
534+
from bigframes.display import TableWidget
551535

536+
# Set up display options that define a page size.
537+
with bf.option_context("display.repr_mode", "anywidget", "display.max_rows", 2):
552538
widget = TableWidget(paginated_bf_df)
553539

554-
# Override batches with max_results to test the behavior
555-
widget._batches = paginated_bf_df.to_pandas_batches(
556-
page_size=widget.page_size, max_results=max_results
557-
)
558-
559-
# Re-apply the logic to update row_count
560-
if isinstance(widget._batches, PandasBatches):
561-
widget.row_count = widget._batches.total_rows or 0
562-
563-
assert widget.row_count == expected_rows
540+
# The widget should report the total rows in the DataFrame,
541+
# not limited by page_size (which only affects pagination)
542+
assert widget.row_count == EXPECTED_ROW_COUNT
543+
assert widget.page_size == 2 # Respects the display option
564544

565545

566546
# TODO(shuowei): Add tests for custom index and multiindex

0 commit comments

Comments
 (0)