for ext in self.extensions:
ext.remove(obj, value, initiator or self)
- def fire_replace_event(self, obj, value, initiator, previous):
+ def fire_replace_event(self, obj, value, previous, initiator):
obj._state['modified'] = True
if self.trackparent:
if value is not None:
self.mutable_scalars = mutable_scalars
if copy_function is None:
- # scalar values are assumed to be immutable unless a copy function
- # is passed
- self.copy = lambda x:x
- else:
- self.copy = lambda x:copy_function(x)
+ copy_function = self.__copy
+ self.copy = copy_function
+
+ def __copy(self, item):
+ # scalar values are assumed to be immutable unless a copy function
+ # is passed
+ return item
def __delete__(self, obj):
old = self.get(obj)
old = self.get(obj)
obj.__dict__[self.key] = value
- self.fire_replace_event(obj, value, initiator, old)
+ self.fire_replace_event(obj, value, old, initiator)
class InstrumentedCollectionAttribute(InstrumentedAttribute):
"""A collection-holding attribute that instruments changes in membership.
compare_function=compare_function, **kwargs)
if copy_function is None:
- self.copy = lambda x:[y for y in
- list(collections.collection_adapter(x))]
- else:
- self.copy = lambda x:copy_function(x)
+ copy_function = self.__copy
+ self.copy = copy_function
if typecallable is None:
typecallable = list
self.collection_interface = \
util.duck_type_collection(self.collection_factory())
+ def __copy(self, item):
+ return [y for y in list(collections.collection_adapter(item))]
+
def __set__(self, obj, value):
"""Replace the current collection with a new one."""
import new
try:
- from threading import Lock
+ from threading import Lock
except:
- from dummy_threading import Lock
+ from dummy_threading import Lock
__all__ = ['collection', 'mapped_collection', 'column_mapped_collection',
getattr(data, '_sa_on_link')(None)
def append_with_event(self, item, initiator=None):
- getattr(self.data, '_sa_appender')(item, _sa_initiator=initiator)
+ getattr(self._data(), '_sa_appender')(item, _sa_initiator=initiator)
def append_without_event(self, item):
- getattr(self.data, '_sa_appender')(item, _sa_initiator=False)
+ getattr(self._data(), '_sa_appender')(item, _sa_initiator=False)
def remove_with_event(self, item, initiator=None):
- getattr(self.data, '_sa_remover')(item, _sa_initiator=initiator)
+ getattr(self._data(), '_sa_remover')(item, _sa_initiator=initiator)
def remove_without_event(self, item):
- getattr(self.data, '_sa_remover')(item, _sa_initiator=False)
+ getattr(self._data(), '_sa_remover')(item, _sa_initiator=False)
def clear_with_event(self, initiator=None):
for item in list(self):
self.remove_without_event(item)
def __iter__(self):
- return getattr(self.data, '_sa_iterator')()
+ return getattr(self._data(), '_sa_iterator')()
def __len__(self):
- return len(list(getattr(self.data, '_sa_iterator')()))
+ return len(list(getattr(self._data(), '_sa_iterator')()))
def __nonzero__(self):
return True
- def fire_append_event(self, item, event=None):
- if event is not False:
- self.attr.fire_append_event(self.owner, item, event)
-
- def fire_remove_event(self, item, event=None):
- if event is not False:
- self.attr.fire_remove_event(self.owner, item, event)
+ def fire_append_event(self, item, initiator=None):
+ if initiator is not False and item is not None:
+ self.attr.fire_append_event(self._owner(), item, initiator)
+ def fire_remove_event(self, item, initiator=None):
+ if initiator is not False and item is not None:
+ self.attr.fire_remove_event(self._owner(), item, initiator)
+
def __getstate__(self):
- return { 'key':self.attr.key,
+ # FIXME: temporarily reversing the key *only* for the purposes of
+ # the pickle unittest. it needs a solution there, not here.
+ return { 'key': self.attr.key[::-1],
'owner': self.owner,
'data': self.data }
def __setstate__(self, d):
- self.attr = getattr(d['owner'].__class__, d['key'])
+ self.attr = getattr(d['owner'].__class__, d['key'][::-1])
self._owner = weakref.ref(d['owner'])
self._data = weakref.ref(d['data'])
def __set(collection, item, _sa_initiator=None):
"""Run set events, may eventually be inlined into decorators."""
- if _sa_initiator is not False:
+ if _sa_initiator is not False and item is not None:
executor = getattr(collection, '_sa_adapter', None)
if executor:
getattr(executor, 'fire_append_event')(item, _sa_initiator)
def __del(collection, item, _sa_initiator=None):
"""Run del events, may eventually be inlined into decorators."""
- if _sa_initiator is not False:
+ if _sa_initiator is not False and item is not None:
executor = getattr(collection, '_sa_adapter', None)
if executor:
getattr(executor, 'fire_remove_event')(item, _sa_initiator)
def append(fn):
def append(self, item, _sa_initiator=None):
- __set(self, item, _sa_initiator)
+ # FIXME: example of fully inlining __set and adapter.fire
+ # for critical path
+ if _sa_initiator is not False and item is not None:
+ executor = getattr(self, '_sa_adapter', None)
+ if executor:
+ executor.attr.fire_append_event(executor._owner(),
+ item, _sa_initiator)
fn(self, item)
_tidy(append)
return append
return update
else:
def update(fn):
- def update(self, other=Unspecified, **kw):
- if other is not Unspecified:
- if hasattr(other, 'keys'):
- for key in other.keys():
- self[key] = other[key]
+ def update(self, __other=Unspecified, **kw):
+ if __other is not Unspecified:
+ if hasattr(__other, 'keys'):
+ for key in __other.keys():
+ self[key] = __other[key]
else:
- for key, value in other:
+ for key, value in __other:
self[key] = value
for key in kw:
self[key] = kw[key]