[sqlalchemy] Re: moving an object
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.comwrote: 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,
[sqlalchemy] Re: moving an object
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.comwrote: 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.
[sqlalchemy] Re: moving an object
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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: moving an object
So, we would like SA to have some kind of operation like reparent_item() that would move an object from 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 for moving an 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.comwrote: 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: moving an object
The object doesn't move from one relation to another : this is the same relation 'entries' but on a different parent. This is common to any parent.child pattern, not a business specific case. The current behavior is not consistent because as soon as we commit() + refresh(), the object is not on accountA anymore (entry.account_id has changed). This end result should be reflected in memory just after the change too (i.e. before commit). On Apr 6, 1:10 pm, Mike Conley mconl...@gmail.com wrote: So, we would like SA to have some kind of operation like reparent_item() that would move an object from 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 for moving an 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.comwrote: 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: moving an object
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 an object from 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 for moving an 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.comwrote: 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: moving an object
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 an object from 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 for moving an 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.comwrote: 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: moving an object
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 an object from 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 for moving an 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.comwrote: 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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: moving an object
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 -~--~~~~--~~--~--~---