:meth:`MutableBase._parents` collection is restored to all ``Point`` objects.
"""
+from collections import defaultdict
import weakref
from .. import event
val = state.dict.get(key, None)
if val is not None:
if "ext.mutable.values" not in state_dict:
- state_dict["ext.mutable.values"] = []
- state_dict["ext.mutable.values"].append(val)
+ state_dict["ext.mutable.values"] = defaultdict(list)
+ state_dict["ext.mutable.values"][key].append(val)
def unpickle(state, state_dict):
if "ext.mutable.values" in state_dict:
- for val in state_dict["ext.mutable.values"]:
+ for val in state_dict["ext.mutable.values"][key]:
val._parents[state] = key
event.listen(parent_cls, "load", load, raw=True, propagate=True)
from sqlalchemy import event
from sqlalchemy import ForeignKey
from sqlalchemy import func
+from sqlalchemy import inspect
from sqlalchemy import Integer
+from sqlalchemy import select
from sqlalchemy import String
from sqlalchemy import testing
from sqlalchemy import util
from sqlalchemy.orm import column_property
from sqlalchemy.orm import composite
from sqlalchemy.orm import declarative_base
+from sqlalchemy.orm import Session
from sqlalchemy.orm.instrumentation import ClassManager
from sqlalchemy.orm.mapper import Mapper
from sqlalchemy.testing import assert_raises
pass
+class Foo2(fixtures.BasicEntity):
+ pass
+
+
class FooWithEq(object):
def __init__(self, **kw):
for k in kw:
ClassManager.dispatch._clear()
+class MiscTest(fixtures.TestBase):
+ @testing.combinations(True, False, argnames="pickleit")
+ def test_pickle_parent_multi_attrs(self, registry, connection, pickleit):
+ """test #8133"""
+
+ local_foo = Table(
+ "lf",
+ registry.metadata,
+ Column("id", Integer, primary_key=True),
+ Column("j1", MutableDict.as_mutable(PickleType)),
+ Column("j2", MutableDict.as_mutable(PickleType)),
+ Column("j3", MutableDict.as_mutable(PickleType)),
+ Column("j4", MutableDict.as_mutable(PickleType)),
+ )
+
+ registry.map_imperatively(Foo2, local_foo)
+ registry.metadata.create_all(connection)
+
+ with Session(connection) as sess:
+
+ data = dict(
+ j1={"a": 1},
+ j2={"b": 2},
+ j3={"c": 3},
+ j4={"d": 4},
+ )
+ lf = Foo2(**data)
+ sess.add(lf)
+ sess.commit()
+
+ all_attrs = {"j1", "j2", "j3", "j4"}
+ for attr in all_attrs:
+ for loads, dumps in picklers():
+ with Session(connection) as sess:
+ f1 = sess.scalars(select(Foo2)).first()
+ if pickleit:
+ f2 = loads(dumps(f1))
+ else:
+ f2 = f1
+
+ existing_dict = getattr(f2, attr)
+ existing_dict["q"] = "c"
+ eq_(
+ inspect(f2).attrs[attr].history,
+ ([existing_dict], (), ()),
+ )
+ for other_attr in all_attrs.difference([attr]):
+ a = inspect(f2).attrs[other_attr].history
+ b = ((), [data[other_attr]], ())
+ eq_(a, b)
+
+
class _MutableDictTestBase(_MutableDictTestFixture):
run_define_tables = "each"