@@ -168,7 +168,14 @@ def on_close():
168
168
if id in WIDGET_INSTANCE_MAP :
169
169
del WIDGET_INSTANCE_MAP [id ]
170
170
171
- ctx .on_invalidate (on_close )
171
+ # This could be running in a shiny.reactive.ExtendedTask, in which case,
172
+ # the context is a DenialContext. As a result, on_invalidate() will throw
173
+ # (since reading/invalidating reactive sources isn't allowed in this context).
174
+ # For now, we just don't clean up the widget in this case.
175
+ # TODO: this line can likely be removed once we start closing iff we're in a
176
+ # output context (see TODO comment above)
177
+ if "DenialContext" != ctx .__class__ .__name__ :
178
+ ctx .on_invalidate (on_close )
172
179
173
180
# Keep track of what session this widget belongs to (so we can close it when the
174
181
# session ends)
@@ -208,6 +215,7 @@ def on_close():
208
215
# Reactivity
209
216
# --------------------------------------
210
217
218
+
211
219
def reactive_read (widget : Widget , names : Union [str , Sequence [str ]]) -> Any :
212
220
"""
213
221
Reactively read a widget trait
@@ -273,6 +281,7 @@ def _():
273
281
274
282
return w
275
283
284
+
276
285
# Previous versions of ipywidgets (< 8.0.5) had
277
286
# `Widget.comm = Instance('ipykernel.comm.Comm')`
278
287
# which meant we'd get a runtime error when setting `Widget.comm = ShinyComm()`.
@@ -300,6 +309,7 @@ def is_traitlet_instance(x: object) -> "TypeGuard[Instance[Any]]":
300
309
return False
301
310
return isinstance (x , Instance )
302
311
312
+
303
313
# It doesn't, at the moment, seem feasible to establish a comm with statically rendered widgets,
304
314
# and partially for this reason, it may not be sensible to provide an input-like API for them.
305
315
0 commit comments