##// END OF EJS Templates
Merge pull request #11876 from daharn/autoreload-fix-using-gc.get_referrers()...
Matthias Bussonnier -
r25187:cd54f155 merge
parent child Browse files
Show More
@@ -115,7 +115,7 b' import sys'
115 115 import traceback
116 116 import types
117 117 import weakref
118 import inspect
118 import gc
119 119 from importlib import import_module
120 120 from importlib.util import source_from_cache
121 121 from imp import reload
@@ -268,56 +268,16 b' def update_function(old, new):'
268 268 pass
269 269
270 270
271 def update_instances(old, new, objects=None, visited={}):
272 """Iterate through objects recursively, searching for instances of old and
273 replace their __class__ reference with new. If no objects are given, start
274 with the current ipython workspace.
275 """
276 if objects is None:
277 # make sure visited is cleaned when not called recursively
278 visited = {}
279 # find ipython workspace stack frame
280 frame = next(frame_nfo.frame for frame_nfo in inspect.stack()
281 if 'trigger' in frame_nfo.function)
282 # build generator for non-private variable values from workspace
283 shell = frame.f_locals['self'].shell
284 user_ns = shell.user_ns
285 user_ns_hidden = shell.user_ns_hidden
286 nonmatching = object()
287 objects = ( value for key, value in user_ns.items()
288 if not key.startswith('_')
289 and (value is not user_ns_hidden.get(key, nonmatching))
290 and not inspect.ismodule(value))
271 def update_instances(old, new):
272 """Use garbage collector to find all instances that refer to the old
273 class definition and update their __class__ to point to the new class
274 definition"""
291 275
292 # use dict values if objects is a dict but don't touch private variables
293 if hasattr(objects, 'items'):
294 objects = (value for key, value in objects.items()
295 if not str(key).startswith('_')
296 and not inspect.ismodule(value) )
276 refs = gc.get_referrers(old)
297 277
298 # try if objects is iterable
299 try:
300 for obj in (obj for obj in objects if id(obj) not in visited):
301 # add current object to visited to avoid revisiting
302 visited.update({id(obj):obj})
303
304 # update, if object is instance of old_class (but no subclasses)
305 if type(obj) is old:
306 obj.__class__ = new
307
308
309 # if object is instance of other class, look for nested instances
310 if hasattr(obj, '__dict__') and not (inspect.isfunction(obj)
311 or inspect.ismethod(obj)):
312 update_instances(old, new, obj.__dict__, visited)
313
314 # if object is a container, search it
315 if hasattr(obj, 'items') or (hasattr(obj, '__contains__')
316 and not isinstance(obj, str)):
317 update_instances(old, new, obj, visited)
318
319 except TypeError:
320 pass
278 for ref in refs:
279 if type(ref) is old:
280 ref.__class__ = new
321 281
322 282
323 283 def update_class(old, new):
General Comments 0
You need to be logged in to leave comments. Login now