Skip to content

Commit 25ba8b4

Browse files
committed
Set up bookmark exclude and bookmark store
1 parent 505e027 commit 25ba8b4

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

shiny/express/_stub_session.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,21 @@ def __init__(self, ns: ResolvedId = Root):
4444
# Application-level (not session-level) options that may be set via app_opts().
4545
self.app_opts: AppOpts = {}
4646

47+
self.bookmark_exclude = []
48+
self.bookmark_store = "disable" # TODO: Is this correct?
49+
4750
def is_stub_session(self) -> Literal[True]:
4851
return True
4952

5053
async def close(self, code: int = 1001) -> None:
5154
return
5255

56+
def _get_bookmark_exclude(self) -> list[str]:
57+
raise NotImplementedError("Please call this only from a real session object")
58+
59+
def do_bookmark(self) -> None:
60+
raise NotImplementedError("Please call this only from a real session object")
61+
5362
# This is needed so that Outputs don't throw an error.
5463
def _is_hidden(self, name: str) -> bool:
5564
return False

shiny/session/_session.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,14 @@
5959
from ._utils import RenderedDeps, read_thunk_opt, session_context
6060

6161
if TYPE_CHECKING:
62+
from shiny.bookmark._serializers import Unserializable
63+
6264
from .._app import App
6365

6466

67+
BookmarkStore = Literal["url", "server", "disable"]
68+
69+
6570
class ConnectionState(enum.Enum):
6671
Start = 0
6772
Running = 1
@@ -171,6 +176,9 @@ class Session(ABC):
171176
input: Inputs
172177
output: Outputs
173178
clientdata: ClientData
179+
bookmark_exclude: list[str]
180+
bookmark_store: BookmarkStore
181+
_bookmark_exclude_fns: list[Callable[[], list[str]]]
174182
user: str | None
175183
groups: list[str] | None
176184

@@ -477,6 +485,38 @@ def _increment_busy_count(self) -> None: ...
477485
@abstractmethod
478486
def _decrement_busy_count(self) -> None: ...
479487

488+
@abstractmethod
489+
def _get_bookmark_exclude(self) -> list[str]:
490+
"""
491+
Retrieve the list of inputs excluded from being bookmarked.
492+
"""
493+
...
494+
495+
@abstractmethod
496+
def do_bookmark(self) -> None:
497+
"""
498+
Perform bookmarking.
499+
500+
This method will also call the `on_bookmark` and `on_bookmarked` callbacks to alter the bookmark state. Then, the bookmark state will be either saved to the server or encoded in the URL, depending on the `bookmark_store` option.
501+
502+
No actions will be performed if the `bookmark_store` option is set to `"disable"`.
503+
"""
504+
...
505+
506+
# @abstractmethod
507+
# def set_bookmark_exclude(self, *names: str) -> None:
508+
# """
509+
# Exclude inputs from being bookmarked.
510+
# """
511+
# ...
512+
513+
# @abstractmethod
514+
# def get_bookmark_exclude(self) -> list[str]:
515+
# """
516+
# Get the list of inputs excluded from being bookmarked.
517+
# """
518+
# ...
519+
480520

481521
# ======================================================================================
482522
# AppSession
@@ -522,6 +562,10 @@ def __init__(
522562
self.output: Outputs = Outputs(self, self.ns, outputs=dict())
523563
self.clientdata: ClientData = ClientData(self)
524564

565+
self.bookmark_exclude: list[str] = []
566+
self.bookmark_store = "disable"
567+
self._bookmark_exclude_fns: list[Callable[[], list[str]]] = []
568+
525569
self.user: str | None = None
526570
self.groups: list[str] | None = None
527571
credentials_json: str = ""
@@ -711,6 +755,21 @@ def _is_hidden(self, name: str) -> bool:
711755

712756
return hidden_value_obj()
713757

758+
# ==========================================================================
759+
# Bookmarking
760+
# ==========================================================================
761+
762+
def _get_bookmark_exclude(self) -> list[str]:
763+
"""
764+
Get the list of inputs excluded from being bookmarked.
765+
"""
766+
scoped_excludes: list[str] = []
767+
for exclude_fn in self._bookmark_exclude_fns:
768+
# Call the function and append the result to the list
769+
scoped_excludes.extend(exclude_fn())
770+
# Remove duplicates
771+
return list(set([*self.bookmark_exclude, *scoped_excludes]))
772+
714773
# ==========================================================================
715774
# Message handlers
716775
# ==========================================================================
@@ -1173,9 +1232,32 @@ def __init__(self, parent: Session, ns: ResolvedId) -> None:
11731232
self._outbound_message_queues = parent._outbound_message_queues
11741233
self._downloads = parent._downloads
11751234

1235+
self.bookmark_exclude: list[str] = []
1236+
1237+
def ns_bookmark_exclude() -> list[str]:
1238+
return [self.ns(name) for name in self.bookmark_exclude]
1239+
1240+
self._parent._bookmark_exclude_fns.append(ns_bookmark_exclude)
1241+
11761242
def _is_hidden(self, name: str) -> bool:
11771243
return self._parent._is_hidden(name)
11781244

1245+
def _get_bookmark_exclude(self) -> list[str]:
1246+
raise NotImplementedError(
1247+
"Please call `._get_bookmark_exclude()` from the root session only."
1248+
)
1249+
1250+
@property
1251+
def bookmark_store(self) -> BookmarkStore:
1252+
return self._parent.bookmark_store
1253+
1254+
@bookmark_store.setter
1255+
def bookmark_store( # pyright: ignore[reportIncompatibleVariableOverride]
1256+
self,
1257+
value: BookmarkStore,
1258+
) -> None:
1259+
self._parent.bookmark_store = value
1260+
11791261
def on_ended(
11801262
self,
11811263
fn: Callable[[], None] | Callable[[], Awaitable[None]],

0 commit comments

Comments
 (0)