From 26e348634444bf4142b42ad484d89161634c344d Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 16 Jun 2006 19:21:57 +0000 Subject: [PATCH] more intelligent "removal" of list items when a list attribute is replaced, doesnt actually "remove" the items from teh replaced list just marks them as "removed" from the parent object for history purposes --- lib/sqlalchemy/attributes.py | 38 ++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/sqlalchemy/attributes.py b/lib/sqlalchemy/attributes.py index 60cbecec14..b7ad5249b0 100644 --- a/lib/sqlalchemy/attributes.py +++ b/lib/sqlalchemy/attributes.py @@ -179,9 +179,9 @@ class InstrumentedAttribute(object): for ext in self.extensions: ext.set(event or self, obj, value, old) else: - # set the deleted event for the old item - old[:] = [] - + # mark all the old elements as detached from the parent + old.list_replaced() + def delete(self, event, obj): """deletes a value from the given object. 'event' is the InstrumentedAttribute that initiated the delete() operation and is used to control the depth of a circular delete @@ -256,16 +256,39 @@ class InstrumentedList(object): self.key = attr.key self.data = data or attr._blank_list() - # adapt to lists or sets automatically + # adapt to lists or sets + # TODO: make three subclasses of InstrumentedList that come off from a + # metaclass, based on the type of data sent in if hasattr(self.data, 'append'): self._data_appender = self.data.append + self._clear_data = self._clear_list elif hasattr(self.data, 'add'): self._data_appender = self.data.add + self._clear_data = self._clear_set + if isinstance(self.data, dict): + self._clear_data = self._clear_dict if init: for x in self.data: self.__setrecord(x) - + + def list_replaced(self): + """fires off delete event handlers for each item in the list but + doesnt affect the original data list""" + [self.__delrecord(x) for x in self.data] + + def clear(self): + """clears all items in this InstrumentedList and fires off delete event handlers for each item""" + self._clear_data() + def _clear_dict(self): + [self.__delrecord(x) for x in self.data.values()] + self.data.clear() + def _clear_set(self): + [self.__delrecord(x) for x in self.data] + self.data.clear() + def _clear_list(self): + self[:] = [] + def __getstate__(self): """implemented to allow pickling, since __obj is a weakref.""" return {'key':self.key, 'obj':self.obj, 'data':self.data, 'attr':self.attr} @@ -326,11 +349,6 @@ class InstrumentedList(object): self.__setrecord(item) self._data_appender(item) - def clear(self): - if isinstance(self.data, dict): - self.data.clear() - else: - self.data[:] = self.attr._blank_list() def __getitem__(self, i): return self.data[i] -- 2.47.2