summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/attributes.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2006-06-16 19:21:57 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2006-06-16 19:21:57 +0000
commit26e348634444bf4142b42ad484d89161634c344d (patch)
tree64b00a5b891b2c5adc6dbe8bc7aa4c1705d46205 /lib/sqlalchemy/attributes.py
parentbcc4f63a0790cd95a32dd334230656867e9a6b9e (diff)
downloadsqlalchemy-26e348634444bf4142b42ad484d89161634c344d.tar.gz
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
Diffstat (limited to 'lib/sqlalchemy/attributes.py')
-rw-r--r--lib/sqlalchemy/attributes.py38
1 files changed, 28 insertions, 10 deletions
diff --git a/lib/sqlalchemy/attributes.py b/lib/sqlalchemy/attributes.py
index 60cbecec1..b7ad5249b 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]