Hi,
maybe you could do this by a decorator on the setattr method. It should
look more or less
like your implementation, but in my eyes it's a cleaner and can be reused.
Further, I would use a stack for each attribute, so that you can restore
all previous values.
bg,
Johannes
On 03/06/2013 05:07 PM, Ben Sizer wrote:
I am trying to make an object that can track when its attributes have been
assigned new values, and which can rollback to previous values where necessary.
I have the following code which I believe works, but would like to know if
there are simpler ways to achieve this goal, or if there are any bugs I haven't
seen yet.
class ChangeTrackingObject(object):
def __init__(self):
self.clean()
def clean(self):
"""Mark all attributes as unmodified."""
object.__setattr__(self, '_dirty_attributes', dict())
def dirty_vals(self):
"""Returns all dirty values."""
return dict( [ (k,v) for k,v in self.__dict__.iteritems() if k in
self._dirty_attributes] )
def get_changes_and_clean(self):
"""Helper that collects all the changes and returns them, cleaning the dirty flags at
the same time."""
changes = self.dirty_vals()
self.clean()
return changes
def rollback(self):
"""Reset attributes to their previous values."""
for k,v in self._dirty_attributes.iteritems():
object.__setattr__(self, k, v)
self.clean()
def __setattr__(self, key, value):
# If the first modification to this attribute, store the old value
if key not in self._dirty_attributes:
if key in self.__dict__:
self._dirty_attributes[key] = object.__getattribute__(self,
key)
else:
self._dirty_attributes[key] = None
# Set the new value
object.__setattr__(self, key, value)
I am aware that adding a new attribute and then calling rollback() leaves the
new attribute in place with a None value - maybe I can use a special DeleteMe
marker object in the _dirty_attributes dict along with a loop that calls
delattr on any attribute that has that value after a rollback.
I also believe that this won't catch modification to existing attributes as
opposed to assignments: eg. if one of the attributes is a list and I append to
it, this system won't notice. Is that something I can rectify easily?
Any other comments or suggestions?
Thanks,
--
http://mail.python.org/mailman/listinfo/python-list