|
59 | 59 | from ._utils import RenderedDeps, read_thunk_opt, session_context |
60 | 60 |
|
61 | 61 | if TYPE_CHECKING: |
| 62 | + from shiny.bookmark._serializers import Unserializable |
| 63 | + |
62 | 64 | from .._app import App |
63 | 65 |
|
64 | 66 |
|
| 67 | +BookmarkStore = Literal["url", "server", "disable"] |
| 68 | + |
| 69 | + |
65 | 70 | class ConnectionState(enum.Enum): |
66 | 71 | Start = 0 |
67 | 72 | Running = 1 |
@@ -171,6 +176,9 @@ class Session(ABC): |
171 | 176 | input: Inputs |
172 | 177 | output: Outputs |
173 | 178 | clientdata: ClientData |
| 179 | + bookmark_exclude: list[str] |
| 180 | + bookmark_store: BookmarkStore |
| 181 | + _bookmark_exclude_fns: list[Callable[[], list[str]]] |
174 | 182 | user: str | None |
175 | 183 | groups: list[str] | None |
176 | 184 |
|
@@ -477,6 +485,38 @@ def _increment_busy_count(self) -> None: ... |
477 | 485 | @abstractmethod |
478 | 486 | def _decrement_busy_count(self) -> None: ... |
479 | 487 |
|
| 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 | + |
480 | 520 |
|
481 | 521 | # ====================================================================================== |
482 | 522 | # AppSession |
@@ -522,6 +562,10 @@ def __init__( |
522 | 562 | self.output: Outputs = Outputs(self, self.ns, outputs=dict()) |
523 | 563 | self.clientdata: ClientData = ClientData(self) |
524 | 564 |
|
| 565 | + self.bookmark_exclude: list[str] = [] |
| 566 | + self.bookmark_store = "disable" |
| 567 | + self._bookmark_exclude_fns: list[Callable[[], list[str]]] = [] |
| 568 | + |
525 | 569 | self.user: str | None = None |
526 | 570 | self.groups: list[str] | None = None |
527 | 571 | credentials_json: str = "" |
@@ -711,6 +755,21 @@ def _is_hidden(self, name: str) -> bool: |
711 | 755 |
|
712 | 756 | return hidden_value_obj() |
713 | 757 |
|
| 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 | + |
714 | 773 | # ========================================================================== |
715 | 774 | # Message handlers |
716 | 775 | # ========================================================================== |
@@ -1173,9 +1232,32 @@ def __init__(self, parent: Session, ns: ResolvedId) -> None: |
1173 | 1232 | self._outbound_message_queues = parent._outbound_message_queues |
1174 | 1233 | self._downloads = parent._downloads |
1175 | 1234 |
|
| 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 | + |
1176 | 1242 | def _is_hidden(self, name: str) -> bool: |
1177 | 1243 | return self._parent._is_hidden(name) |
1178 | 1244 |
|
| 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 | + |
1179 | 1261 | def on_ended( |
1180 | 1262 | self, |
1181 | 1263 | fn: Callable[[], None] | Callable[[], Awaitable[None]], |
|
0 commit comments