The following code duplicates a situation I'm seeing with the
association proxy.  There are at least two ways I can avoid having the
error happen.  But since I wasn't sure if the error is a usage error,
I wanted to post here first before implementing my work around.  One
work around for the test code is to delete/comment out line 77
(commented as such).

Here is the traceback of the error (run against r4588):

Traceback (most recent call last):
  File "atest.py", line 82, in <module>
    have_a_kid('A', 'b') # fails with 'stale association proxy...'
  File "atest.py", line 34, in have_a_kid
    if k.kid_name not in [kk.kid_name for kk in p.kids]:
  File "/home/sim/en36219/.python/sqlalchemy/ext/associationproxy.py",
line 353, in __iter__
    for member in self.col:
  File "/home/sim/en36219/.python/sqlalchemy/ext/associationproxy.py",
line 271, in <lambda>
    col = property(lambda self: self.lazy_collection())
  File "/home/sim/en36219/.python/sqlalchemy/ext/associationproxy.py",
line 140, in lazy_collection
    "stale association proxy, parent object has gone out of "
sqlalchemy.exceptions.InvalidRequestError: stale association proxy,
parent object has gone out of scope

Here is the code:

from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy import (
    create_engine, MetaData, Table, Column, Integer, String,
ForeignKey)
from sqlalchemy.orm import mapper, relation, create_session

class Parent(object):
    kids = association_proxy('kid_associations', 'kid',
        creator=lambda x,**kw: Parent_x_Kid(x, **kw))

    def __init__(self, name):
        self.parent_name = name
    def __repr__(self):
        return 'Parent(%s)' % self.parent_name

class Kid(object):
    parents = association_proxy('parent_associations', 'parent',
        creator=lambda x,**kw: Parent_x_Kid(x, **kw))

    def __init__(self, name):
        self.kid_name = name
    def __repr__(self):
        return 'Kid(%s)' % self.kid_name

class Parent_x_Kid(object):
    def __init__(self, kid):
        self.kid = kid
    def __repr__(self):
        return 'PK(%s,%s)' % (self.parent.parent_name,
self.kid.kid_name)

def have_a_kid(p_name, k_name):
    p = session.query(Parent).filter_by(parent_name = p_name).one()
    k = session.query(Kid).filter_by(kid_name = k_name).one()

    if k.kid_name not in [kk.kid_name for kk in p.kids]:
        p.kids.append(k)
    else:
        print "%s already has a %s" % (p, k)

db_con = create_engine('sqlite:///:memory:')
metadata = MetaData(db_con)
# TABLE CREATION
parents = Table('parents', metadata,
    Column('parent_id', Integer, primary_key=True),
    Column('parent_name', String(30), nullable=False)
    )
kids = Table('kids', metadata,
    Column('kid_id', Integer, primary_key=True),
    Column('kid_name', String(30), nullable=False)
    )
parent_x_kid = Table('parent_x_kid', metadata,
    Column('parent_id', Integer, ForeignKey('parents.parent_id'),
        primary_key=True),
    Column('kid_id', Integer, ForeignKey('kids.kid_id'),
        primary_key=True),
    )
metadata.create_all()
# MAPPERS
mapper(Parent_x_Kid, parent_x_kid, properties={
    'parent':relation(Parent, lazy=False),
    'kid':relation(Kid, lazy=False)
    })
mapper(Parent, parents, properties={
    'kid_associations':relation(
    Parent_x_Kid, cascade='all, delete-orphan', lazy=True)
    })
mapper(Kid, kids, properties={
    'parent_associations':relation(
    Parent_x_Kid, cascade='all, delete-orphan', lazy=True)
    })
session = create_session()
# TEST DATA CREATION
p_s = [Parent('A'), Parent('B'), Parent('C'), Parent('D')]
k_s = [Kid('a'), Kid('b'), Kid('c'), Kid('d'), Kid('e')]
[session.save(x) for x in p_s]
[session.save(x) for x in k_s]
session.flush()
session.clear() # LINE 77, delete to make this code work
have_a_kid('A', 'a')
have_a_kid('B', 'b')
have_a_kid('C', 'b')
have_a_kid('D', 'c')
have_a_kid('A', 'b') # fails with 'stale association proxy...'
have_a_kid('A', 'c')
have_a_kid('B', 'c')
have_a_kid('A', 'e')
session.flush()
# PRINTING TEST DATA
session.clear()
pA = session.query(Parent).filter_by(parent_name = 'A').one()
print pA
print "  ", pA.kids
pB = session.query(Parent).filter_by(parent_name = 'B').one()
print pB
print "  ", pB.kids
ka = session.query(Kid).filter_by(kid_name = 'a').one()
print ka
print "  ", ka.parents
kb = session.query(Kid).filter_by(kid_name = 'b').one()
print kb
print "  ", kb.parents

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to