diff --git a/CHANGELOG.md b/CHANGELOG.md index b5f0fafb4..60e39dc4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Added `@render.download` as a replacement for `@session.download`, which is now deprecated. (#977) +* Added `ui.output_code()`, which is currently an alias for `ui.output_text_verbatim()`. (#997) + +* Added `@render.code`, which is an alias for `@render.text`, but in Express mode, it displays the result using `ui.output_code()`. (#997) + ### Bug fixes * CLI command `shiny create`... (#965) diff --git a/docs/_quartodoc.yml b/docs/_quartodoc.yml index 967abf63c..921a453f9 100644 --- a/docs/_quartodoc.yml +++ b/docs/_quartodoc.yml @@ -158,6 +158,7 @@ quartodoc: - ui.output_table - ui.output_data_frame - ui.output_text + - ui.output_code - ui.output_text_verbatim - ui.output_ui - render.plot diff --git a/shiny/__init__.py b/shiny/__init__.py index 513122382..ae11bd126 100644 --- a/shiny/__init__.py +++ b/shiny/__init__.py @@ -1,6 +1,6 @@ """A package for building reactive web applications.""" -__version__ = "0.6.1.9003" +__version__ = "0.6.1.9004" from ._shinyenv import is_pyodide as _is_pyodide diff --git a/shiny/api-examples/Renderer/app.py b/shiny/api-examples/Renderer/app.py index 332a470f0..e1a8cb513 100644 --- a/shiny/api-examples/Renderer/app.py +++ b/shiny/api-examples/Renderer/app.py @@ -28,7 +28,7 @@ class render_capitalize(Renderer[str]): Whether to render a placeholder value. (Defaults to `True`) """ - def default_ui(self, id: str): + def auto_output_ui(self, id: str): """ Express UI for the renderer """ @@ -94,7 +94,7 @@ class render_upper(Renderer[str]): Note: This renderer is equivalent to `render_capitalize(to="upper")`. """ - def default_ui(self, id: str): + def auto_output_ui(self, id: str): """ Express UI for the renderer """ diff --git a/shiny/express/__init__.py b/shiny/express/__init__.py index 1c430267f..8add0557a 100644 --- a/shiny/express/__init__.py +++ b/shiny/express/__init__.py @@ -4,22 +4,23 @@ # console. from ..session import Inputs as _Inputs, Outputs as _Outputs, Session as _Session from ..session import _utils as _session_utils +from .. import render from . import ui from ._is_express import is_express_app from ._output import ( # noqa: F401 - ui_kwargs, suspend_display, output_args, # pyright: ignore[reportUnusedImport] ) from ._run import wrap_express_app from .display_decorator import display_body + __all__ = ( + "render", "input", "output", "session", "is_express_app", - "ui_kwargs", "suspend_display", "wrap_express_app", "ui", diff --git a/shiny/express/_output.py b/shiny/express/_output.py index 6ab1362d8..ef614efd7 100644 --- a/shiny/express/_output.py +++ b/shiny/express/_output.py @@ -8,13 +8,8 @@ from .. import ui from .._typing_extensions import ParamSpec from ..render.renderer import RendererBase, RendererBaseT -from ..render.transformer import OutputRenderer -from ..render.transformer._transformer import OT -__all__ = ( - "ui_kwargs", - "suspend_display", -) +__all__ = ("suspend_display",) P = ParamSpec("P") R = TypeVar("R") @@ -22,7 +17,7 @@ # TODO-barret-future; quartodoc entry? -def ui_kwargs( +def output_args( **kwargs: object, ) -> Callable[[RendererBaseT], RendererBaseT]: """ @@ -31,9 +26,9 @@ def ui_kwargs( Each Shiny render function (like :func:`~shiny.render.plot`) can display itself when declared within a Shiny inline-style application. In the case of :func:`~shiny.render.plot`, the :func:`~shiny.ui.output_plot` function is called - implicitly to display the plot. Use the `@ui_kwargs` decorator to specify - arguments to be passed to `output_plot` (or whatever the corresponding UI function - is) when the render function displays itself. + implicitly to display the plot. Use the `@ui_kwargs` decorator to specify arguments + to be passed to `output_plot` (or whatever the corresponding UI function is) when + the render function displays itself. Parameters ---------- @@ -47,51 +42,7 @@ def ui_kwargs( """ def wrapper(renderer: RendererBaseT) -> RendererBaseT: - # renderer._default_ui_args = args - renderer._default_ui_kwargs = kwargs - return renderer - - return wrapper - - -def output_args( - *args: object, - **kwargs: object, -) -> Callable[[OutputRenderer[OT]], OutputRenderer[OT]]: - """ - Sets default UI arguments for a Shiny rendering function. - - Each Shiny render function (like :func:`~shiny.render.plot`) can display itself when - declared within a Shiny inline-style application. In the case of - :func:`~shiny.render.plot`, the :func:`~shiny.ui.output_plot` function is called - implicitly to display the plot. Use the `@output_args` decorator to specify - arguments to be passed to `output_plot` (or whatever the corresponding UI function - is) when the render function displays itself. - - - Parameters - ---------- - *args - Positional arguments to be passed to the UI function. - **kwargs - Keyword arguments to be passed to the UI function. - - Returns - ------- - : - A decorator that sets the default UI arguments for a Shiny rendering function. - """ - - def wrapper(renderer: OutputRenderer[OT]) -> OutputRenderer[OT]: - if not isinstance(renderer, OutputRenderer): - raise TypeError( - f"Expected an OutputRenderer, but got {type(renderer).__name__}." - "\nIf you are trying to set default UI arguments for a `Renderer`, use" - " `@ui_kwargs` instead." - ) - renderer._default_ui_args = args - renderer._default_ui_kwargs = kwargs - + renderer._auto_output_ui_kwargs = kwargs return renderer return wrapper @@ -152,7 +103,7 @@ def suspend_display( # display yourself" if isinstance(fn, RendererBase): # By setting the class value, the `self` arg will be auto added. - fn.default_ui = null_ui + fn.auto_output_ui = null_ui return fn return suspend_display_ctxmgr()(fn) diff --git a/shiny/express/ui/__init__.py b/shiny/express/ui/__init__.py index 730380281..533371a84 100644 --- a/shiny/express/ui/__init__.py +++ b/shiny/express/ui/__init__.py @@ -38,8 +38,6 @@ SliderStepArg, SliderValueArg, ValueBoxTheme, - download_button, - download_link, brush_opts, click_opts, dblclick_opts, @@ -95,14 +93,7 @@ notification_show, notification_remove, nav_spacer, - output_plot, - output_image, - output_text, - output_text_verbatim, - output_table, - output_ui, Progress, - output_data_frame, value_box_theme, ) @@ -178,8 +169,6 @@ "SliderStepArg", "SliderValueArg", "ValueBoxTheme", - "download_button", - "download_link", "brush_opts", "click_opts", "dblclick_opts", @@ -235,14 +224,7 @@ "notification_show", "notification_remove", "nav_spacer", - "output_plot", - "output_image", - "output_text", - "output_text_verbatim", - "output_table", - "output_ui", "Progress", - "output_data_frame", "value_box_theme", # Imports from ._cm_components "sidebar", @@ -301,6 +283,17 @@ "showcase_bottom", "showcase_left_center", "showcase_top_right", + # Outputs automatically placed by render functions + "download_button", + "download_link", + "output_plot", + "output_image", + "output_text", + "output_code", + "output_text_verbatim", + "output_table", + "output_ui", + "output_data_frame", ), # Items from shiny.express.ui that don't have a counterpart in shiny.ui "shiny.express.ui": ("page_opts",), diff --git a/shiny/render/__init__.py b/shiny/render/__init__.py index ce47f4f64..a1876c33f 100644 --- a/shiny/render/__init__.py +++ b/shiny/render/__init__.py @@ -15,6 +15,7 @@ display, ) from ._render import ( + code, image, plot, table, @@ -28,6 +29,7 @@ "data_frame", "display", "text", + "code", "plot", "image", "table", diff --git a/shiny/render/_dataframe.py b/shiny/render/_dataframe.py index 246aab89f..6ecdc55d5 100644 --- a/shiny/render/_dataframe.py +++ b/shiny/render/_dataframe.py @@ -256,7 +256,7 @@ class data_frame(Renderer[DataFrameResult]): objects you can return from the rendering function to specify options. """ - def default_ui(self, id: str) -> Tag: + def auto_output_ui(self, id: str) -> Tag: return ui.output_data_frame(id=id) async def transform(self, value: DataFrameResult) -> Jsonifiable: diff --git a/shiny/render/_display.py b/shiny/render/_display.py index 593cdda4d..da597a9f1 100644 --- a/shiny/render/_display.py +++ b/shiny/render/_display.py @@ -18,7 +18,7 @@ class display(Renderer[None]): - def default_ui( + def auto_output_ui( self, id: str, *, diff --git a/shiny/render/_render.py b/shiny/render/_render.py index 5d03a2a6d..426e319f2 100644 --- a/shiny/render/_render.py +++ b/shiny/render/_render.py @@ -9,6 +9,7 @@ # Can use `dict` in python >= 3.9 from typing import ( TYPE_CHECKING, + Any, Callable, Literal, Optional, @@ -46,6 +47,7 @@ __all__ = ( "text", + "code", "plot", "image", "table", @@ -61,6 +63,17 @@ class text(Renderer[str]): """ Reactively render text. + When used in Shiny Express applications, this defaults to displaying the text as + normal text on the web page. When used in Shiny Core applications, this should be + paired with :func:`~shiny.ui.output_text` in the UI. + + + Parameters + ---------- + inline + (Express only). If ``True``, the result is displayed inline. (This argument is + passed to :func:`~shiny.ui.output_text`.) + Returns ------- : @@ -74,13 +87,90 @@ class text(Renderer[str]): See Also -------- - ~shiny.ui.output_text + * ~shiny.render.code + * ~shiny.ui.output_text + """ + + def auto_output_ui( + self, + id: str, + *, + inline: bool | MISSING_TYPE = MISSING, + ) -> Tag: + kwargs: dict[str, Any] = {} + set_kwargs_value(kwargs, "inline", inline, self.inline) + + return _ui.output_text(id, **kwargs) + + def __init__( + self, + _fn: Optional[ValueFn[str | None]] = None, + *, + inline: bool = False, + ) -> None: + super().__init__(_fn) + self.inline: bool = inline + + async def transform(self, value: str) -> Jsonifiable: + return str(value) + + +# ====================================================================================== +# RenderCode +# ====================================================================================== + + +class code(Renderer[str]): + """ + Reactively render text as code (monospaced). + + When used in Shiny Express applications, this defaults to displaying the text in a + monospace font in a code block. When used in Shiny Core applications, this should be + paired with :func:`~shiny.ui.output_code` in the UI. + + Parameters + ---------- + placeholder + (Express only) If the output is empty or ``None``, should an empty rectangle be + displayed to serve as a placeholder? This does not affect behavior when the + output is nonempty. (This argument is passed to :func:`~shiny.ui.output_code`.) + + + Returns + ------- + : + A decorator for a function that returns a string. + + Tip + ---- + The name of the decorated function (or ``@output(id=...)``) should match the ``id`` + of a :func:`~shiny.ui.output_code` container (see :func:`~shiny.ui.output_code` for + example usage). + + See Also + -------- + * ~shiny.render.code + * ~shiny.ui.output_code """ - def default_ui(self, id: str, placeholder: bool | MISSING_TYPE = MISSING) -> Tag: + def auto_output_ui( + self, + id: str, + *, + placeholder: bool | MISSING_TYPE = MISSING, + ) -> Tag: kwargs: dict[str, bool] = {} - set_kwargs_value(kwargs, "placeholder", placeholder, None) - return _ui.output_text_verbatim(id, **kwargs) + set_kwargs_value(kwargs, "placeholder", placeholder, self.placeholder) + return _ui.output_code(id, **kwargs) + + def __init__( + self, + _fn: Optional[ValueFn[str | None]] = None, + *, + placeholder: bool = True, + ) -> None: + super().__init__(_fn) + self.placeholder = placeholder async def transform(self, value: str) -> Jsonifiable: return str(value) @@ -147,10 +237,11 @@ class plot(Renderer[object]): See Also -------- - ~shiny.ui.output_plot ~shiny.render.image + * ~shiny.ui.output_plot + * ~shiny.render.image """ - def default_ui( + def auto_output_ui( self, id: str, *, @@ -166,6 +257,7 @@ def default_ui( # (possibly) contains `width` and `height` keys! **kwargs, # pyright: ignore[reportGeneralTypeIssues] ) + # TODO: Deal with output width/height separately from render width/height? def __init__( self, @@ -316,16 +408,17 @@ class image(Renderer[ImgData]): See Also -------- - ~shiny.ui.output_image - ~shiny.types.ImgData - ~shiny.render.plot + * ~shiny.ui.output_image + * ~shiny.types.ImgData + * ~shiny.render.plot """ - def default_ui(self, id: str, **kwargs: object): + def auto_output_ui(self, id: str, **kwargs: object): return _ui.output_image( id, **kwargs, # pyright: ignore[reportGeneralTypeIssues] ) + # TODO: Make width/height handling consistent with render_plot def __init__( self, @@ -334,7 +427,8 @@ def __init__( delete_file: bool = False, ) -> None: super().__init__(_fn) - self.delete_file: bool = delete_file + + self.delete_file = delete_file async def transform(self, value: ImgData) -> dict[str, Jsonifiable] | None: src: str = value.get("src") @@ -409,11 +503,12 @@ class table(Renderer[TableResult]): See Also -------- - ~shiny.ui.output_table for the corresponding UI component to this render function. + * ~shiny.ui.output_table for the corresponding UI component to this render function. """ - def default_ui(self, id: str, **kwargs: TagAttrValue) -> Tag: + def auto_output_ui(self, id: str, **kwargs: TagAttrValue) -> Tag: return _ui.output_table(id, **kwargs) + # TODO: Deal with kwargs def __init__( self, @@ -430,6 +525,8 @@ def __init__( self.border: int = border self.kwargs: dict[str, object] = kwargs + # TODO: deal with kwargs collision with output_table + async def transform(self, value: TableResult) -> dict[str, Jsonifiable]: import pandas import pandas.io.formats.style @@ -485,10 +582,10 @@ class ui(Renderer[TagChild]): See Also -------- - ~shiny.ui.output_ui + * ~shiny.ui.output_ui """ - def default_ui(self, id: str) -> Tag: + def auto_output_ui(self, id: str) -> Tag: return _ui.output_ui(id) async def transform(self, value: TagChild) -> Jsonifiable: @@ -509,12 +606,12 @@ class download(Renderer[str]): ---------- filename The filename of the download. - label - A label for the button, when used in Express mode. Defaults to "Download". media_type The media type of the download. encoding The encoding of the download. + label + (Express only) A label for the button. Defaults to "Download". Returns ------- @@ -523,27 +620,30 @@ class download(Renderer[str]): See Also -------- - ~shiny.ui.download_button + * ~shiny.ui.download_button """ - def default_ui(self, id: str) -> Tag: - return _ui.download_button(id, label=self.label) + def auto_output_ui(self, id: str) -> Tag: + return _ui.download_button( + id, + label=self.label, + ) def __init__( self, fn: Optional[DownloadHandler] = None, *, filename: Optional[str | Callable[[], str]] = None, - label: TagChild = "Download", media_type: None | str | Callable[[], str] = None, encoding: str = "utf-8", + label: TagChild = "Download", ) -> None: super().__init__() - self.label = label self.filename = filename self.media_type = media_type self.encoding = encoding + self.label = label if fn is not None: self(fn) diff --git a/shiny/render/renderer/_renderer.py b/shiny/render/renderer/_renderer.py index cb0bbd04a..a76519257 100644 --- a/shiny/render/renderer/_renderer.py +++ b/shiny/render/renderer/_renderer.py @@ -102,8 +102,8 @@ class RendererBase(ABC): # Q: Could we do this with typing without putting `P` in the Generic? # A: No. Even if we had a `P` in the Generic, the calling decorator would not have access to it. # Idea: Possibly use a chained method of `.ui_kwargs()`? https://github.com/posit-dev/py-shiny/issues/971 - _default_ui_kwargs: dict[str, Any] = dict() - # _default_ui_args: tuple[Any, ...] = tuple() + _auto_output_ui_kwargs: dict[str, Any] = dict() + # _auto_output_ui_args: tuple[Any, ...] = tuple() __name__: str """ @@ -135,7 +135,7 @@ def _set_output_metadata( """ self.output_id = output_name - def default_ui( + def auto_output_ui( self, id: str, # *args: object, @@ -155,13 +155,13 @@ def __init__(self) -> None: # Tagify-like methods # ###### def _repr_html_(self) -> str | None: - rendered_ui = self._render_default_ui() + rendered_ui = self._render_auto_output_ui() if rendered_ui is None: return None return TagList(rendered_ui)._repr_html_() def tagify(self) -> DefaultUIFnResult: - rendered_ui = self._render_default_ui() + rendered_ui = self._render_auto_output_ui() if rendered_ui is None: raise TypeError( "No default UI exists for this type of render function: ", @@ -169,11 +169,11 @@ def tagify(self) -> DefaultUIFnResult: ) return rendered_ui - def _render_default_ui(self) -> DefaultUIFnResultOrNone: - return self.default_ui( + def _render_auto_output_ui(self) -> DefaultUIFnResultOrNone: + return self.auto_output_ui( self.__name__, - # Pass the `@ui_kwargs(foo="bar")` kwargs through to the default_ui function. - **self._default_ui_kwargs, + # Pass the `@output_args(foo="bar")` kwargs through to the auto_output_ui function. + **self._auto_output_ui_kwargs, ) # ###### diff --git a/shiny/render/transformer/_transformer.py b/shiny/render/transformer/_transformer.py index bb7315d18..114c88269 100644 --- a/shiny/render/transformer/_transformer.py +++ b/shiny/render/transformer/_transformer.py @@ -266,11 +266,11 @@ def __init__( self._transformer = transform_fn self._params = params - self._default_ui = default_ui - self._default_ui_passthrough_args = default_ui_passthrough_args + self._auto_output_ui = default_ui + self._auto_output_ui_passthrough_args = default_ui_passthrough_args - self._default_ui_args: tuple[object, ...] = tuple() - self._default_ui_kwargs: dict[str, object] = dict() + self._auto_output_ui_args: tuple[object, ...] = tuple() + self._auto_output_ui_kwargs: dict[str, object] = dict() # Allow for App authors to not require `@output` self._auto_register() @@ -318,24 +318,24 @@ async def _run(self) -> OT: # # Shims for Renderer class ############################# - def default_ui( + def auto_output_ui( self, id: str, **kwargs: object, ) -> DefaultUIFnResultOrNone: - if self._default_ui is None: + if self._auto_output_ui is None: return None - if self._default_ui_passthrough_args is not None: + if self._auto_output_ui_passthrough_args is not None: kwargs.update( { k: v for k, v in self._params.kwargs.items() - if k in self._default_ui_passthrough_args and v is not MISSING + if k in self._auto_output_ui_passthrough_args and v is not MISSING } ) - return self._default_ui(id, *self._default_ui_args, **kwargs) + return self._auto_output_ui(id, *self._auto_output_ui_args, **kwargs) async def render(self) -> Jsonifiable: ret = await self._run() diff --git a/shiny/templates/package-templates/js-output/custom_component/custom_component.py b/shiny/templates/package-templates/js-output/custom_component/custom_component.py index 2dd5f13a8..1bf568912 100644 --- a/shiny/templates/package-templates/js-output/custom_component/custom_component.py +++ b/shiny/templates/package-templates/js-output/custom_component/custom_component.py @@ -27,7 +27,7 @@ class render_custom_component(Renderer[int]): """ # The UI used within Shiny Express mode - def default_ui(self, id: str) -> Tag: + def auto_output_ui(self, id: str) -> Tag: return custom_component(id, height=self.height) # The init method is used to set up the renderer's parameters. diff --git a/shiny/templates/package-templates/js-react/custom_component/custom_component.py b/shiny/templates/package-templates/js-react/custom_component/custom_component.py index a8dc26c99..f68f90a12 100644 --- a/shiny/templates/package-templates/js-react/custom_component/custom_component.py +++ b/shiny/templates/package-templates/js-react/custom_component/custom_component.py @@ -39,7 +39,7 @@ class render_custom_component(Renderer[str]): """ # The UI used within Shiny Express mode - def default_ui(self, id: str) -> Tag: + def auto_output_ui(self, id: str) -> Tag: return output_custom_component(id) # # There are no parameters being supplied to the `output_custom_component` rendering function. diff --git a/shiny/ui/__init__.py b/shiny/ui/__init__.py index 49a725aab..70cc4108d 100644 --- a/shiny/ui/__init__.py +++ b/shiny/ui/__init__.py @@ -110,6 +110,7 @@ output_plot, output_image, output_text, + output_code, output_text_verbatim, output_table, output_ui, @@ -296,6 +297,7 @@ "output_plot", "output_image", "output_text", + "output_code", "output_text_verbatim", "output_table", "output_ui", diff --git a/shiny/ui/_output.py b/shiny/ui/_output.py index 7accac6a1..aab99a35a 100644 --- a/shiny/ui/_output.py +++ b/shiny/ui/_output.py @@ -4,6 +4,7 @@ "output_plot", "output_image", "output_text", + "output_code", "output_text_verbatim", "output_table", "output_ui", @@ -270,6 +271,47 @@ def output_text( return container(id=resolve_id(id), class_="shiny-text-output") +def output_code(id: str, placeholder: bool = True) -> Tag: + """ + Create a output container for code (monospaced text). + + This is similar to :func:`~shiny.ui.output_text`, except that it displays the text + in a fixed-width container with a gray-ish background color and border. + + Parameters + ---------- + id + An output id. + placeholder + If the output is empty or ``None``, should an empty rectangle be displayed to + serve as a placeholder? (This does not affect behavior when the output is + nonempty.) + + Returns + ------- + : + A UI element + + Note + ---- + This function is currently the same as :func:`~shiny.ui.output_text_verbatim`, but + this may change in future versions of Shiny. + + See Also + -------- + * :func:`~shiny.render.text` + * :func:`~shiny.ui.output_text` + * :func:`~shiny.ui.output_text_verbatim` + + Example + ------- + See :func:`~shiny.ui.output_text` + """ + + cls = "shiny-text-output" + (" noplaceholder" if not placeholder else "") + return tags.pre(id=resolve_id(id), class_=cls) + + def output_text_verbatim(id: str, placeholder: bool = False) -> Tag: """ Create a output container for some text. diff --git a/tests/playwright/controls.py b/tests/playwright/controls.py index c27becd07..8fdcc7d76 100644 --- a/tests/playwright/controls.py +++ b/tests/playwright/controls.py @@ -2174,6 +2174,7 @@ def __init__( super().__init__(page, id=id, loc=f"#{id}.shiny-text-output") +# TODO-Karan: Add OutputCode class class OutputTextVerbatim(_OutputTextValue): def __init__(self, page: Page, id: str) -> None: super().__init__(page, id=id, loc=f"pre#{id}.shiny-text-output") diff --git a/tests/playwright/shiny/shiny-express/page_fillable/app.py b/tests/playwright/shiny/shiny-express/page_fillable/app.py index 94e8b2a99..573e65fdb 100644 --- a/tests/playwright/shiny/shiny-express/page_fillable/app.py +++ b/tests/playwright/shiny/shiny-express/page_fillable/app.py @@ -6,6 +6,6 @@ with ui.card(id="card"): ui.input_slider("a", "A", 1, 100, 50) - @render.text + @render.code def txt(): return input.a() diff --git a/tests/playwright/shiny/shiny-express/page_fluid/app.py b/tests/playwright/shiny/shiny-express/page_fluid/app.py index 54fd50c64..1f5c0dae4 100644 --- a/tests/playwright/shiny/shiny-express/page_fluid/app.py +++ b/tests/playwright/shiny/shiny-express/page_fluid/app.py @@ -6,6 +6,6 @@ with ui.card(id="card"): ui.input_slider("a", "A", 1, 100, 50) - @render.text + @render.code def txt(): return input.a() diff --git a/tests/playwright/shiny/shiny-express/page_sidebar/app.py b/tests/playwright/shiny/shiny-express/page_sidebar/app.py index 8168abf73..455326083 100644 --- a/tests/playwright/shiny/shiny-express/page_sidebar/app.py +++ b/tests/playwright/shiny/shiny-express/page_sidebar/app.py @@ -9,6 +9,6 @@ with ui.card(id="card"): ui.input_slider("a", "A", 1, 100, 50) - @render.text + @render.code def txt(): return input.a() diff --git a/tests/playwright/shiny/shiny-express/suspend_display/app.py b/tests/playwright/shiny/shiny-express/suspend_display/app.py index 14baf6df7..4f4b510ef 100644 --- a/tests/playwright/shiny/shiny-express/suspend_display/app.py +++ b/tests/playwright/shiny/shiny-express/suspend_display/app.py @@ -5,7 +5,7 @@ ui.input_slider("s1", "A", 1, 100, 20) @suspend_display - @render.text + @render.code def hidden(): return input.s1() @@ -14,7 +14,7 @@ def hidden(): # from shiny.express import ui_kwargs # @ui_kwargs(placeholder=False) # @ui_kwargs(placeholder=True) - @render.text() + @render.code() def visible(): # from shiny import req diff --git a/tests/pytest/test_display_decorator.py b/tests/pytest/test_display_decorator.py index bfdb51b7e..aa8f330dc 100644 --- a/tests/pytest/test_display_decorator.py +++ b/tests/pytest/test_display_decorator.py @@ -165,7 +165,7 @@ def annotated(x: int, y: int) -> int: def test_implicit_output(): @display_body() def has_implicit_outputs(): - @render.text + @render.code def foo(): return "hello" @@ -173,7 +173,7 @@ def foo(): has_implicit_outputs() assert len(d) == 1 d0 = cast(Tagifiable, d[0]) - assert d0.tagify() == ui.output_text_verbatim("foo") + assert d0.tagify() == ui.output_code("foo") def test_no_nested_transform_unless_explicit(): diff --git a/tests/pytest/test_express_ui.py b/tests/pytest/test_express_ui.py index 2f5a7cc0d..0c1afcb43 100644 --- a/tests/pytest/test_express_ui.py +++ b/tests/pytest/test_express_ui.py @@ -6,7 +6,7 @@ import pytest from shiny import render, ui -from shiny.express import suspend_display, ui_kwargs +from shiny.express import output_args, suspend_display from shiny.express._run import run_express @@ -50,7 +50,7 @@ def text1(): assert ( ui.TagList(text1.tagify()).get_html_string() - == ui.output_text_verbatim("text1").get_html_string() + == ui.output_text("text1").get_html_string() ) @suspend_display @@ -60,23 +60,23 @@ def text2(): assert ui.TagList(text2.tagify()).get_html_string() == "" - @ui_kwargs(placeholder=True) - @render.text - def text3(): + @output_args(placeholder=False) + @render.code + def code1(): return "text" assert ( - ui.TagList(text3.tagify()).get_html_string() - == ui.output_text_verbatim("text3", placeholder=True).get_html_string() + ui.TagList(code1.tagify()).get_html_string() + == ui.output_code("code1", placeholder=False).get_html_string() ) - @ui_kwargs(width=100) - @render.text - def text4(): + @output_args(width=100) + @render.code + def code2(): return "text" with pytest.raises(TypeError, match="width"): - text4.tagify() + code2.tagify() def test_suspend_display(): diff --git a/tests/pytest/test_plot_sizing.py b/tests/pytest/test_plot_sizing.py index da6a354fc..4390f85f2 100644 --- a/tests/pytest/test_plot_sizing.py +++ b/tests/pytest/test_plot_sizing.py @@ -1,5 +1,5 @@ from shiny import render, ui -from shiny.express import ui_kwargs +from shiny.express import output_args from shiny.types import MISSING @@ -27,10 +27,10 @@ def foo(): assert rendered == str(ui.output_plot("foo")) -def test_decorator_ui_kwargs(): - """@ui_kwargs is respected""" +def test_decorator_output_args(): + """@output_args is respected""" - @ui_kwargs(width="640px", height="480px") + @output_args(width="640px", height="480px") @render.plot() def foo(): ... @@ -39,10 +39,10 @@ def foo(): assert rendered == str(ui.output_plot("foo", width="640px", height="480px")) -def test_decorator_ui_kwargs_priority(): - """@ui_kwargs should override render.plot width/height""" +def test_decorator_output_args_priority(): + """@output_args should override render.plot width/height""" - @ui_kwargs(width="640px", height=480) + @output_args(width="640px", height=480) @render.plot(width=1280, height=960) def foo(): ... @@ -52,10 +52,10 @@ def foo(): assert rendered == str(ui.output_plot("foo", width=640, height="480px")) -def test_decorator_ui_kwargs_MISSING(): +def test_decorator_output_args_MISSING(): """Not saying we support this, but test how MISSING interacts""" - @ui_kwargs(width=MISSING) + @output_args(width=MISSING) @render.plot(width=1280, height=MISSING) def foo(): ...