Dynamically Update Class Definitions?

C

chrisspen

Is there a way to loop through all instantiated objects and update
their classes when a source file changes? I know about Michael Hudson's
method
(http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/160164), but
you have to modify all your classes to subclass AutoReloader. Is there
something less intrusive (visitor pattern?) that you can use like
update(old_class, new_class) to automagically do the work?

Chris
 
A

Alex Martelli

Is there a way to loop through all instantiated objects and update
their classes when a source file changes? I know about Michael Hudson's
method
(http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/160164), but
you have to modify all your classes to subclass AutoReloader. Is there
something less intrusive (visitor pattern?) that you can use like
update(old_class, new_class) to automagically do the work?

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.


Alex
 
C

Chris Spencer

Alex said:
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
 
C

Chris Spencer

Chris said:
Alex Martelli wrote:


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()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top