Skip to content

Commit 7851978

Browse files
authored
fix(bookmarking): Be able to set the default save/restore functions after app initialization (#1955)
1 parent 7cfabaa commit 7851978

File tree

5 files changed

+45
-15
lines changed

5 files changed

+45
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
## New features
1111

12-
* Added support for bookmarking Shiny applications. Bookmarking allows users to save the current state of an application and return to it later. This feature is available in both Shiny Core and Shiny Express. (#1870, #1915, #1919, #1920, #1922, #1934, #1938, #1945)
12+
* Added support for bookmarking Shiny applications. Bookmarking allows users to save the current state of an application and return to it later. This feature is available in both Shiny Core and Shiny Express. (#1870, #1915, #1919, #1920, #1922, #1934, #1938, #1945, #1955)
1313
* To enable bookmarking in Express mode, set `shiny.express.app_opts(bookmark_store=)` during the app's initial construction.
1414
* To enable bookmarking in Core mode, set `shiny.App(bookmark_store=)` when constructing the `app` object.
1515

shiny/_app.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
from ._error import ErrorMiddleware
3131
from ._shinyenv import is_pyodide
3232
from ._utils import guess_mime_type, is_async_callable, sort_keys_length
33-
from .bookmark import _global as bookmark_global_state
3433
from .bookmark._global import as_bookmark_dir_fn
3534
from .bookmark._restore_state import RestoreContext, restore_context
3635
from .bookmark._types import (
@@ -42,6 +41,7 @@
4241
from .html_dependencies import jquery_deps, require_deps, shiny_deps
4342
from .http_staticfiles import FileResponse, StaticFiles
4443
from .session._session import AppSession, Inputs, Outputs, Session, session_context
44+
from .types import MISSING, MISSING_TYPE
4545

4646
T = TypeVar("T")
4747

@@ -115,8 +115,8 @@ def server(input: Inputs, output: Outputs, session: Session):
115115
ui: RenderedHTML | Callable[[Request], Tag | TagList]
116116
server: Callable[[Inputs, Outputs, Session], None]
117117

118-
_bookmark_save_dir_fn: BookmarkSaveDirFn | None
119-
_bookmark_restore_dir_fn: BookmarkRestoreDirFn | None
118+
_bookmark_save_dir_fn: BookmarkSaveDirFn | None | MISSING_TYPE
119+
_bookmark_restore_dir_fn: BookmarkRestoreDirFn | None | MISSING_TYPE
120120
_bookmark_store: BookmarkStore
121121

122122
def __init__(
@@ -498,8 +498,8 @@ def _render_page_from_file(self, file: Path, lib_prefix: str) -> RenderedHTML:
498498
# ==========================================================================
499499

500500
def _init_bookmarking(self, *, bookmark_store: BookmarkStore, ui: Any) -> None:
501-
self._bookmark_save_dir_fn = bookmark_global_state.bookmark_save_dir
502-
self._bookmark_restore_dir_fn = bookmark_global_state.bookmark_restore_dir
501+
self._bookmark_save_dir_fn = MISSING
502+
self._bookmark_restore_dir_fn = MISSING
503503
self._bookmark_store = bookmark_store
504504

505505
if bookmark_store != "disable" and not callable(ui):

shiny/bookmark/_global.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,44 @@
33
from typing import overload
44

55
from .._utils import wrap_async
6+
from ..types import MISSING_TYPE
67
from ._types import (
78
BookmarkDirFn,
89
BookmarkDirFnAsync,
910
BookmarkRestoreDirFn,
1011
BookmarkSaveDirFn,
1112
)
1213

13-
# WARNING! This file contains global state!
14+
# WARNING! This file contains global default values!
15+
16+
1417
# During App initialization, the save_dir and restore_dir functions are conventionally set
1518
# to read-only on the App.
19+
# If nothing is set on the `app` object, the global default bookmark functions are found and used during every save/restore.
20+
_default_bookmark_save_dir_fn: BookmarkSaveDirFn | None = None
21+
_default_bookmark_restore_dir_fn: BookmarkRestoreDirFn | None = None
22+
23+
24+
def get_bookmark_save_dir_fn(
25+
save_dir_fn: BookmarkSaveDirFn | None | MISSING_TYPE,
26+
) -> BookmarkSaveDirFn | None:
27+
if isinstance(save_dir_fn, MISSING_TYPE):
28+
# Allow for default bookmark function to be utilized after app initialization.
29+
# Sometimes the app is created before hooks are registered.
30+
return _default_bookmark_save_dir_fn
31+
else:
32+
return save_dir_fn
1633

1734

18-
bookmark_save_dir: BookmarkSaveDirFn | None = None
19-
bookmark_restore_dir: BookmarkRestoreDirFn | None = None
35+
def get_bookmark_restore_dir_fn(
36+
restore_dir_fn: BookmarkRestoreDirFn | None | MISSING_TYPE,
37+
) -> BookmarkRestoreDirFn | None:
38+
if isinstance(restore_dir_fn, MISSING_TYPE):
39+
# Allow for default bookmark function to be utilized after app initialization.
40+
# Sometimes the app is created before hooks are registered.
41+
return _default_bookmark_restore_dir_fn
42+
else:
43+
return restore_dir_fn
2044

2145

2246
@overload
@@ -74,9 +98,9 @@ def restore_bookmark_dir(id: str) -> Path:
7498
--------
7599
* `~shiny.bookmark.set_global_restore_dir_fn` : Set the global bookmark restore directory function
76100
"""
77-
global bookmark_save_dir
101+
global _default_bookmark_save_dir_fn
78102

79-
bookmark_save_dir = as_bookmark_dir_fn(fn)
103+
_default_bookmark_save_dir_fn = as_bookmark_dir_fn(fn)
80104
return fn
81105

82106

@@ -118,7 +142,7 @@ def restore_bookmark_dir(id: str) -> Path:
118142
--------
119143
* `~shiny.bookmark.set_global_save_dir_fn` : Set the global bookmark save directory function.
120144
"""
121-
global bookmark_restore_dir
145+
global _default_bookmark_restore_dir_fn
122146

123-
bookmark_restore_dir = as_bookmark_dir_fn(fn)
147+
_default_bookmark_restore_dir_fn = as_bookmark_dir_fn(fn)
124148
return fn

shiny/bookmark/_restore_state.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .._docstring import add_example
1111
from ..module import ResolvedId
1212
from ._bookmark_state import local_restore_dir
13+
from ._global import get_bookmark_restore_dir_fn
1314
from ._types import BookmarkRestoreDirFn
1415
from ._utils import from_json_file, from_json_str, in_shiny_server
1516

@@ -189,7 +190,9 @@ async def _load_state_qs(self, query_string: str, *, app: App) -> None:
189190

190191
id = id[0]
191192

192-
load_bookmark_fn: BookmarkRestoreDirFn | None = app._bookmark_restore_dir_fn
193+
load_bookmark_fn: BookmarkRestoreDirFn | None = get_bookmark_restore_dir_fn(
194+
app._bookmark_restore_dir_fn
195+
)
193196

194197
if load_bookmark_fn is None:
195198
if in_shiny_server():

shiny/bookmark/_save_state.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .._utils import private_random_id
88
from ..reactive import isolate
99
from ._bookmark_state import local_save_dir
10+
from ._global import get_bookmark_save_dir_fn
1011
from ._types import BookmarkSaveDirFn
1112
from ._utils import in_shiny_server, to_json_file, to_json_str
1213

@@ -66,7 +67,9 @@ async def _save_state(self, *, app: App) -> str:
6667
# to `self.dir`.
6768

6869
# This will be defined by the hosting environment if it supports bookmarking.
69-
save_bookmark_fn: BookmarkSaveDirFn | None = app._bookmark_save_dir_fn
70+
save_bookmark_fn: BookmarkSaveDirFn | None = get_bookmark_save_dir_fn(
71+
app._bookmark_save_dir_fn
72+
)
7073

7174
if save_bookmark_fn is None:
7275
if in_shiny_server():

0 commit comments

Comments
 (0)