diff options
| author | Jason Kirtland <jek@discorporate.us> | 2008-01-21 23:19:39 +0000 |
|---|---|---|
| committer | Jason Kirtland <jek@discorporate.us> | 2008-01-21 23:19:39 +0000 |
| commit | 412c80dd6c5d6b940e86e7e142aa1fdd6ee4466d (patch) | |
| tree | 2a5bfa8185dd888d52b31bfb26ada56c7db89139 /lib/sqlalchemy | |
| parent | 08bbc3dfd84234c3cd691e43ff17ed36e2396d76 (diff) | |
| download | sqlalchemy-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.py | 8 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/collections.py | 58 | ||||
| -rw-r--r-- | lib/sqlalchemy/util.py | 63 |
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. |
