Skip to content

Commit 4fc66b3

Browse files
committed
Leverage htmltools's new HTML/UserString and TagList/UserList objects by not needing to manually inspect reasonable cell
1 parent da98bd8 commit 4fc66b3

File tree

1 file changed

+21
-29
lines changed

1 file changed

+21
-29
lines changed

shiny/render/_data_frame_utils/_tbl_data.py

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import narwhals.stable.v1 as nw
66
import orjson
7-
from htmltools import TagNode
87

98
from ..._typing_extensions import TypeIs
109
from ...session import Session, require_active_session
@@ -240,47 +239,40 @@ def serialize_frame(into_data: IntoDataFrame) -> FrameJson:
240239
data = as_data_frame(into_data)
241240

242241
type_hints = [serialize_dtype(data[col_name]) for col_name in data.columns]
243-
type_hints_type = [type_hint["type"] for type_hint in type_hints]
244242

243+
# TODO-future-barret; Swich serialization to "by column", rather than "by row"
244+
# * This would allow for a single column to be serialized in a single operation
245+
# * This would allow for each column to capture the `"html"` type hint properly
246+
# for object and unknown columns. Currently, there is no way to determine which
247+
# cells are HTML-like during orjson serialization.
248+
# * Even better, would be to move `orjson` serialization to the websocket
249+
# serialization.
250+
# * No need to serialize to JSON, then unserialize, then serialize again when
251+
# sending it to the client!
252+
# * The only serialization would occur during "send to browser"
253+
# * This approach would lose the ability to upgrade the column type hints to "html"
245254
data_rows = data.rows(named=False)
246255

247-
# Shiny tag support
248-
if "html" in type_hints_type:
249-
session = require_active_session(None)
256+
session: Session | None = None
250257

251-
def wrap_shiny_html_with_session(x: TagNode):
252-
return maybe_as_cell_html(x, session=session)
258+
def default_orjson_serializer(val: Any) -> Jsonifiable:
259+
nonlocal session
260+
if ui_must_be_processed(val):
261+
if session is None:
262+
session = require_active_session(None)
263+
return cast(JsonifiableDict, dict(as_cell_html(val, session=session)))
253264

254-
html_column_positions = [
255-
i for i, x in enumerate(type_hints_type) if x == "html"
256-
]
257-
258-
new_rows: list[tuple[Any, ...]] = []
259-
260-
# Wrap the corresponding columns with the cell html object
261-
for row in data_rows:
262-
new_row = list(row)
263-
for html_column_position in html_column_positions:
264-
new_row[html_column_position] = wrap_shiny_html_with_session(
265-
new_row[html_column_position]
266-
)
267-
new_rows.append(tuple(new_row))
268-
269-
data_rows = new_rows
270-
271-
# _ = datetime(5)
265+
# All other values are serialized as strings
266+
return str(val)
272267

273268
data_val = orjson.loads(
274269
orjson.dumps(
275270
data_rows,
276-
default=str,
271+
default=default_orjson_serializer,
277272
# option=(orjson.OPT_NAIVE_UTC),
278273
)
279274
)
280275

281-
# import json
282-
# data_val = json.loads(json.dumps(data_rows, default=str))
283-
284276
return {
285277
"columns": data.columns,
286278
"data": data_val,

0 commit comments

Comments
 (0)