@@ -162,39 +162,41 @@ def filename_and_mtime(
162
162
163
163
return py_filename , pymtime
164
164
165
- def check (self , do_reload : bool = True ) -> None :
166
- """Check whether some modules need to be reloaded."""
167
- self .reloaded_modules .clear ()
168
- self .failed_modules .clear ()
169
-
170
- # TODO: we should try to reload the modules in topological order
165
+ def _get_modules_needing_reload (self ) -> Dict [str , Tuple [ModuleType , str , float ]]:
166
+ modules_needing_reload = {}
171
167
for modname , m in list (sys .modules .items ()):
172
168
package_components = modname .split ("." )
173
169
if any (
174
170
"." .join (package_components [:idx ]) in self .skip_modules
175
171
for idx in range (1 , len (package_components ))
176
172
):
177
173
continue
178
-
179
174
py_filename , pymtime = self .filename_and_mtime (m )
180
175
if py_filename is None :
181
176
continue
182
-
183
- try :
184
- if pymtime <= self .modules_mtimes [modname ]:
185
- continue
186
- except KeyError :
187
- self .modules_mtimes [modname ] = pymtime
177
+ if pymtime <= self .modules_mtimes .setdefault (modname , pymtime ):
178
+ continue
179
+ if self .failed .get (py_filename ) == pymtime :
188
180
continue
189
- else :
190
- if self .failed .get (py_filename , None ) == pymtime :
191
- continue
192
-
193
181
self .modules_mtimes [modname ] = pymtime
182
+ modules_needing_reload [modname ] = (m , py_filename , pymtime )
183
+ return modules_needing_reload
194
184
195
- if not do_reload :
196
- continue
185
+ def check (self , do_reload : bool = True ) -> None :
186
+ """Check whether some modules need to be reloaded."""
187
+ self .reloaded_modules .clear ()
188
+ self .failed_modules .clear ()
197
189
190
+ modules_needing_reload = self ._get_modules_needing_reload ()
191
+ if not do_reload :
192
+ return
193
+
194
+ # TODO: we should try to reload the modules in topological order
195
+ for modname , (
196
+ m ,
197
+ py_filename ,
198
+ pymtime ,
199
+ ) in modules_needing_reload .items ():
198
200
# If we've reached this point, we should try to reload the module
199
201
self ._report (f"Reloading '{ modname } '." )
200
202
try :
@@ -220,6 +222,18 @@ def maybe_track_obj(self, module: ModuleType, name: str, obj: object) -> None:
220
222
except TypeError :
221
223
pass
222
224
225
+ def _patch_ipyflow_symbols (self , old , new , flow_ ):
226
+ if flow_ is None :
227
+ return
228
+ if isinstance (old , IMMUTABLE_PRIMITIVE_TYPES ):
229
+ return
230
+ old_id = id (old )
231
+ if old_id not in flow_ .aliases :
232
+ return
233
+ for sym in list (flow_ .aliases [old_id ]):
234
+ sym ._override_ready_liveness_cell_num = flow_ .cell_counter ()
235
+ sym .update_obj_ref (new )
236
+
223
237
def superduperreload (self , module : ModuleType ) -> ModuleType :
224
238
"""Enhanced version of the superreload function from IPython's autoreload extension.
225
239
@@ -229,6 +243,13 @@ def superduperreload(self, module: ModuleType) -> ModuleType:
229
243
- upgrades the code object of every old function and method
230
244
- clears the module's namespace before reloading
231
245
"""
246
+ try :
247
+ from ipyflow import flow
248
+
249
+ flow_ = flow ()
250
+ except :
251
+ flow_ = None
252
+
232
253
self ._patched_obj_ids .clear ()
233
254
234
255
# collect old objects in the module
@@ -254,6 +275,7 @@ def superduperreload(self, module: ModuleType) -> ModuleType:
254
275
continue
255
276
self ._patch_generic (old_obj , new_obj )
256
277
self ._patch_referrers_generic (old_obj , new_obj )
278
+ self ._patch_ipyflow_symbols (old_obj , new_obj , flow_ )
257
279
258
280
if new_refs :
259
281
self .old_objects [key ] = new_refs
0 commit comments