Skip to content

Commit

Permalink
reactive_read() now throws more informative errors (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpsievert committed Nov 17, 2023
1 parent 0ea60ef commit 178da20
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ All notable changes to shinywidgets will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [UNRELEASED]

* `reactive_read()` now throws a more informative error when attempting to read non-existing or non-trait attributes. (#120)

## [0.2.3] - 2023-11-13

* Widgets now `fill` inside of a `fillable` container by default. For examples, see the [ipyleaflet](https://github.com/posit-dev/py-shinywidgets/blob/main/examples/ipyleaflet/app.py), [plotly](https://github.com/posit-dev/py-shinywidgets/blob/main/examples/plotly/app.py), or other [output](https://github.com/posit-dev/py-shinywidgets/blob/main/examples/outputs/app.py) examples. If this intelligent filling isn't desirable, either provide a `height` or `fillable=False` on `output_widget()`. (#115)
* `as_widget()` uses the new `altair.JupyterChart()` to coerce `altair.Chart()` into a `ipywidgets.widgets.Widget` instance. (#120)
* `as_widget()` uses the new `altair.JupyterChart()` to coerce `altair.Chart()` into a `ipywidgets.widgets.Widget` instance. (#113)

## [0.2.2] - 2023-10-31

Expand Down
37 changes: 37 additions & 0 deletions examples/altair/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import altair as alt
from shiny import App, render, ui
from vega_datasets import data

from shinywidgets import output_widget, reactive_read, register_widget

source = data.cars()

app_ui = ui.page_fluid(
ui.output_text_verbatim("selection"),
output_widget("chart")
)

def server(input, output, session):

# Replicate JupyterChart interactivity
# https://altair-viz.github.io/user_guide/jupyter_chart.html#point-selections
brush = alt.selection_point(name="point", encodings=["color"], bind="legend")
chart = alt.Chart(source).mark_point().encode(
x='Horsepower:Q',
y='Miles_per_Gallon:Q',
color=alt.condition(brush, 'Origin:N', alt.value('grey')),
).add_params(brush)

jchart = alt.JupyterChart(chart)

# Display/register the chart in the app_ui
register_widget("chart", jchart)

# Reactive-ly read point selections
@output
@render.text
def selection():
pt = reactive_read(jchart.selections, "point")
return "Selected point: " + str(pt)

app = App(app_ui, server)
16 changes: 15 additions & 1 deletion shinywidgets/_shinywidgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,21 @@ def reactive_depend(
Reactively read a Widget's trait(s)
"""

ctx = reactive.get_current_context() # pyright: ignore[reportPrivateImportUsage]
try:
ctx = reactive.get_current_context() # pyright: ignore[reportPrivateImportUsage]
except RuntimeError:
raise RuntimeError("reactive_read() must be called within a reactive context")

if isinstance(names, str):
names = [names]

for name in names:
if not widget.has_trait(name):
raise ValueError(
f"The '{name}' attribute of {widget.__class__.__name__} is not a "
"widget trait, and so it's not possible to reactively read it. "
"For a list of widget traits, call `.trait_names()` on the widget."
)

def invalidate(change: object):
ctx.invalidate()
Expand Down

0 comments on commit 178da20

Please sign in to comment.