summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorJason Kirtland <jek@discorporate.us>2008-01-21 23:19:39 +0000
committerJason Kirtland <jek@discorporate.us>2008-01-21 23:19:39 +0000
commit412c80dd6c5d6b940e86e7e142aa1fdd6ee4466d (patch)
tree2a5bfa8185dd888d52b31bfb26ada56c7db89139 /lib/sqlalchemy
parent08bbc3dfd84234c3cd691e43ff17ed36e2396d76 (diff)
downloadsqlalchemy-412c80dd6c5d6b940e86e7e142aa1fdd6ee4466d.tar.gz
- 2.3 fixup, part two: 100% passing for sqlite
- added 2.4-style binops to util.Set on 2.3 - OrderedSets pickle on 2.3 - more lib/sqlalchemy set vs Set corrections - fixed InstrumentedSet.discard for 2.3 - set, sorted compatibility for test suite - added testing.fails_if decorator
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/ext/associationproxy.py8
-rw-r--r--lib/sqlalchemy/orm/collections.py58
-rw-r--r--lib/sqlalchemy/util.py63
3 files changed, 96 insertions, 33 deletions
diff --git a/lib/sqlalchemy/ext/associationproxy.py b/lib/sqlalchemy/ext/associationproxy.py
index fefc289f8..e9f604005 100644
--- a/lib/sqlalchemy/ext/associationproxy.py
+++ b/lib/sqlalchemy/ext/associationproxy.py
@@ -686,7 +686,7 @@ class _AssociationSet(object):
self.add(value)
def __ior__(self, other):
- if util.duck_type_collection(other) is not set:
+ if util.duck_type_collection(other) is not util.Set:
return NotImplemented
for value in other:
self.add(value)
@@ -710,7 +710,7 @@ class _AssociationSet(object):
self.discard(value)
def __isub__(self, other):
- if util.duck_type_collection(other) is not set:
+ if util.duck_type_collection(other) is not util.Set:
return NotImplemented
for value in other:
self.discard(value)
@@ -732,7 +732,7 @@ class _AssociationSet(object):
self.add(value)
def __iand__(self, other):
- if util.duck_type_collection(other) is not set:
+ if util.duck_type_collection(other) is not util.Set:
return NotImplemented
want, have = self.intersection(other), util.Set(self)
@@ -760,7 +760,7 @@ class _AssociationSet(object):
self.add(value)
def __ixor__(self, other):
- if util.duck_type_collection(other) is not set:
+ if util.duck_type_collection(other) is not util.Set:
return NotImplemented
want, have = self.symmetric_difference(other), util.Set(self)
diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py
index c63c4dc8c..daf9dfb45 100644
--- a/lib/sqlalchemy/orm/collections.py
+++ b/lib/sqlalchemy/orm/collections.py
@@ -98,7 +98,7 @@ through the adapter, allowing for some very sophisticated behavior.
import copy, inspect, sys, weakref
from sqlalchemy import exceptions, schema, util as sautil
-from sqlalchemy.util import attrgetter
+from sqlalchemy.util import attrgetter, Set
__all__ = ['collection', 'collection_adapter',
@@ -1098,7 +1098,7 @@ def _set_decorators():
def _tidy(fn):
setattr(fn, '_sa_instrumented', True)
- fn.__doc__ = getattr(getattr(set, fn.__name__), '__doc__')
+ fn.__doc__ = getattr(getattr(Set, fn.__name__), '__doc__')
Unspecified=object()
@@ -1110,15 +1110,23 @@ def _set_decorators():
_tidy(add)
return add
- def discard(fn):
- def discard(self, value, _sa_initiator=None):
- # testlib.pragma exempt:__hash__
- if value in self:
- __del(self, value, _sa_initiator)
- # testlib.pragma exempt:__hash__
- fn(self, value)
- _tidy(discard)
- return discard
+ if sys.version_info < (2, 4):
+ def discard(fn):
+ def discard(self, value, _sa_initiator=None):
+ if value in self:
+ self.remove(value, _sa_initiator)
+ _tidy(discard)
+ return discard
+ else:
+ def discard(fn):
+ def discard(self, value, _sa_initiator=None):
+ # testlib.pragma exempt:__hash__
+ if value in self:
+ __del(self, value, _sa_initiator)
+ # testlib.pragma exempt:__hash__
+ fn(self, value)
+ _tidy(discard)
+ return discard
def remove(fn):
def remove(self, value, _sa_initiator=None):
@@ -1156,7 +1164,7 @@ def _set_decorators():
def __ior__(fn):
def __ior__(self, value):
- if sautil.duck_type_collection(value) is not set:
+ if sautil.duck_type_collection(value) is not Set:
return NotImplemented
for item in value:
if item not in self:
@@ -1174,7 +1182,7 @@ def _set_decorators():
def __isub__(fn):
def __isub__(self, value):
- if sautil.duck_type_collection(value) is not set:
+ if sautil.duck_type_collection(value) is not Set:
return NotImplemented
for item in value:
self.discard(item)
@@ -1184,7 +1192,7 @@ def _set_decorators():
def intersection_update(fn):
def intersection_update(self, other):
- want, have = self.intersection(other), sautil.Set(self)
+ want, have = self.intersection(other), Set(self)
remove, add = have - want, want - have
for item in remove:
@@ -1196,9 +1204,9 @@ def _set_decorators():
def __iand__(fn):
def __iand__(self, other):
- if sautil.duck_type_collection(other) is not set:
+ if sautil.duck_type_collection(other) is not Set:
return NotImplemented
- want, have = self.intersection(other), sautil.Set(self)
+ want, have = self.intersection(other), Set(self)
remove, add = have - want, want - have
for item in remove:
@@ -1211,7 +1219,7 @@ def _set_decorators():
def symmetric_difference_update(fn):
def symmetric_difference_update(self, other):
- want, have = self.symmetric_difference(other), sautil.Set(self)
+ want, have = self.symmetric_difference(other), Set(self)
remove, add = have - want, want - have
for item in remove:
@@ -1223,9 +1231,9 @@ def _set_decorators():
def __ixor__(fn):
def __ixor__(self, other):
- if sautil.duck_type_collection(other) is not set:
+ if sautil.duck_type_collection(other) is not Set:
return NotImplemented
- want, have = self.symmetric_difference(other), sautil.Set(self)
+ want, have = self.symmetric_difference(other), Set(self)
remove, add = have - want, want - have
for item in remove:
@@ -1250,7 +1258,7 @@ class InstrumentedList(list):
'remover': 'remove',
'iterator': '__iter__', }
-class InstrumentedSet(sautil.Set):
+class InstrumentedSet(Set):
"""An instrumented version of the built-in set (or Set)."""
__instrumentation__ = {
@@ -1266,7 +1274,7 @@ class InstrumentedDict(dict):
__canned_instrumentation = {
list: InstrumentedList,
- sautil.Set: InstrumentedSet,
+ Set: InstrumentedSet,
dict: InstrumentedDict,
}
@@ -1275,10 +1283,10 @@ __interfaces = {
'remover': 'remove',
'iterator': '__iter__',
'_decorators': _list_decorators(), },
- sautil.Set: { 'appender': 'add',
- 'remover': 'remove',
- 'iterator': '__iter__',
- '_decorators': _set_decorators(), },
+ Set: { 'appender': 'add',
+ 'remover': 'remove',
+ 'iterator': '__iter__',
+ '_decorators': _set_decorators(), },
# decorators are required for dicts and object collections.
dict: { 'iterator': 'itervalues',
'_decorators': _dict_decorators(), },
diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py
index 05990e4ed..4f30f76ba 100644
--- a/lib/sqlalchemy/util.py
+++ b/lib/sqlalchemy/util.py
@@ -19,8 +19,49 @@ try:
Set = set
set_types = set, sets.Set
except NameError:
- Set = sets.Set
set_types = sets.Set,
+ # layer some of __builtin__.set's binop behavior onto sets.Set
+ class Set(sets.Set):
+ def _binary_sanity_check(self, other):
+ pass
+
+ def issubset(self, iterable):
+ other = type(self)(iterable)
+ return sets.Set.issubset(self, other)
+ def __le__(self, other):
+ sets.Set._binary_sanity_check(self, other)
+ return sets.Set.__le__(self, other)
+ def issuperset(self, iterable):
+ other = type(self)(iterable)
+ return sets.Set.issuperset(self, other)
+ def __ge__(self, other):
+ sets.Set._binary_sanity_check(self, other)
+ return sets.Set.__ge__(self, other)
+
+ # lt and gt still require a BaseSet
+ def __lt__(self, other):
+ sets.Set._binary_sanity_check(self, other)
+ return sets.Set.__lt__(self, other)
+ def __gt__(self, other):
+ sets.Set._binary_sanity_check(self, other)
+ return sets.Set.__gt__(self, other)
+
+ def __ior__(self, other):
+ if not isinstance(other, sets.BaseSet):
+ return NotImplemented
+ return sets.Set.__ior__(self, other)
+ def __iand__(self, other):
+ if not isinstance(other, sets.BaseSet):
+ return NotImplemented
+ return sets.Set.__iand__(self, other)
+ def __ixor__(self, other):
+ if not isinstance(other, sets.BaseSet):
+ return NotImplemented
+ return sets.Set.__ixor__(self, other)
+ def __isub__(self, other):
+ if not isinstance(other, sets.BaseSet):
+ return NotImplemented
+ return sets.Set.__isub__(self, other)
try:
import cPickle as pickle
@@ -186,11 +227,16 @@ def duck_type_collection(specimen, default=None):
"""
if hasattr(specimen, '__emulates__'):
- return specimen.__emulates__
+ # canonicalize set vs sets.Set to a standard: util.Set
+ if (specimen.__emulates__ is not None and
+ issubclass(specimen.__emulates__, set_types)):
+ return Set
+ else:
+ return specimen.__emulates__
isa = isinstance(specimen, type) and issubclass or isinstance
if isa(specimen, list): return list
- if isa(specimen, Set): return Set
+ if isa(specimen, set_types): return Set
if isa(specimen, dict): return dict
if hasattr(specimen, 'append'):
@@ -349,7 +395,8 @@ class OrderedDict(dict):
def __init__(self, ____sequence=None, **kwargs):
self._list = []
if ____sequence is None:
- self.update(**kwargs)
+ if kwargs:
+ self.update(**kwargs)
else:
self.update(____sequence, **kwargs)
@@ -539,6 +586,14 @@ class OrderedSet(Set):
__isub__ = difference_update
+ if hasattr(Set, '__getstate__'):
+ def __getstate__(self):
+ base = Set.__getstate__(self)
+ return base, self._list
+
+ def __setstate__(self, state):
+ Set.__setstate__(self, state[0])
+ self._list = state[1]
class IdentitySet(object):
"""A set that considers only object id() for uniqueness.