Skip to content

Commit 8925380

Browse files
authored
Allow for the model_id property to still be accessed after the widget is closed (#179)
1 parent a315cc7 commit 8925380

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [UNRELEASED] - 2025-01-23
99

1010
* Fixed an issue with plotly graphs sometimes not getting fully removed from the DOM. (#178)
11+
* Fixed an issue with ipyleaflet erroring out when attempting to read the `.model_id` property of a closed widget object. (#179)
1112

1213
## [0.4.2] - 2024-12-18
1314

shinywidgets/_comm.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from base64 import b64encode
2+
from dataclasses import dataclass
23
from typing import Callable, Dict, List, Optional
34

45
from shiny._utils import run_coro_hybrid
@@ -196,3 +197,30 @@ def handle_msg(self, msg: Dict[str, object]) -> None:
196197
def handle_close(self, msg: Dict[str, object]) -> None:
197198
if self._close_callback is not None:
198199
self._close_callback(msg)
200+
201+
202+
@dataclass
203+
class OrphanedShinyComm:
204+
"""
205+
A 'mock' `ShinyComm`. It's only purpose is to allow one to get
206+
the `model_id` (i.e., `comm_id`) of a widget after closing it.
207+
"""
208+
209+
comm_id: str
210+
211+
def send(
212+
self,
213+
*args: object,
214+
**kwargs: object,
215+
) -> None:
216+
pass
217+
218+
def close(
219+
self,
220+
*args: object,
221+
**kwargs: object,
222+
) -> None:
223+
pass
224+
225+
def on_msg(self, callback: MsgCallback) -> None:
226+
pass

shinywidgets/_shinywidgets.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
from ._as_widget import as_widget
2727
from ._cdn import SHINYWIDGETS_CDN_ONLY, SHINYWIDGETS_EXTENSION_WARNING
28-
from ._comm import BufferType, ShinyComm, ShinyCommManager
28+
from ._comm import BufferType, OrphanedShinyComm, ShinyComm, ShinyCommManager
2929
from ._dependencies import require_dependency
3030
from ._render_widget_base import has_current_context
3131
from ._utils import package_dir
@@ -134,7 +134,16 @@ def _cleanup_session_state():
134134
def on_close():
135135
with session_context(session):
136136
w.close()
137-
137+
# By closing the widget, we also close the comm, which sets w.comm to
138+
# None. Unfortunately, the w.model_id property looks up w.comm.comm_id
139+
# at runtime, and some packages like ipyleaflet want to use this id
140+
# to manage references between widgets.
141+
w.comm = OrphanedShinyComm(id)
142+
# Assigning a comm has the side-effect of adding back a reference to
143+
# the widget instance, so remove it again
144+
if id in WIDGET_INSTANCE_MAP:
145+
del WIDGET_INSTANCE_MAP[id]
146+
138147
ctx.on_invalidate(on_close)
139148

140149
# Keep track of what session this widget belongs to (so we can close it when the

0 commit comments

Comments
 (0)