mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-06-01 05:18:44 -04:00
- fixed __setstate__ method of CollectionAdapter to not
fail during deserialize where parent InstanceState not yet unserialized. [ticket:1802]
This commit is contained in:
@@ -12,6 +12,10 @@ CHANGES
|
||||
- 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
|
||||
|
||||
@@ -471,15 +471,20 @@ class CollectionAdapter(object):
|
||||
|
||||
"""
|
||||
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)
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
"The entity collection being adapted."
|
||||
return self._data()
|
||||
|
||||
data = property(lambda s: s._data(),
|
||||
doc="The entity collection being adapted.")
|
||||
|
||||
@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)
|
||||
@@ -619,12 +624,12 @@ class CollectionAdapter(object):
|
||||
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'])
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import pickle
|
||||
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,\
|
||||
@@ -218,6 +218,49 @@ class PickleTest(_fixtures.FixtureTest):
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user