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
10 changes: 10 additions & 0 deletions docs/_quartodoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ quartodoc:
- render.table
- render.text
- render.ui
- render.express
- render.data_frame
- render.DataGrid
- render.DataTable
Expand Down Expand Up @@ -329,6 +330,15 @@ quartodoc:
flatten: true
contents:
- express.ui.page_opts
- kind: page
path: DisplayFunctions
summary:
name: "Display functions"
desc: ""
flatten: true
contents:
- express.ui.hold
- express.expressify
- title: Deprecated
desc: ""
contents:
Expand Down
26 changes: 26 additions & 0 deletions shiny/express/expressify_decorator/_expressify.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,32 @@ def expressify() -> Callable[[TFunc], TFunc]:


def expressify(fn: TFunc | None = None) -> TFunc | Callable[[TFunc], TFunc]:
"""
Decorate a function so that output is captured as in Shiny Express

In a Shiny Express app, the output of each line of the app file is captured and
displayed in the UI. However, if the app calls a function, only the return value of
the function is displayed. This decorator changes the behavior of the function so
that when it is executed, the result of each line is captured and displayed, just
like code at the top level of a Shiny Express app.

Parameters
----------
fn :
The function to decorate. If not provided, this is a decorator factory.

Returns
-------
:
A function that returns `None`, or a decorator for a function that returns
`None`.

See Also
--------
* ~shiny.render.express
* ~shiny.express.ui.hold
"""

def decorator(fn: TFunc) -> TFunc:
if is_pyodide:
# Disable code caching on Pyodide due to bug in hashing bytecode in 0.22.1.
Expand Down
37 changes: 15 additions & 22 deletions shiny/express/ui/_hold.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,25 @@
def hold() -> HoldContextManager:
"""Prevent the display of UI elements in various ways.

If used as a context manager (`with hide():`), it prevents the display of all UI
elements within the context block. (This is useful when you want to temporarily
prevent the display of a large number of UI elements, or when you want to prevent
the display of UI elements that are not directly under your control.)

If used as a decorator (without parentheses) on a Shiny rendering function, it
prevents that function from automatically outputting itself at the point of its
declaration. (This is useful when you want to define the rendering logic for an
output, but want to explicitly call a UI output function to indicate where and how
it should be displayed.)

If used as a decorator (without parentheses) on any other function, it turns
Python's `sys.displayhook` into a no-op for the duration of the function call.

Parameters
----------
fn
The function to decorate. If `None`, returns a context manager that prevents the
display of UI elements within the context block.
This is used as a context manager, as in `with hold():`. It prevents the display of
all UI elements within the context block. (This is useful when you want to
temporarily prevent the display of a large number of UI elements, or when you want
to prevent the display of UI elements that are not directly under your control.)

It can also be used as `with hold() as content:` to capture the UI elements that
would be displayed within the context block. Then, later, you can put `content` on a
line by itself to display the captured UI elements.

Returns
-------
:
If `fn` is `None`, returns a context manager that prevents the display of UI
elements within the context block. Otherwise, returns a decorated version of
`fn`.
A context manager that prevents the display of UI elements within the context
block.

See Also
--------
* ~shiny.render.express
* ~shiny.express.expressify
"""

return HoldContextManager()
Expand Down
22 changes: 22 additions & 0 deletions shiny/render/_express.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,28 @@


class express(Renderer[None]):
"""
Reactively render HTML content with output captured as in Shiny Express

This is similar to :class:`~shiny.render.ui`, except that :class:`~shiny.render.ui`
uses the return value from the the decorated function, whereas this function works
like Shiny Express: as it executes each line of the decorated function, it calls
:func:`~sys.displayhook()` on the result. This has the effet of "capturing" the
output of each line.

Returns
-------
:
A decorator for a function that returns `None`.

See Also
--------
* ~shiny.render.ui
* ~shiny.ui.output_ui
* ~shiny.express.expressify
* ~shiny.express.ui.hold
"""

def auto_output_ui(
self,
*,
Expand Down