Show More
@@ -115,7 +115,7 b' import sys' | |||||
115 | import traceback |
|
115 | import traceback | |
116 | import types |
|
116 | import types | |
117 | import weakref |
|
117 | import weakref | |
118 |
import |
|
118 | import gc | |
119 | from importlib import import_module |
|
119 | from importlib import import_module | |
120 | from importlib.util import source_from_cache |
|
120 | from importlib.util import source_from_cache | |
121 | from imp import reload |
|
121 | from imp import reload | |
@@ -268,56 +268,16 b' def update_function(old, new):' | |||||
268 | pass |
|
268 | pass | |
269 |
|
269 | |||
270 |
|
270 | |||
271 |
def update_instances(old, new |
|
271 | def update_instances(old, new): | |
272 | """Iterate through objects recursively, searching for instances of old and |
|
272 | """Use garbage collector to find all instances that refer to the old | |
273 | replace their __class__ reference with new. If no objects are given, start |
|
273 | class definition and update their __class__ to point to the new class | |
274 | with the current ipython workspace. |
|
274 | definition""" | |
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)) |
|
|||
291 |
|
||||
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) ) |
|
|||
297 |
|
||||
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 |
|
275 | |||
309 | # if object is instance of other class, look for nested instances |
|
276 | refs = gc.get_referrers(old) | |
310 | if hasattr(obj, '__dict__') and not (inspect.isfunction(obj) |
|
|||
311 | or inspect.ismethod(obj)): |
|
|||
312 | update_instances(old, new, obj.__dict__, visited) |
|
|||
313 |
|
277 | |||
314 | # if object is a container, search it |
|
278 | for ref in refs: | |
315 | if hasattr(obj, 'items') or (hasattr(obj, '__contains__') |
|
279 | if type(ref) is old: | |
316 | and not isinstance(obj, str)): |
|
280 | ref.__class__ = new | |
317 | update_instances(old, new, obj, visited) |
|
|||
318 |
|
||||
319 | except TypeError: |
|
|||
320 | pass |
|
|||
321 |
|
281 | |||
322 |
|
282 | |||
323 | def update_class(old, new): |
|
283 | def update_class(old, new): |
General Comments 0
You need to be logged in to leave comments.
Login now