Skip to content

Commit

Permalink
Fix regression handling selection on multi-indexed Tabulator data (#7336
Browse files Browse the repository at this point in the history
)
  • Loading branch information
philippjfr authored Sep 30, 2024
1 parent 114a60d commit e42736d
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 8 deletions.
17 changes: 17 additions & 0 deletions panel/tests/ui/widgets/test_tabulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,23 @@ def test_tabulator_selection_selectable_rows(page, df_mixed):
assert widget.selected_dataframe.equals(expected_selected)


@pytest.mark.parametrize('pagination', ['remote', 'local', None])
def test_tabulator_selection_on_multi_index(page, pagination):
index = pd.MultiIndex.from_tuples([(i, j) for i in range(10) for j in range(10)], names=["A", "B"])
df = pd.DataFrame(index=index, data={"C": range(100)})

widget = Tabulator(df, pagination=pagination, selectable='checkbox')

serve_component(page, widget)

checkboxes = page.locator('input[type="checkbox"]')
expect(checkboxes).to_have_count(widget.initial_page_size+1 if pagination else len(df)+1)
checkboxes.nth(1).check()
checkboxes.nth(17).check()

wait_until(lambda: widget.selection == [0, 16], page)


def test_tabulator_row_content(page, df_mixed):
widget = Tabulator(df_mixed, row_content=lambda i: f"{i['str']}-row-content")

Expand Down
8 changes: 4 additions & 4 deletions panel/tests/widgets/test_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -1817,8 +1817,8 @@ def test_tabulator_constant_scalar_filter_on_index_client_side(document, comm, p

@pytest.mark.parametrize('pagination', ['local', 'remote', None])
def test_tabulator_constant_scalar_filter_on_multi_index_client_side(document, comm, pagination):
df = makeMixedDataFrame()
table = Tabulator(df.set_index(['A', 'C']), pagination=pagination)
df = makeMixedDataFrame().set_index(['A', 'C'])
table = Tabulator(df, pagination=pagination)

table.filters = [
{'field': 'A', 'sorter': 'number', 'type': '=', 'value': 2},
Expand All @@ -1831,9 +1831,9 @@ def test_tabulator_constant_scalar_filter_on_multi_index_client_side(document, c
'B': np.array([0.]),
'D': np.array(['2009-01-05T00:00:00.000000000'],
dtype='datetime64[ns]')
})
}).set_index(['A', 'C'])
pd.testing.assert_frame_equal(
table._processed, expected if pagination == 'remote' else df[['A', 'C', 'B', 'D']]
table._processed, expected if pagination == 'remote' else df
)

@pytest.mark.parametrize('pagination', ['local', 'remote', None])
Expand Down
7 changes: 3 additions & 4 deletions panel/widgets/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,9 +642,7 @@ def _process_df_and_convert_to_cds(self, df: pd.DataFrame) -> tuple[pd.DataFrame
else:
default_index = ('level_0' if 'index' in df.columns else 'index')
indexes = [df.index.name or default_index]
if len(indexes) > 1:
df = df.reset_index()
data = ColumnDataSource.from_df(df)
data = ColumnDataSource.from_df(df.reset_index() if len(indexes) > 1 else df)
if not self.show_index and len(indexes) > 1:
data = {k: v for k, v in data.items() if k not in indexes}
return df, {k if isinstance(k, str) else str(k): self._process_column(v) for k, v in data.items()}
Expand Down Expand Up @@ -1440,14 +1438,15 @@ def _get_data(self):
indexes = [df.index.name or default_index]
if len(indexes) > 1:
page_df = page_df.reset_index()
df = df.reset_index()
data = ColumnDataSource.from_df(page_df).items()
return df, {k if isinstance(k, str) else str(k): v for k, v in data}

def _get_style_data(self, recompute=True):
if self.value is None or self.style is None or self.value.empty:
return {}
df = self._processed
if len(self.indexes) > 1:
df = df.reset_index()
if recompute:
try:
self._computed_styler = styler = df.style
Expand Down

0 comments on commit e42736d

Please sign in to comment.