- session.merge() will not expire attributes on the returned
instance if that instance is "pending". [ticket:1789]
+ - fixed __setstate__ method of CollectionAdapter to not
+ fail during deserialize where parent InstanceState not
+ yet unserialized. [ticket:1802]
+
- sql
- expr.in_() now accepts a text() construct as the argument.
Grouping parenthesis are added automatically, i.e. usage
"""
def __init__(self, attr, owner_state, data):
- self.attr = attr
- # TODO: figure out what this being a weakref buys us
+ self._key = attr.key
self._data = weakref.ref(data)
self.owner_state = owner_state
self.link_to_self(data)
-
- data = property(lambda s: s._data(),
- doc="The entity collection being adapted.")
-
+
+ @property
+ def data(self):
+ "The entity collection being adapted."
+ return self._data()
+
+ @util.memoized_property
+ def attr(self):
+ return self.owner_state.manager[self._key].impl
+
def link_to_self(self, data):
"""Link a collection to this adapter, and fire a link event."""
setattr(data, '_sa_adapter', self)
initiator=initiator)
def __getstate__(self):
- return {'key': self.attr.key,
+ return {'key': self._key,
'owner_state': self.owner_state,
'data': self.data}
def __setstate__(self, d):
- self.attr = getattr(d['owner_state'].obj().__class__, d['key']).impl
+ self._key = d['key']
self.owner_state = d['owner_state']
self._data = weakref.ref(d['data'])
import sqlalchemy as sa
from sqlalchemy.test import testing
from sqlalchemy.test.testing import assert_raises_message
-from sqlalchemy import Integer, String, ForeignKey, exc
+from sqlalchemy import Integer, String, ForeignKey, exc, MetaData
from sqlalchemy.test.schema import Table, Column
from sqlalchemy.orm import mapper, relationship, create_session, \
sessionmaker, attributes, interfaces,\
u2 = pickle.loads(pickle.dumps(u1))
+ def test_collection_setstate(self):
+ """test a particular cycle that requires CollectionAdapter
+ to not rely upon InstanceState to deserialize."""
+
+ global Child1, Child2, Parent, Screen
+
+ m = MetaData()
+ c1 = Table('c1', m,
+ Column('parent_id', String,
+ ForeignKey('p.id'), primary_key=True)
+ )
+ c2 = Table('c2', m,
+ Column('parent_id', String,
+ ForeignKey('p.id'), primary_key=True)
+ )
+ p = Table('p', m,
+ Column('id', String, primary_key=True)
+ )
+ class Child1(_base.ComparableEntity):
+ pass
+
+ class Child2(_base.ComparableEntity):
+ pass
+
+ class Parent(_base.ComparableEntity):
+ pass
+
+ mapper(Parent, p, properties={
+ 'children1':relationship(Child1),
+ 'children2':relationship(Child2)
+ })
+ mapper(Child1, c1)
+ mapper(Child2, c2)
+ class Screen(object):
+ def __init__(self, obj, parent=None):
+ self.obj = obj
+ self.parent = parent
+
+ obj = Parent()
+ screen1 = Screen(obj)
+ screen1.errors = [obj.children1, obj.children2]
+ screen2 = Screen(Child2(), screen1)
+ pickle.loads(pickle.dumps(screen2))
class PolymorphicDeferredTest(_base.MappedTest):
@classmethod