Skip to content

Commit d3b5c45

Browse files
committed
Input serializers and serializer method
1 parent ee1a47e commit d3b5c45

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

shiny/session/_session.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from shiny.bookmark._serializers import Unserializable
4+
35
__all__ = ("Session", "Inputs", "Outputs", "ClientData")
46

57
import asyncio
@@ -1357,6 +1359,75 @@ def __contains__(self, key: str) -> bool:
13571359
def __dir__(self):
13581360
return list(self._map.keys())
13591361

1362+
_serializers: dict[
1363+
str,
1364+
Callable[
1365+
[Any, Path | None],
1366+
Awaitable[Any | Unserializable],
1367+
],
1368+
]
1369+
1370+
# This method can not be on the `Value` class as the _value_ may not exist when the
1371+
# "creating" method is executed.
1372+
# Ex: File inputs do not _make_ the input reactive value. The browser does when the
1373+
# client sets the value.
1374+
def set_serializer(
1375+
self,
1376+
id: str,
1377+
fn: (
1378+
Callable[
1379+
[Any, Path | None],
1380+
Awaitable[Any | Unserializable],
1381+
]
1382+
| Callable[
1383+
[Any, Path | None],
1384+
Any | Unserializable,
1385+
]
1386+
),
1387+
) -> None:
1388+
"""
1389+
Add a function for serializing an input before bookmarking application state
1390+
1391+
Parameters
1392+
----------
1393+
id
1394+
The ID of the input value.
1395+
fn
1396+
A function that takes the input value and returns a modified value. The
1397+
returned value will be used for test snapshots and bookmarking.
1398+
"""
1399+
self._serializers[id] = wrap_async(fn)
1400+
1401+
async def _serialize(
1402+
self,
1403+
/,
1404+
*,
1405+
exclude: list[str],
1406+
state_dir: Path | None,
1407+
) -> dict[str, Any]:
1408+
from ..bookmark._serializers import serializer_default
1409+
1410+
exclude_set = set(exclude)
1411+
serialized_values: dict[str, Any] = {}
1412+
1413+
with reactive.isolate():
1414+
1415+
for key, value in self._map.items():
1416+
if key in exclude_set:
1417+
continue
1418+
val = value()
1419+
1420+
# Possibly apply custom serialization given the input id
1421+
serializer = self._serializers.get(key, serializer_default)
1422+
serialized_value = await serializer(val, state_dir)
1423+
1424+
# Filter out any values that were marked as unserializable.
1425+
if isinstance(serialized_value, Unserializable):
1426+
continue
1427+
serialized_values[key] = serialized_value
1428+
1429+
return serialized_values
1430+
13601431

13611432
@add_example()
13621433
class ClientData:

0 commit comments

Comments
 (0)