|
4 | 4 |
|
5 | 5 | import narwhals.stable.v1 as nw |
6 | 6 | import orjson |
7 | | -from htmltools import TagNode |
8 | 7 |
|
9 | 8 | from ..._typing_extensions import TypeIs |
10 | 9 | from ...session import Session, require_active_session |
@@ -240,47 +239,40 @@ def serialize_frame(into_data: IntoDataFrame) -> FrameJson: |
240 | 239 | data = as_data_frame(into_data) |
241 | 240 |
|
242 | 241 | 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] |
244 | 242 |
|
| 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" |
245 | 254 | data_rows = data.rows(named=False) |
246 | 255 |
|
247 | | - # Shiny tag support |
248 | | - if "html" in type_hints_type: |
249 | | - session = require_active_session(None) |
| 256 | + session: Session | None = None |
250 | 257 |
|
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))) |
253 | 264 |
|
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) |
272 | 267 |
|
273 | 268 | data_val = orjson.loads( |
274 | 269 | orjson.dumps( |
275 | 270 | data_rows, |
276 | | - default=str, |
| 271 | + default=default_orjson_serializer, |
277 | 272 | # option=(orjson.OPT_NAIVE_UTC), |
278 | 273 | ) |
279 | 274 | ) |
280 | 275 |
|
281 | | - # import json |
282 | | - # data_val = json.loads(json.dumps(data_rows, default=str)) |
283 | | - |
284 | 276 | return { |
285 | 277 | "columns": data.columns, |
286 | 278 | "data": data_val, |
|
0 commit comments