Skip to content

Conversation

@wch
Copy link
Collaborator

@wch wch commented Mar 12, 2024

This PR adds support for Shiny Express apps in Quarto Dashboards. Prior to this PR, it would throw an error if a Quarto document had an import from shiny.express.

If a code block in a .qmd file has an import from shiny.express, like from shiny.express import ... or import shiny.express, then the app.py that is generated from the Quarto document will be written in Express syntax instead of Core syntax. Existing Quarto Dashboards with Shiny (which import from shiny rather than shiny.express) will continue to work in the existing way, where it writes out an app.py with Core syntax.

Remaining issues:

  • It feels a little awkward to have from shiny import reactive and then from shiny.express import ui, render. Should we have an alias to reactive in shiny.express?
  • Should we provide a deprecation warning to encourage Quarto-Shiny users to migrate from import shiny to import shiny.express?

For example:

---
title: "Palmer Penguins"
format: dashboard
server: shiny
---

```{python}
#| context: setup
import seaborn as sns
from shiny.express import render, ui, input
penguins = sns.load_dataset("penguins")
```

# {.sidebar}

```{python}
species = list(penguins["species"].value_counts().index)
ui.input_checkbox_group(
    "species", "Species:",
    species, selected = species
)
```

# Plots

```{python}
@render.plot
def depth():
    data = penguins[penguins["species"].isin(input.species())]
    return sns.displot(
        data, x = "bill_depth_mm",
        hue = "species", kind = "kde",
        fill = True
    )
```

This is what it looks like:

image

The generated app.py looks like this.

# This file generated by Quarto; do not edit by hand.

from __future__ import annotations

from pathlib import Path
from shiny.express import app_opts

_static_assets = ["simple_files"]
_static_assets = {"/" + sa: Path(__file__).parent / sa for sa in _static_assets}
app_opts(
    ui=Path(__file__).parent / "simple.html",
    static_assets=_static_assets
)

import seaborn as sns
from shiny.express import render, ui, input
penguins = sns.load_dataset("penguins")

# ========================================================================



species = list(penguins["species"].value_counts().index)
ui.input_checkbox_group(
    "species", "Species:",
    species, selected = species
)

# ========================================================================

@render.plot
def depth():
    data = penguins[penguins["species"].isin(input.species())]
    return sns.displot(
        data, x = "bill_depth_mm",
        hue = "species", kind = "kde",
        fill = True
    )

# ========================================================================

Note that the UI that's generated from the special evaluation of the Express code will not be used. Instead, it will use the UI that was generated by Quarto (in the form of a static .html file). This is done via app_opts(ui=...).

@wch
Copy link
Collaborator Author

wch commented Mar 13, 2024

Closing in favor of #1217.

@wch wch closed this Mar 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants