- changed status to resolved
identified where pickle.loads() hits CollectionAdapter before the InstanceState is built
Issue #1802
resolved
thanks to avdd for this
import pickle
import sqlalchemy as sql
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base
engine = sql.create_engine("sqlite:///:memory:")
Model = declarative_base()
class Child1(Model):
__tablename__ = 'child1'
parent_id = sql.Column(sql.String,
sql.ForeignKey('parent.id'),
primary_key=True)
class Child2(Model):
__tablename__ = 'child2'
parent_id = sql.Column(sql.String,
sql.ForeignKey('parent.id'),
primary_key=True)
class Parent(Model):
__tablename__ = 'parent'
id = sql.Column(sql.String, primary_key=True)
children1 = orm.relation(Child1)
children2 = orm.relation(Child2)
class Screen:
def __init__(self, obj, parent=None):
self.obj = obj
self.parent = parent
obj = Parent()
screen1 = Screen(obj)
screen1.errors = [obj.children2](obj.children1,)
screen2 = Screen(Child2(), screen1)
pickle.loads(pickle.dumps(screen2))
here's a patch:
diff -r 25e7dc60dfa739692421a9576c83f2db29f73cb2 lib/sqlalchemy/orm/collections.py
--- a/lib/sqlalchemy/orm/collections.py Mon May 10 11:37:48 2010 -0400
+++ b/lib/sqlalchemy/orm/collections.py Thu May 13 11:18:14 2010 -0400
@@ -471,14 +471,19 @@
"""
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.")
+
+ @util.memoized_property
+ def attr(self):
+ return self.owner_state.manager[self._key](self._key).impl
+
+ @property
+ def data(self):
+ "The entity collection being adapted."
+ return self._data()
def link_to_self(self, data):
"""Link a collection to this adapter, and fire a link event."""
@@ -610,12 +615,12 @@
self.attr.fire_pre_remove_event(self.owner_state, self.owner_state.dict, 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']('owner_state').obj().__class__, d['key']('key')).impl
+ self._key = d['key']('key')
self.owner_state = d['owner_state']('owner_state')
self._data = weakref.ref(d['data']('data'))
Comments (2)
-
reporter -
reporter - removed milestone
Removing milestone: 0.6.1 (automated comment)
- Log in to comment
e352e255a749b6e75e18bd41bf6646eeea345442