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