if we had some help.   the next time I have time to work on SQLAlchemy  
the 0.6 release is my top priority.  this particular issue is a  
behavioral quirk with multiple, straightforward workarounds, and it  
also not entirely clear if continuing event chains in the manner I'm  
proposing is even going to work for all situations - in any case its a  
pretty significant behavioral change.


On Apr 18, 2009, at 5:12 AM, jean-philippe dutreve wrote:

>
> Hi, any chance to have a fix for this?
>
> On 6 avr, 17:16, "Michael Bayer" <mike...@zzzcomputing.com> wrote:
>> OK in fact this can possibly be implemented if the "initiator" passed
>> during attribute mutation operations consisted of not just an
>> AttributeImpl but also a target instance, so that append/remove/set
>> operations can have the information they need continue down the  
>> chain of
>> events without exiting prematurely.  Such as this test below:
>>
>> from sqlalchemy import *
>> from sqlalchemy.orm import *
>> from sqlalchemy.ext.declarative import declarative_base
>>
>> Base = declarative_base()
>>
>> class Parent(Base):
>>    __tablename__ = 'parent'
>>
>>    id = Column(Integer, primary_key=True)
>>    stuff = relation("Stuff", backref="parent")
>>
>> class Stuff(Base):
>>    __tablename__ = 'stuff'
>>
>>    id = Column(Integer, primary_key=True)
>>    parent_id = Column(Integer, ForeignKey('parent.id'))
>>
>> p1 = Parent()
>> p2 = Parent()
>> s1 = Stuff()
>>
>> p1.stuff.append(s1)
>> p2.stuff.append(s1)
>> assert s1.parent is p2
>> assert s1 not in p1.stuff
>> assert s1 in p2.stuff
>>
>> can be made to pass if we say this:
>>
>> Index: lib/sqlalchemy/orm/attributes.py
>> ===================================================================
>> --- lib/sqlalchemy/orm/attributes.py    (revision 5901)
>> +++ lib/sqlalchemy/orm/attributes.py    (working copy)
>> @@ -679,9 +679,6 @@
>>             collection.append_with_event(value, initiator)
>>
>>     def remove(self, state, value, initiator, passive=PASSIVE_OFF):
>> -        if initiator is self:
>> -            return
>> -
>>         collection = self.get_collection(state, passive=passive)
>>         if collection is PASSIVE_NORESULT:
>>             self.fire_remove_event(state, value, initiator)
>>
>> so some more complete way of not exiting the event loop too soon  
>> would
>> need to be implemented.
>>
>> Jason, any comments on this ?
>>
>> jean-philippe dutreve wrote:
>>
>>> It would be fine/safe that accountA has entry removed BEFORE any
>>> reload (with explicit refresh/expire/commit). I can't remember,  
>>> but a
>>> previous version of SA had this behavior.
>>
>>> On Apr 6, 4:42 pm, "Michael Bayer" <mike...@zzzcomputing.com> wrote:
>>>> im slightly confused.  the backref should be automatically  
>>>> reparenting,
>>>> not sure if ordering_list interferes with that, but in any case  
>>>> after
>>>> you
>>>> flush()/expire() or commit(), it will definitely happen since all
>>>> collections will load fresh.
>>
>>>> Mike Conley wrote:
>>>>> So, we would like SA to have some kind of operation like
>>>> "reparent_item()"
>>>>> that would move anobjectfrom one relation to another.
>>>>> It seems to me that this is is better handled as a piece of
>>>> application
>>>>> business logic. In this case, provide a "move_entry()" function  
>>>>> that
>>>>> properly encapsulates inserting and removing the entry in a single
>>>>> operation. I can imagine that there would be many variations on
>>>> business
>>>>> rules formovingan item that would be difficult to encapsulate in a
>>>>> common
>>>>> operation within SA.
>>
>>>>> --
>>>>> Mike Conley
>>
>>>>> On Mon, Apr 6, 2009 at 2:10 AM, jean-philippe dutreve
>>>>> <jdutr...@gmail.com>wrote:
>>
>>>>>> Currently, I use accountA.remove(entry) and I have rewritten  
>>>>>> insort
>>>> to
>>>>>> bypass the bug you say.
>>
>>>>>> So, AFAIK, whereas an entry has only one account (via
>>>>>> entry.account_id), SA can't remove the first relation.
>>>>>> It's dangerous, because if developer forget to remove the first
>>>>>> relation, the entry is contained in 2 accounts temporaly.
>>>>>> It can lead to false computation (when summing balance for  
>>>>>> instance).
>>
>>>>>> On 5 avr, 22:03, jason kirtland <j...@discorporate.us> wrote:
>>>>>>> jean-philippe dutreve wrote:
>>>>>>>> Hi all,
>>
>>>>>>>> I wonder if SA can handle this use case:
>>
>>>>>>>> An Account can contain Entries ordered by 'position' attribute.
>>
>>>>>>>> mapper(Account, table_accounts, properties = dict(
>>>>>>>>    entries = relation(Entry, lazy=True,
>>>>>> collection_class=ordering_list
>>>>>>>> ('position'),
>>>>>>>>        order_by=[table_entries.c.position],
>>>>>>>>        passive_deletes='all', cascade='save-update',
>>>>>>>>        backref=backref('account', lazy=False),
>>>>>>>>    ),
>>>>>>>> ))
>>
>>>>>>>> I'd like to move an entry from accountA to accountB and let SA
>>>>>> remove
>>>>>>>> the link between the entry and accountA:
>>
>>>>>>>>    entry = accountA.entries[0]
>>>>>>>>    insort_right(accountB.entries, entry)
>>>>>>>>    assert not entry in accountA.entries    # false, entry is
>>>> still
>>>>>> in
>>>>>>>> accountA !!!!
>>
>>>>>>>> It is possible?
>>
>>>>>>> Try removing the entry from accountA:
>>
>>>>>>>     entry = accountA.pop(0)
>>>>>>>     ...
>>
>>>>>>> Also beware that bisect insort has a bug that prevents it from
>>>> working
>>>>>>> properly with list subclasses like ordering_list (or any SA
>>>> list-based
>>>>>>> collection).  I think it's fixed in Python 3.0, not sure if  
>>>>>>> the fix
>>>>>> was
>>>>>>> backported to 2.x.
> >


--~--~---------~--~----~------------~-------~--~----~
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