Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [UNRELEASED]

### `input` key changes
### Deprecations

* Restored `@render.data_frame`'s (prematurely removed in v0.9.0) input value `input.<ID>_selected_rows()`. Please use `<ID>.input_cell_selection()["rows"]` and consider `input.<ID>_selected_rows()` deprecated. (#1345, #1377)
* Restored `@render.data_frame`'s (prematurely removed in v0.9.0) input value `input.<ID>_selected_rows()`. Please use `<ID>.cell_selection()["rows"]` and consider `input.<ID>_selected_rows()` deprecated. (#1345, #1377)

* `@render.data_frame`'s method `.input_cell_selection()` has been renamed to `.cell_selection()`. Please use `.cell_selection()` and consider `.input_cell_selection()` deprecated. (#1407)

* `@render.data_frame`'s input value `input.<ID>_data_view_indices` has been renamed to `input.<ID>_data_view_rows` for consistent naming. Please use `input.<ID>_data_view_rows` and consider `input.<ID>_data_view_indices` deprecated. (#1377)

Expand Down
2 changes: 1 addition & 1 deletion examples/dataframe/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def handle_edit():

@render.text
def detail():
selected_rows = (grid.input_cell_selection() or {}).get("rows", ())
selected_rows = (grid.cell_selection() or {}).get("rows", ())
if len(selected_rows) > 0:
# "split", "records", "index", "columns", "values", "table"
return df().iloc[list(selected_rows)]
Expand Down
39 changes: 27 additions & 12 deletions shiny/render/_data_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class data_frame(Renderer[DataFrameResult]):
Row selection
-------------
When using the row selection feature, you can access the selected rows by using the
`<data_frame_renderer>.input_cell_selection()` method, where `<data_frame_renderer>`
`<data_frame_renderer>.cell_selection()` method, where `<data_frame_renderer>`
is the render function name that corresponds with the `id=` used in
:func:`~shiny.ui.outout_data_frame`. Internally, this method retrieves the selected
cell information from session's `input.<id>_cell_selection()` value. The value
Expand Down Expand Up @@ -281,11 +281,11 @@ def data_view(self, *, selected: bool = False) -> pd.DataFrame:
Reactive value of the data frame's possible selection modes.
"""

input_cell_selection: reactive.Calc_[CellSelection | None]
cell_selection: reactive.Calc_[CellSelection | None]
"""
Reactive value of selected cell information.

This method is a wrapper around `input.<id>_selected_cells()`, where `<id>` is
This method is a wrapper around `input.<id>_cell_selection()`, where `<id>` is
the `id` of the data frame output. This method returns the selected rows and
will cause reactive updates as the selected rows change.

Expand Down Expand Up @@ -364,21 +364,21 @@ def self_selection_modes() -> SelectionModes:
self.selection_modes = self_selection_modes

@reactive.calc
def self_input_cell_selection() -> CellSelection | None:
browser_cell_selection_input = self._get_session().input[
def self_cell_selection() -> CellSelection | None:
browser_cell_selection = self._get_session().input[
f"{self.output_id}_cell_selection"
]()

browser_cell_selection = as_cell_selection(
browser_cell_selection_input,
cell_selection = as_cell_selection(
browser_cell_selection,
selection_modes=self.selection_modes(),
)
if browser_cell_selection["type"] == "none":
if cell_selection["type"] == "none":
return None

return browser_cell_selection
return cell_selection

self.input_cell_selection = self_input_cell_selection
self.cell_selection = self_cell_selection

# # Array of sorted column information
# # TODO-barret-render.data_frame; Expose and update column sorting
Expand Down Expand Up @@ -414,7 +414,7 @@ def self__input_data_view_rows() -> list[int]:
# @reactive.calc
# def self__data_selected() -> pd.DataFrame:
# # browser_cell_selection
# bcs = self.input_cell_selection()
# bcs = self.cell_selection()
# if bcs is None:
# req(False)
# raise RuntimeError("This should never be reached for typing purposes")
Expand Down Expand Up @@ -489,7 +489,7 @@ def _subset_data_view(selected: bool) -> pd.DataFrame:

# Possibly subset the indices to selected rows
if selected:
cell_selection = self.input_cell_selection()
cell_selection = self.cell_selection()
if cell_selection is not None and cell_selection["type"] == "row":
# Use a `set` for faster lookups
selected_row_set = set(cell_selection["rows"])
Expand Down Expand Up @@ -893,3 +893,18 @@ async def update_cell_selection(
"updateCellSelection",
{"cellSelection": cell_selection},
)

def input_cell_selection(self) -> CellSelection | None:
"""
[Deprecated] Reactive value of selected cell information.

Please use `~shiny.render.data_frame.cell_selection` instead.
"""

from .._deprecated import warn_deprecated

warn_deprecated(
"`@render.data_frame`'s `.input_cell_selection()` method is deprecated. Please use `.cell_selection()` instead."
)

return self.cell_selection()
2 changes: 1 addition & 1 deletion tests/playwright/shiny/bugs/0676-row-selection/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def detail():

@render.code
def debug():
return str((grid.input_cell_selection() or {}).get("rows", ()))
return str((grid.cell_selection() or {}).get("rows", ()))


app = App(app_ui, server, debug=True)
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def selected_rows():

@render.text
def cell_selection():
cell_selection = df1.input_cell_selection()
cell_selection = df1.cell_selection()
if cell_selection is None:
req(cell_selection)
raise ValueError("Cell selection is None")
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright/shiny/components/data_frame/edit/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def _():

@reactive.effect
def _():
print("Cell Selection:", summary_data.input_cell_selection())
print("Cell Selection:", summary_data.cell_selection())

# @reactive.effect
# def _():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def data_view_selected_true(): # pyright: ignore[reportUnknownParameterType]

@render.code # pyright: ignore[reportArgumentType]
def cell_selection(): # pyright: ignore[reportUnknownParameterType]
return iris_df.input_cell_selection()["rows"] # pyright: ignore
return iris_df.cell_selection()["rows"] # pyright: ignore

@reactive.Effect
@reactive.event(input.reset_df)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,73 +6,73 @@
def test_dataframe_organization_methods(page: Page, local_app: ShinyAppProc) -> None:
page.goto(local_app.url)
data_frame = OutputDataFrame(page, "iris_df")
input_view_rows = OutputCode(page, "data_view_rows")
input_view_selected_true = OutputCode(page, "data_view_selected_true")
input_view_selected_false = OutputCode(page, "data_view_selected_false")
input_cell_selection = OutputCode(page, "cell_selection")
data_view_rows = OutputCode(page, "data_view_rows")
data_view_selected_true = OutputCode(page, "data_view_selected_true")
data_view_selected_false = OutputCode(page, "data_view_selected_false")
cell_selection = OutputCode(page, "cell_selection")
reset_df = InputActionButton(page, "reset_df")

def reset_data_frame():
reset_df.click()
input_view_rows.expect_value("(0, 1, 2)")
input_view_selected_true.expect_value("[]")
input_view_selected_false.expect_value("[ 0 50 100]")
input_cell_selection.expect_value("()")
data_view_rows.expect_value("(0, 1, 2)")
data_view_selected_true.expect_value("[]")
data_view_selected_false.expect_value("[ 0 50 100]")
cell_selection.expect_value("()")

# assert value of unsorted table
reset_data_frame()

# sort column by number descending
data_frame.set_column_sort(col=0)
input_view_rows.expect_value("(1, 2, 0)")
input_view_selected_true.expect_value("[]")
input_view_selected_false.expect_value("[ 50 100 0]")
input_cell_selection.expect_value("()")
data_view_rows.expect_value("(1, 2, 0)")
data_view_selected_true.expect_value("[]")
data_view_selected_false.expect_value("[ 50 100 0]")
cell_selection.expect_value("()")

# sort column by number ascending
data_frame.set_column_sort(col=0)
input_view_rows.expect_value("(0, 2, 1)")
input_view_selected_true.expect_value("[]")
input_view_selected_false.expect_value("[ 0 100 50]")
input_cell_selection.expect_value("()")
data_view_rows.expect_value("(0, 2, 1)")
data_view_selected_true.expect_value("[]")
data_view_selected_false.expect_value("[ 0 100 50]")
cell_selection.expect_value("()")

# sort column by text ascending
data_frame.set_column_sort(col=4)
input_view_rows.expect_value("(0, 1, 2)")
input_view_selected_true.expect_value("[]")
input_view_selected_false.expect_value("[ 0 50 100]")
input_cell_selection.expect_value("()")
data_view_rows.expect_value("(0, 1, 2)")
data_view_selected_true.expect_value("[]")
data_view_selected_false.expect_value("[ 0 50 100]")
cell_selection.expect_value("()")

# sort column by text descending
data_frame.set_column_sort(col=4)
input_view_rows.expect_value("(2, 1, 0)")
input_view_selected_true.expect_value("[]")
input_view_selected_false.expect_value("[100 50 0]")
input_cell_selection.expect_value("()")
data_view_rows.expect_value("(2, 1, 0)")
data_view_selected_true.expect_value("[]")
data_view_selected_false.expect_value("[100 50 0]")
cell_selection.expect_value("()")

reset_data_frame()

# filter using numbers
data_frame.set_column_filter(col=0, text=["6", "7"])
input_view_rows.expect_value("(1, 2)")
input_view_selected_true.expect_value("[]")
input_view_selected_false.expect_value("[ 50 100]")
input_cell_selection.expect_value("()")
data_view_rows.expect_value("(1, 2)")
data_view_selected_true.expect_value("[]")
data_view_selected_false.expect_value("[ 50 100]")
cell_selection.expect_value("()")

reset_data_frame()

# select multiple rows
data_frame.select_rows([0, 2])
input_view_rows.expect_value("(0, 1, 2)")
input_view_selected_true.expect_value("[ 0 100]")
input_view_selected_false.expect_value("[ 0 50 100]")
input_cell_selection.expect_value("(0, 2)")
data_view_rows.expect_value("(0, 1, 2)")
data_view_selected_true.expect_value("[ 0 100]")
data_view_selected_false.expect_value("[ 0 50 100]")
cell_selection.expect_value("(0, 2)")

reset_data_frame()

# select single row
data_frame.select_rows([0])
input_view_rows.expect_value("(0, 1, 2)")
input_view_selected_true.expect_value("[0]")
input_view_selected_false.expect_value("[ 0 50 100]")
input_cell_selection.expect_value("(0,)")
data_view_rows.expect_value("(0, 1, 2)")
data_view_selected_true.expect_value("[0]")
data_view_selected_false.expect_value("[ 0 50 100]")
cell_selection.expect_value("(0,)")
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async def select_1_3_5():

@render.code
def selected_rows():
cell_selection = grid.input_cell_selection()
cell_selection = grid.cell_selection()
if cell_selection is None:
return "None"
return str(cell_selection.get("rows", ()))
Expand Down