assuming you can try 0.8 which provides inspect(), this will show what is 
happening:

from sqlalchemy import inspect
print "--------------------"

p.children[2] = c2
print p.children
print inspect(c2).attrs.parent.history
print inspect(c3).attrs.parent.history
print "--------------------"

p.children[1] = c3
print p.children
print inspect(c2).attrs.parent.history
print inspect(c3).attrs.parent.history
print "--------------------"


we see:

--------------------
[Mary, John, John]
History(added=(), unchanged=[Thomas], deleted=())
History(added=[None], unchanged=(), deleted=[Thomas])
--------------------
[Mary, Kenny, John]
History(added=[None], unchanged=(), deleted=[Thomas])
History(added=(), unchanged=[Thomas], deleted=())
--------------------


basically, "somecollection[n] = someobject" will also fire a backref event.   
The object already at somecollection[n] fires a replace event, which sends a 
"remove" to the backref at somecollection[n].  

The confusion arises because "p.children[2] = c2" means that c2 is now present 
in the list twice, which is not a condition the collection mechanics support.   
The assignment back of "c3" leads the system to believe that "c2" is being 
removed from the collection, hence the backref sets "c2.parent" to None, yet c2 
is in the list twice so it isn't actually being removed.   It's the backref 
event being fired off inappropriately that's the core of the issue.   Tracking 
this count like the ticket states would add an expensive id() + dictionary 
storage for all objects in all collections everywhere, for a pretty infrequent 
use case, hitting us both in memory and time spent.   It's a bad situation.   i 
can see having this as perhaps an option on relationship(), track_dupes=True, 
we'd have to recommend it in conjunction with ordering_list.  

Some ways to work around include, assigning a slice, so that both items are 
removed first:

p.children[1:2] = [c2, c1]

or just doing the second set event again:

p.children[1], p.children[2] = p.children[2], p.children[1]
p.children[1] = p.children[1]

I'll add these workarounds to the ticket.




On Jan 7, 2013, at 9:09 PM, Alexey Vihorev wrote:

> Tried to replace this with this,  but results are the same
>  
> temp1 = p.children[1]
> 
> temp2 = p.children[2]
> 
>  
> 
> p.children[2] = temp1
> 
> p.children[1] = temp2
> 
>  
> From: sqlalchemy@googlegroups.com [mailto:sqlalchemy@googlegroups.com] On 
> Behalf Of Michael Bayer
> Sent: Tuesday, January 08, 2013 2:23 AM
> To: sqlalchemy@googlegroups.com
> Subject: Re: [sqlalchemy] Strange behaviour while trying to swap related 
> records, or am I doing it wrong?
>  
>  
> On Jan 7, 2013, at 7:05 PM, Alexey Vihorev wrote:
>  
> p.children[1], p.children[2] = p.children[2], p.children[1]
> print(p.children) #prints [Mary, Kenny, John]
>  
>  
> yeah, without looking too deeply I'm fairly certain this is this trac ticket:
>  
> http://www.sqlalchemy.org/trac/ticket/1103
>  
>  
> basically would add a good chunk of complexity and overhead to the list 
> instrumentation.   this is a "blue sky" ticket for that reason.   For now 
> you'd need to just assign to an intermediary variable and do one assignment 
> at a time.
>  
>  
>  
> -- 
> 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 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.
> 
> -- 
> 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 
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/sqlalchemy?hl=en.

-- 
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 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to