P
Paul Johnston
Hi,
I would like to be able to install a code hook to detect updates on
arbitrary objects. To give some background, I'm writing a web widget
library, that uses request-local storage. If there's a mutable object
on a widget (a dict is common), I'd like any attempts to update the
dict to cause the dict to be cloned into request-local storage and the
update applied.
Now, I did have this working quite nicely for dict and list instances,
by subclassing dict and list, and overriding the write methods (or
most of them - __setitem__, __delitem__, append, etc.) When the dict/
list is added to the widget, it's replaced with a clone, using the
DictProxy/ListProxy subclass. (I realise Proxy may have been slightly
inaccurate as a name) However, sometimes a user needs to use a list-
like object that isn't a list, and this approach breaks down.
So, I think I need to do a real object proxy - a class that defers
almost all attributes to an inner instance that it stores, but
overrides a few. The following is my initial attempt, which almost
works, but I think there must be a better way. In particular, needing
to explicitly override __iter__ and __eq__ spells trouble - what about
__ne__, __gt__, etc. Also, is there a way to catch just any change,
rather than trying to know all the change methods. A way to do this
for arbitrary objects (not just dicts and lists) would be good too.
Any hints, tips, or pointers to docs online?
Thanks,
Paul
class GenericProxy(object):
def __init__(self, obj):
self._obj = obj
def __getattr__(self, a):
return getattr(self._obj, a)
def __iter__(self):
return self._obj.__iter__()
def __eq__(self, x):
return self._obj.__eq__(x)
__setitem__ = _catch_modify('__setitem__')
__delitem__ = _catch_modify('__delitem__')
append = _catch_modify('append')
insert = _catch_modify('insert')
I would like to be able to install a code hook to detect updates on
arbitrary objects. To give some background, I'm writing a web widget
library, that uses request-local storage. If there's a mutable object
on a widget (a dict is common), I'd like any attempts to update the
dict to cause the dict to be cloned into request-local storage and the
update applied.
Now, I did have this working quite nicely for dict and list instances,
by subclassing dict and list, and overriding the write methods (or
most of them - __setitem__, __delitem__, append, etc.) When the dict/
list is added to the widget, it's replaced with a clone, using the
DictProxy/ListProxy subclass. (I realise Proxy may have been slightly
inaccurate as a name) However, sometimes a user needs to use a list-
like object that isn't a list, and this approach breaks down.
So, I think I need to do a real object proxy - a class that defers
almost all attributes to an inner instance that it stores, but
overrides a few. The following is my initial attempt, which almost
works, but I think there must be a better way. In particular, needing
to explicitly override __iter__ and __eq__ spells trouble - what about
__ne__, __gt__, etc. Also, is there a way to catch just any change,
rather than trying to know all the change methods. A way to do this
for arbitrary objects (not just dicts and lists) would be good too.
Any hints, tips, or pointers to docs online?
Thanks,
Paul
class GenericProxy(object):
def __init__(self, obj):
self._obj = obj
def __getattr__(self, a):
return getattr(self._obj, a)
def __iter__(self):
return self._obj.__iter__()
def __eq__(self, x):
return self._obj.__eq__(x)
__setitem__ = _catch_modify('__setitem__')
__delitem__ = _catch_modify('__delitem__')
append = _catch_modify('append')
insert = _catch_modify('insert')