mutable composites lose track of parent after a flush

Issue #2308 resolved
Mike Bayer repo owner created an issue
from sqlalchemy import MetaData, Column, create_engine
from sqlalchemy.types import Integer, String
from sqlalchemy.orm import create_session, composite
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.mutable import MutableComposite

engine = create_engine('sqlite://', echo=True)
metadata = MetaData(bind=engine)
Base = declarative_base(metadata=metadata)


class MyComposite(MutableComposite):

    def __init__(self, a, b):
        self.a = a
        self.b = b

    def __composite_values__(self):
        return (self.a, self.b)

    def __getstate__(self):
        return self.__composite_values__()

    def __setstate__(self, state):
        (self.a, self.b) = state

    def __setattr__(self, key, value):
        object.__setattr__(self, key, value)
        self.changed()


class Foo(Base):
    __tablename__ = 'foos'
    id = Column(Integer, primary_key=True)
    name = Column(String(50))
    comp = composite(MyComposite,
                     Column('a', String(50)),
                     Column('b', String(50)))


metadata.drop_all()
metadata.create_all()

sess = create_session()

foo = Foo()
sess.add(foo)

sess.flush()
sess.expunge_all()

##########
print "loading a foo instance"
foo = sess.query(Foo).get(1)

print "changing foo.name"
foo.name = 'changed'

print "before flush, foo.comp._parents is %r" % foo.comp._parents.items()
sess.flush()
print "after flush, foo.comp._parents is %r" % foo.comp._parents.items()

print "changing foo.comp.a"
foo.comp.a = 'hello'

print "flushing again"
sess.flush()
sess.expunge_all()

##########

print "checking that change to composite was persisted"
foo = sess.query(Foo).get(1)
assert foo.comp.a == 'hello'
print "good"

Comments (2)

  1. Log in to comment