Skip to content

Commit 6e90032

Browse files
committed
feat(express): Automatically suppress non-renderable UI objects
1 parent 36aa320 commit 6e90032

File tree

1 file changed

+41
-3
lines changed

1 file changed

+41
-3
lines changed

shiny/express/_recall_context.py

+41-3
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,53 @@
33
import functools
44
import sys
55
from types import TracebackType
6-
from typing import Callable, Generic, Mapping, Optional, Type, TypeVar
6+
from typing import Any, Callable, Generic, Mapping, Optional, Type, TypeVar
77

8-
from htmltools import MetadataNode, Tag, TagList, wrap_displayhook_handler
8+
from htmltools import (
9+
HTML,
10+
MetadataNode,
11+
ReprHtml,
12+
Tag,
13+
Tagifiable,
14+
TagList,
15+
wrap_displayhook_handler,
16+
)
917

1018
from .._typing_extensions import ParamSpec
19+
from ..render.renderer import Renderer
1120

1221
P = ParamSpec("P")
1322
R = TypeVar("R")
1423
U = TypeVar("U")
1524

1625

26+
def only_append_renderable(handler: Callable[[object], None]) -> Callable[[Any], None]:
27+
def f(x: Any):
28+
if isinstance(x, (list, tuple)):
29+
for item in x: # pyright: ignore[reportUnknownVariableType]
30+
f(item)
31+
return
32+
elif isinstance(x, (str, float, int, bool)):
33+
handler(x)
34+
return
35+
elif isinstance(x, (HTML, Tag, TagList, Tagifiable, ReprHtml, Renderer)):
36+
handler(x) # pyright: ignore[reportUnknownArgumentType]
37+
return
38+
39+
trunc_to = 80
40+
x_trunc = f"{x!r}"
41+
if len(x_trunc) > trunc_to:
42+
x_trunc = x_trunc[:trunc_to] + "..."
43+
44+
print(
45+
# TODO: Make this a more informative warning
46+
f"Express has suppressed the object `{x_trunc}` because it is of type {type(x)}. "
47+
"Coerce to HTML, a string, or an htmltools tag to display this object."
48+
)
49+
50+
return f
51+
52+
1753
class RecallContextManager(Generic[R]):
1854
def __init__(
1955
self,
@@ -31,7 +67,9 @@ def __init__(
3167
self.kwargs: dict[str, object] = dict(kwargs)
3268
# Let htmltools.wrap_displayhook_handler decide what to do with objects before
3369
# we append them.
34-
self.wrapped_append = wrap_displayhook_handler(self.args.append)
70+
self.wrapped_append = only_append_renderable(
71+
wrap_displayhook_handler(self.args.append)
72+
)
3573

3674
def __enter__(self) -> None:
3775
self._prev_displayhook = sys.displayhook

0 commit comments

Comments
 (0)