render.transformer.output_transformer
render.transformer.output_transformer(transform_fn=None, *, default_ui=None, default_ui_passthrough_args=None)
Deprecated. Please use Renderer instead.
Output transformer decorator.
This decorator method is a convenience method to generate the appropriate types and internal implementation for an overloaded renderer method. This method will provide you with all the necessary types to define two different overloads: one for when the decorator is called without parentheses and another for when it is called with parentheses where app authors can pass in parameters to the renderer.
Transform Function
The output renderer’s transform function (transform_fn
) is the key building block for output_transformer
. It is a package author function that calls the app-defined output value function (value_fn
) transforms the result of type IT
into type OT
.
The transform function is supplied meta output information, the (app-supplied) value function, and any keyword arguments supplied to the output tranformer decorator:
- The first parameter to the handler function has the class
TransformerMetadata
and is typically called_meta
. This information gives context to the handler while trying to resolve the app-supplied value function (typically called_fn
). - The second parameter is the app-defined output value function (e.g.
_fn
). It’s return type (IT
) determines what types can be returned by the app-supplied output value function. For example, if_fn
has the typeValueFnAsync[str | None]
, both thestr
andNone
types are allowed to be returned from the app-supplied output value function. - The remaining parameters are the keyword arguments (e.g.
alt:Optional[str] = None
or**kwargs: object
) that app authors may supply to the renderer (when the renderer decorator is called with parentheses). Variadic positional parameters (e.g.*args
) are not allowed. All keyword arguments should have a type and default value. No default value is needed for keyword arguments that are passed through (e.g.**kwargs: Any
).
The transform function’s return type (OT
) determines the output type of the OutputRenderer
. Note that in many cases (but not all!) IT
and OT
will be the same. The None
type should typically be defined in both IT
and OT
. If IT
allows for None
values, it (typically) signals that nothing should be rendered. If OT
allows for None
and returns a None
value, shiny will not render the output.
Notes
When defining the renderer decorator overloads, if you have extra parameters of
**kwargs: object
, you may get a type error about incompatible signatures. To fix this, you can use**kwargs: Any
instead or add_fn: None = None
as the first parameter in the overload containing the**kwargs: object
.The
transform_fn
should be defined as an asynchronous function but should only asynchronously yield (i.e. useawait
syntax) when the value function (the second parameter of typeValueFn[IT]
) is awaitable. If the value function is not awaitable (i.e. it is a synchronous function), then the execution of the transform function should also be synchronous.
Parameters
transform_fn:
TransformFn
[IT
,P
,OT
] | None = None-
Asynchronous function used to determine the app-supplied output value function return type (
IT
), the transformed type (OT
), and the keyword arguments (P
) app authors can supply to the renderer decorator. default_ui: Optional[
DefaultUIFn
] = None-
Optional function that takes an
output_id
string and returns a Shiny UI object that can be used to display the output. This allows render functions to respond to_repr_html_
method calls in environments like Jupyter.
Returns
Type | Description |
---|---|
OutputTransformer [IT , OT , P ] | Callable[[TransformFn [IT , P , OT ]], OutputTransformer [IT , OT , P ]] |
An OutputTransformer object that can be used to define two overloads for your renderer function. One overload is for when the renderer is called without parentheses and the other is for when the renderer is called with parentheses. |
Examples
#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400
## file: app.py
from __future__ import annotations
from typing import Literal, overload
from shiny import App, Inputs, Outputs, Session, ui
from shiny.render.transformer import (
TransformerMetadata,
ValueFn,
output_transformer,
resolve_value_fn,
)
#######
# DEPRECATED. Please see `shiny.render.renderer.Renderer` for the latest API.
# This example is kept for backwards compatibility.
#
#
# Package authors can create their own output transformer methods by leveraging
# `output_transformer` decorator.
#
# The transformer is kept simple for demonstration purposes, but it can be much more
# complex (e.g. shiny.render.plotly)
#######
# Create renderer components from the async handler function: `capitalize_components()`
@output_transformer()
async def CapitalizeTransformer(
# Contains information about the render call: `name` and `session`
_meta: TransformerMetadata,
# The app-supplied output value function
_fn: ValueFn[str | None],
*,
# Extra parameters that app authors can supply to the render decorator
# (e.g. `@render_capitalize(to="upper")`)
to: Literal["upper", "lower"] = "upper",
) -> str | None:
# Get the value
value = await resolve_value_fn(_fn)
# Equvalent to:
# if shiny.render.transformer.is_async_callable(_fn):
# value = await _fn()
# else:
# value = _fn()
# Render nothing if `value` is `None`
if value is None:
return None
if to == "upper":
return value.upper()
if to == "lower":
return value.lower()
raise ValueError(f"Invalid value for `to`: {to}")
# First, create an overload where users can supply the extra parameters.
# Example of usage:
# ```
# @render_capitalize(to="upper")
# def value():
# return input.caption()
# ```
# Note: Return type is `OutputRendererDecorator`
@overload
def render_capitalize(
*,
to: Literal["upper", "lower"] = "upper",
) -> CapitalizeTransformer.OutputRendererDecorator: ...
# Second, create an overload where users are not using parentheses to the method.
# While it doesn't look necessary, it is needed for the type checker.
# Example of usage:
# ```
# @render_capitalize
# def value():
# return input.caption()
# ```
# Note: `_fn` type is the transformer's `ValueFn`
# Note: Return type is the transformer's `OutputRenderer`
@overload
def render_capitalize(
_fn: CapitalizeTransformer.ValueFn,
) -> CapitalizeTransformer.OutputRenderer: ...
# Lastly, implement the renderer.
# Note: `_fn` type is the transformer's `ValueFn` or `None`
# Note: Return type is the transformer's `OutputRenderer` or `OutputRendererDecorator`
def render_capitalize(
_fn: CapitalizeTransformer.ValueFn | None = None,
*,
to: Literal["upper", "lower"] = "upper",
) -> (
CapitalizeTransformer.OutputRenderer | CapitalizeTransformer.OutputRendererDecorator
):
return CapitalizeTransformer(
_fn,
CapitalizeTransformer.params(to=to),
)
#######
# End of package author code
#######
app_ui = ui.page_fluid(
ui.h1("Capitalization renderer"),
ui.input_text("caption", "Caption:", "Data summary"),
"Renderer called with out parentheses:",
ui.output_text_verbatim("no_parens"),
"To upper:",
ui.output_text_verbatim("to_upper"),
"To lower:",
ui.output_text_verbatim("to_lower"),
)
def server(input: Inputs, output: Outputs, session: Session):
# Without parentheses
@render_capitalize
def no_parens():
return input.caption()
# With parentheses. Equivalent to `@render_capitalize()`
@render_capitalize(to="upper")
def to_upper():
return input.caption()
@render_capitalize(to="lower")
# Works with async output value functions
async def to_lower():
return input.caption()
app = App(app_ui, server)