summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJason Kirtland <jek@discorporate.us>2008-01-04 20:17:42 +0000
committerJason Kirtland <jek@discorporate.us>2008-01-04 20:17:42 +0000
commita230391a37e1f6b7aaef6adef4a57da24588432b (patch)
tree4ecf454dd4ad8e6987e7a777c76ca3a4d39ead85 /lib
parent0c515c51170bb19260e42da0d34a8db80021381e (diff)
downloadsqlalchemy-a230391a37e1f6b7aaef6adef4a57da24588432b.tar.gz
Fixed in-place set mutation operator support [ticket:920]
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/ext/associationproxy.py45
-rw-r--r--lib/sqlalchemy/orm/collections.py55
2 files changed, 90 insertions, 10 deletions
diff --git a/lib/sqlalchemy/ext/associationproxy.py b/lib/sqlalchemy/ext/associationproxy.py
index 472bd1b2c..c5a2b4d07 100644
--- a/lib/sqlalchemy/ext/associationproxy.py
+++ b/lib/sqlalchemy/ext/associationproxy.py
@@ -176,8 +176,9 @@ class AssociationProxy(object):
self._scalar_set(target, values)
else:
proxy = self.__get__(obj, None)
- proxy.clear()
- self._set(proxy, values)
+ if proxy is not values:
+ proxy.clear()
+ self._set(proxy, values)
def __delete__(self, obj):
delattr(obj, self.key)
@@ -653,7 +654,12 @@ class _AssociationSet(object):
for value in other:
self.add(value)
- __ior__ = update
+ def __ior__(self, other):
+ if util.duck_type_collection(other) is not set:
+ return NotImplemented
+ for value in other:
+ self.add(value)
+ return self
def _set(self):
return util.Set(iter(self))
@@ -672,7 +678,12 @@ class _AssociationSet(object):
for value in other:
self.discard(value)
- __isub__ = difference_update
+ def __isub__(self, other):
+ if util.duck_type_collection(other) is not set:
+ return NotImplemented
+ for value in other:
+ self.discard(value)
+ return self
def intersection(self, other):
return util.Set(self).intersection(other)
@@ -689,7 +700,18 @@ class _AssociationSet(object):
for value in add:
self.add(value)
- __iand__ = intersection_update
+ def __iand__(self, other):
+ if util.duck_type_collection(other) is not set:
+ return NotImplemented
+ want, have = self.intersection(other), util.Set(self)
+
+ remove, add = have - want, want - have
+
+ for value in remove:
+ self.remove(value)
+ for value in add:
+ self.add(value)
+ return self
def symmetric_difference(self, other):
return util.Set(self).symmetric_difference(other)
@@ -706,7 +728,18 @@ class _AssociationSet(object):
for value in add:
self.add(value)
- __ixor__ = symmetric_difference_update
+ def __ixor__(self, other):
+ if util.duck_type_collection(other) is not set:
+ return NotImplemented
+ want, have = self.symmetric_difference(other), util.Set(self)
+
+ remove, add = have - want, want - have
+
+ for value in remove:
+ self.remove(value)
+ for value in add:
+ self.add(value)
+ return self
def issubset(self, other):
return util.Set(self).issubset(other)
diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py
index ddbf6f005..106601640 100644
--- a/lib/sqlalchemy/orm/collections.py
+++ b/lib/sqlalchemy/orm/collections.py
@@ -1138,7 +1138,17 @@ def _set_decorators():
self.add(item)
_tidy(update)
return update
- __ior__ = update
+
+ def __ior__(fn):
+ def __ior__(self, value):
+ if sautil.duck_type_collection(value) is not set:
+ return NotImplemented
+ for item in value:
+ if item not in self:
+ self.add(item)
+ return self
+ _tidy(__ior__)
+ return __ior__
def difference_update(fn):
def difference_update(self, value):
@@ -1146,7 +1156,16 @@ def _set_decorators():
self.discard(item)
_tidy(difference_update)
return difference_update
- __isub__ = difference_update
+
+ def __isub__(fn):
+ def __isub__(self, value):
+ if sautil.duck_type_collection(value) is not set:
+ return NotImplemented
+ for item in value:
+ self.discard(item)
+ return self
+ _tidy(__isub__)
+ return __isub__
def intersection_update(fn):
def intersection_update(self, other):
@@ -1159,7 +1178,21 @@ def _set_decorators():
self.add(item)
_tidy(intersection_update)
return intersection_update
- __iand__ = intersection_update
+
+ def __iand__(fn):
+ def __iand__(self, other):
+ if sautil.duck_type_collection(other) is not set:
+ return NotImplemented
+ want, have = self.intersection(other), sautil.Set(self)
+ remove, add = have - want, want - have
+
+ for item in remove:
+ self.remove(item)
+ for item in add:
+ self.add(item)
+ return self
+ _tidy(__iand__)
+ return __iand__
def symmetric_difference_update(fn):
def symmetric_difference_update(self, other):
@@ -1172,7 +1205,21 @@ def _set_decorators():
self.add(item)
_tidy(symmetric_difference_update)
return symmetric_difference_update
- __ixor__ = symmetric_difference_update
+
+ def __ixor__(fn):
+ def __ixor__(self, other):
+ if sautil.duck_type_collection(other) is not set:
+ return NotImplemented
+ want, have = self.symmetric_difference(other), sautil.Set(self)
+ remove, add = have - want, want - have
+
+ for item in remove:
+ self.remove(item)
+ for item in add:
+ self.add(item)
+ return self
+ _tidy(__ixor__)
+ return __ixor__
l = locals().copy()
l.pop('_tidy')