Chris Spencer wrote: > Alex Martelli wrote: >> If you're in no hurry, you COULD loop over all of gc.get_objects(), >> identify all those which are instances of old_class and "somehow" change >> their classes to new_class -- of course, x.__class__ = new_class may >> well not be sufficient, in which case you'll have to pass to update a >> callable to do the instance-per-instance job. > > > Couldn't I just loop over gc.get_referrers(cls), checking for instances > of the class object? Since class instances refer to their class, the gc > seems to be doing the exact same thing as Hudson's fancy metaclass. Or > am I missing something? > > Chris
In fact, the following code seems to work, and doesn't require any modification to new-style class based code: import os import time import threading import inspect import gc import copy class ModuleUpdater(object): ''' This will constantly check a module's source file for updates, reload if any are detected, and update all class instances. Only works for new-style classes. Use like: checker = ModuleUpdater(module=mymod) checker.start() ''' def __init__(self, module): self.module = module self.lastloaded = time.time() self.running = 0 self.t = None def __call__(self): self.running = 1 while self.running: self.check() time.sleep(1) def check(self): lastmodified = os.stat(inspect.getsourcefile(self.module))[8] if lastmodified > self.lastloaded: print 'update detected for',self.module.__name__ oldmod = copy.copy(self.module.__dict__) newmod = reload(self.module) try: for name,obj in oldmod.items(): if isinstance(obj,type) and name in newmod.__dict__: newobj = newmod.__dict__[name] referrers = gc.get_referrers(obj) for referrer in referrers: if isinstance(referrer,obj): # update old class instances to use new class referrer.__class__ = newobj print 'update loaded for',self.module.__name__ except Exception, e: print 'unable to load update for %s: %s' % (self.module.__name__, str(e)) self.lastloaded = lastmodified return 1 return 0 def start(self): t = threading.Thread(target=self) t.setDaemon(1) t.start() self.t = t return t def stop(self, blocking=0): self.running = 0 if blocking: self.t.join() if __name__ == '__main__': import testmod # any module containing class Bar with method meth uc = ModuleUpdater(testmod) uc.start() b=testmod.Bar(1) while 1: # meanwhile, modify the source to testmod.py time.sleep(1) print b.meth() -- http://mail.python.org/mailman/listinfo/python-list