Skip to content

Commit 69272f9

Browse files
committed
Use JSON instead of pickle files for storage of bookmarks
1 parent b00d2a8 commit 69272f9

File tree

3 files changed

+24
-15
lines changed

3 files changed

+24
-15
lines changed

shiny/bookmark/_restore_state.py

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

3-
import pickle
43
import warnings
54
from contextlib import contextmanager
65
from contextvars import ContextVar, Token
@@ -11,7 +10,7 @@
1110
from ..module import ResolvedId
1211
from ._bookmark_state import local_restore_dir
1312
from ._types import BookmarkRestoreDirFn
14-
from ._utils import from_json_str, in_shiny_server
13+
from ._utils import from_json_file, from_json_str, in_shiny_server
1514

1615
if TYPE_CHECKING:
1716
from .._app import App
@@ -204,17 +203,15 @@ async def _load_state_qs(self, query_string: str, *, app: App) -> None:
204203
self.dir = Path(await load_bookmark_fn(id))
205204

206205
if not self.dir.exists():
207-
raise ValueError("Bookmarked state directory does not exist.")
206+
raise RuntimeError("Bookmarked state directory does not exist.")
208207

209208
# TODO: Barret; Store/restore as JSON
210-
with open(self.dir / "input.pickle", "rb") as f:
211-
input_values = pickle.load(f)
209+
input_values = from_json_file(self.dir / "input.json")
212210
self.input = RestoreInputSet(input_values)
213211

214-
values_file = self.dir / "values.pickle"
212+
values_file = self.dir / "values.json"
215213
if values_file.exists():
216-
with open(values_file, "rb") as f:
217-
self.values = pickle.load(f)
214+
self.values = from_json_file(values_file)
218215
# End load state from disk
219216

220217
return

shiny/bookmark/_save_state.py

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

3-
import pickle
43
from pathlib import Path
54
from typing import TYPE_CHECKING, Any, Awaitable, Callable
65
from urllib.parse import urlencode as urllib_urlencode
@@ -9,7 +8,7 @@
98
from ..reactive import isolate
109
from ._bookmark_state import local_save_dir
1110
from ._types import BookmarkSaveDirFn
12-
from ._utils import in_shiny_server, to_json_str
11+
from ._utils import in_shiny_server, to_json_file, to_json_str
1312

1413
if TYPE_CHECKING:
1514
from .. import Inputs
@@ -55,7 +54,7 @@ async def _call_on_save(self):
5554

5655
async def _save_state(self, *, app: App) -> str:
5756
"""
58-
Save a state to disk (pickle).
57+
Save a bookmark state to disk (JSON).
5958
6059
Returns
6160
-------
@@ -91,12 +90,10 @@ async def _save_state(self, *, app: App) -> str:
9190
)
9291
assert self.dir is not None
9392

94-
with open(self.dir / "input.pickle", "wb") as f:
95-
pickle.dump(input_values_json, f)
93+
to_json_file(input_values_json, self.dir / "input.json")
9694

9795
if len(self.values) > 0:
98-
with open(self.dir / "values.pickle", "wb") as f:
99-
pickle.dump(self.values, f)
96+
to_json_file(self.values, self.dir / "values.json")
10097
# End save to disk
10198

10299
# No need to encode URI component as it is only ascii characters.

shiny/bookmark/_utils.py

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

33
import os
4+
from pathlib import Path
45
from typing import Any
56

67
import orjson
@@ -21,3 +22,17 @@ def to_json_str(x: Any) -> str:
2122

2223
def from_json_str(x: str) -> Any:
2324
return orjson.loads(x)
25+
26+
27+
# When saving to a file, use plain text json.
28+
# (It's possible that we could store bytes, but unknown if there's any security benefit.)
29+
#
30+
# This makes the file contents independent of the json library used and
31+
# independent of the python version being used
32+
# (ex: pickle files are not compatible between python versions)
33+
def to_json_file(x: Any, file: Path) -> None:
34+
file.write_text(to_json_str(x), encoding="utf-8")
35+
36+
37+
def from_json_file(file: Path) -> Any:
38+
return from_json_str(file.read_text(encoding="utf-8"))

0 commit comments

Comments
 (0)