diff --git a/docs/_quartodoc.yml b/docs/_quartodoc.yml index f33556b4e..ae5a7ccdc 100644 --- a/docs/_quartodoc.yml +++ b/docs/_quartodoc.yml @@ -165,6 +165,7 @@ quartodoc: - render.table - render.text - render.ui + - render.express - render.data_frame - render.DataGrid - render.DataTable @@ -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: diff --git a/shiny/express/expressify_decorator/_expressify.py b/shiny/express/expressify_decorator/_expressify.py index ede653fb2..3f58434f1 100644 --- a/shiny/express/expressify_decorator/_expressify.py +++ b/shiny/express/expressify_decorator/_expressify.py @@ -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. diff --git a/shiny/express/ui/_hold.py b/shiny/express/ui/_hold.py index 969b0ae77..9f98b39e5 100644 --- a/shiny/express/ui/_hold.py +++ b/shiny/express/ui/_hold.py @@ -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() diff --git a/shiny/render/_express.py b/shiny/render/_express.py index d899ddcfb..cc7d65b60 100644 --- a/shiny/render/_express.py +++ b/shiny/render/_express.py @@ -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, *,