Creating an object that can track when its attributes are modified

Schneider js at globe.de
Thu Mar 7 07:21:00 EST 2013


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,




More information about the Python-list mailing list