@@ -96,9 +96,6 @@ def _cleanup_session_state():
96
96
97
97
session .on_ended (_cleanup_session_state )
98
98
99
- # Get the initial state of the widget
100
- state , buffer_paths , buffers = _remove_buffers (w .get_state ())
101
-
102
99
# Make sure window.require() calls made by 3rd party widgets
103
100
# (via handle_comm_open() -> new_model() -> loadClass() -> requireLoader())
104
101
# actually point to directories served locally by shiny
@@ -114,18 +111,39 @@ def _cleanup_session_state():
114
111
115
112
id = cast (str , w ._model_id )
116
113
117
- # Initialize the comm...this will also send the initial state of the widget
118
- with widget_comm_patch ():
119
- w .comm = ShinyComm (
120
- comm_id = id ,
121
- comm_manager = COMM_MANAGER ,
122
- target_name = "jupyter.widgets" ,
123
- data = {"state" : state , "buffer_paths" : buffer_paths },
124
- buffers = cast (BufferType , buffers ),
125
- # TODO: should this be hard-coded?
126
- metadata = {"version" : __protocol_version__ },
127
- html_deps = session ._process_ui (TagList (widget_dep ))["deps" ],
128
- )
114
+ # Since the actual ShinyComm() is initialized _after_ the Widget is initialized,
115
+ # and Widget.__init__() includes a call to Widget.open() which opens an unnecessary
116
+ # comm, we just set the comm to a dummy comm for now (to avoid unnecessary work)
117
+ w .comm = OrphanedShinyComm (id )
118
+
119
+ # Schedule the opening of the comm to happen sometime after this init function.
120
+ # This is important for widgets like plotly that do additional initialization that
121
+ # is required to get a valid widget state.
122
+ @reactive .effect (priority = 99999 )
123
+ def _open_shiny_comm ():
124
+
125
+ # Call _repr_mimebundle_() before get_state() since it may modify the widget
126
+ # in an important way (unfortunately, it does for plotly)
127
+ # # https://github.com/plotly/plotly.py/blob/0089f32/packages/python/plotly/plotly/basewidget.py#L734-L738
128
+ w ._repr_mimebundle_ ()
129
+
130
+ # Now, get the state
131
+ state , buffer_paths , buffers = _remove_buffers (w .get_state ())
132
+
133
+ # Initialize the comm -- this sends widget state to the frontend
134
+ with widget_comm_patch ():
135
+ w .comm = ShinyComm (
136
+ comm_id = id ,
137
+ comm_manager = COMM_MANAGER ,
138
+ target_name = "jupyter.widgets" ,
139
+ data = {"state" : state , "buffer_paths" : buffer_paths },
140
+ buffers = cast (BufferType , buffers ),
141
+ # TODO: should this be hard-coded?
142
+ metadata = {"version" : __protocol_version__ },
143
+ html_deps = session ._process_ui (TagList (widget_dep ))["deps" ],
144
+ )
145
+
146
+ _open_shiny_comm .destroy ()
129
147
130
148
# If we're in a reactive context, close this widget when the context is invalidated
131
149
# TODO: this should probably only be done in an output context, but I'm pretty sure
0 commit comments