def watchObject(self, object, identifier, callback):
"""Watch the given object.
Whenever I think the object might have changed, I'll send an
ObjectLink of it to the callback.
The identifier argument is used to generate identifiers for
objects which are members of this one.
"""
if type(object) is not types.InstanceType:
raise TypeError, "Sorry, can only place a watch on Instances."
# uninstallers = []
dct = {}
reflect.addMethodNamesToDict(object.__class__, dct, '')
for k in object.__dict__.keys():
dct[k] = 1
members = dct.keys()
clazzNS = {}
clazz = new.classobj('Watching%s%X' %
(object.__class__.__name__, id(object)),
(_MonkeysSetattrMixin, object.__class__,),
clazzNS)
clazzNS['_watchEmitChanged'] = new.instancemethod(
lambda slf, i=identifier, b=self, cb=callback:
cb(b.browseObject(slf, i)),
None, clazz)
# orig_class = object.__class__
object.__class__ = clazz
for name in members:
m = getattr(object, name)
# Only hook bound methods.
if ((type(m) is types.MethodType)
and (m.im_self is not None)):
# What's the use of putting watch monkeys on methods
# in addition to __setattr__? Well, um, uh, if the
# methods modify their attributes (i.e. add a key to
# a dictionary) instead of [re]setting them, then
# we wouldn't know about it unless we did this.
# (Is that convincing?)
monkey = _WatchMonkey(object)
monkey.install(name)
# uninstallers.append(monkey.uninstall)
# XXX: This probably prevents these objects from ever having a
# zero refcount. Leak, Leak!
## self.watchUninstallers[object] = uninstallers
评论列表
文章目录