[sqlalchemy] ORM Event

2011-08-25 Thread Jaimy Azle
Hi,

I found some weird case on using the mapper event, i setup the mapper
to firing after_insert and after_delete event. However i find some
issue, at least weird behaviour:

* after_insert and after_delete triggered only once on each committed
  transaction.

  dt_1 = Detail(1, 1, 'This is detail')
  dt_2 = Detail(1, 2, 'This is detail')
  session.add(dt_1)
  session.add(dt_2)
  session.commit() # this only fire before insert only once

* no additional data manipulation inside each event could be
  persisted.

  def model_after_insert(mapper, connection, target):
if target.__tablename__ == 'detail':
master = session.query(klass).filter_by(id = target.master).first()
if master:
   master.total = master.total + 1
   session.add(master)   # nothing would be persisted on this

Full example attached below, is there anything i had missed?

-- 
Salam,

-Jaimy Azle

 code snippet -
from sqlalchemy import create_engine, event
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker, mapper
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=engine)

klass = None

def model_after_insert(mapper, connection, target):
  if target.__tablename__ == 'detail':
master = session.query(klass).filter_by(id = target.master).first()
if master:
  master.total = master.total + 1
  session.add(master)
  print('after insert', master.total)
  
def model_after_delete(mapper, connection, target):
  if target.__tablename__ == 'detail':
master = session.query(klass).filter_by(id = target.master).first()
if master:
  master.total = master.total - 1  
  session.add(master)
  print('after delete', master.total)
  

event.listen(mapper, 'after_insert', model_after_insert)
event.listen(mapper, 'after_delete', model_after_delete)

class Master(Base):
  __tablename__ = 'master'
  id = Column(Integer, primary_key=True)
  name = Column(String)
  total = Column(Integer)
  
  def __init__(self, name):
self.name = name
self.total = 0

class Detail(Base):
  __tablename__ = 'detail'  
  id = Column(Integer, primary_key=True)  
  master = Column(Integer, primary_key=True)
  name = Column(String)
  
  def __init__(self, id, master, name):
self.id = id
self.name = name
self.master = master  

klass = Master

Base.metadata.create_all(engine)
session = Session()

master = Master('hello world')  
session.add(master)
session.commit()

dt_1 = Detail(1, 1, 'This is detail')
dt_2 = Detail(1, 2, 'This is detail')
session.add(dt_1)
session.add(dt_2)
session.commit()

master = session.query(Master).filter_by(id = 1).first()
print('total ', master.total)


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



Re: [sqlalchemy] ORM Event

2011-08-25 Thread Michael Bayer
The Session is not usable in the way you're using it inside of after_insert and 
after_delete - in particular the modifications made to the state of the object 
that was just inserted will be discarded, and the add() will have no effect as 
the flush plan cannot be changed in these events.

To modify the Session's flush plan within a flush event, use the before_flush() 
session event.


There are guidelines to this effect on before_insert() 
http://www.sqlalchemy.org/docs/orm/events.html?highlight=after_insert#sqlalchemy.orm.events.MapperEvents.before_insert
  but I'll need to add similar language to after_() also.  look for that soon.




On Aug 25, 2011, at 6:45 AM, Jaimy Azle wrote:

 Hi,
 
 I found some weird case on using the mapper event, i setup the mapper
 to firing after_insert and after_delete event. However i find some
 issue, at least weird behaviour:
 
 * after_insert and after_delete triggered only once on each committed
  transaction.
 
  dt_1 = Detail(1, 1, 'This is detail')
  dt_2 = Detail(1, 2, 'This is detail')
  session.add(dt_1)
  session.add(dt_2)
  session.commit() # this only fire before insert only once
 
 * no additional data manipulation inside each event could be
  persisted.
 
  def model_after_insert(mapper, connection, target):
if target.__tablename__ == 'detail':
master = session.query(klass).filter_by(id = target.master).first()
if master:
   master.total = master.total + 1
   session.add(master)   # nothing would be persisted on this
 
 Full example attached below, is there anything i had missed?
 
 -- 
 Salam,
 
 -Jaimy Azle
 
  code snippet -
 from sqlalchemy import create_engine, event
 from sqlalchemy import Column, Integer, String
 from sqlalchemy.orm import sessionmaker, mapper
 from sqlalchemy.ext.declarative import declarative_base
 
 Base = declarative_base()
 engine = create_engine('sqlite:///:memory:')
 Session = sessionmaker(bind=engine)
 
 klass = None
 
 def model_after_insert(mapper, connection, target):
  if target.__tablename__ == 'detail':
master = session.query(klass).filter_by(id = target.master).first()
if master:
  master.total = master.total + 1
  session.add(master)
  print('after insert', master.total)
 
 def model_after_delete(mapper, connection, target):
  if target.__tablename__ == 'detail':
master = session.query(klass).filter_by(id = target.master).first()
if master:
  master.total = master.total - 1  
  session.add(master)
  print('after delete', master.total)
 
 
 event.listen(mapper, 'after_insert', model_after_insert)
 event.listen(mapper, 'after_delete', model_after_delete)
 
 class Master(Base):
  __tablename__ = 'master'
  id = Column(Integer, primary_key=True)
  name = Column(String)
  total = Column(Integer)
 
  def __init__(self, name):
self.name = name
self.total = 0
 
 class Detail(Base):
  __tablename__ = 'detail'  
  id = Column(Integer, primary_key=True)  
  master = Column(Integer, primary_key=True)
  name = Column(String)
 
  def __init__(self, id, master, name):
self.id = id
self.name = name
self.master = master  
 
 klass = Master
 
 Base.metadata.create_all(engine)
 session = Session()
 
 master = Master('hello world')  
 session.add(master)
 session.commit()
 
 dt_1 = Detail(1, 1, 'This is detail')
 dt_2 = Detail(1, 2, 'This is detail')
 session.add(dt_1)
 session.add(dt_2)
 session.commit()
 
 master = session.query(Master).filter_by(id = 1).first()
 print('total ', master.total)
 
 
 -- 
 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.



Re: [sqlalchemy] ORM Event

2011-08-25 Thread Jaimy Azle
On Thursday, August 25, 2011, 7:36:53 PM, Michael Bayer wrote:

Thanks Michael,

 The Session is not usable in the way you're using it inside of
 after_insert and after_delete - in particular the modifications made
 to the state of the object that was just inserted will be discarded,
 and the add() will have no effect as the flush plan cannot be
 changed in these events.

Still, there is an odd issue here, those mapper event only triggered
on first instance only.

 dt_1 = Detail(1, 1, 'This is detail')
 dt_2 = Detail(1, 2, 'This is detail')
 session.add(dt_1)
 session.add(dt_2)
 session.commit()  # only the first instance call after_insert
   # event, not all

 To modify the Session's flush plan within a flush event, use the
 before_flush() session event.

How to retrieve affected instances with their state (being inserted,
updated, or deleted) that belong to a flush operation? for this case I
need to validate each instance after they were inserted or before they
were deleted from a persistence storage and adjust some rows from
another table.


-- 
Salam,

-Jaimy Azle

“+1 for stating fact: Perl is dead. Please 
don't bring it back” – Matt Joiner
“-1 for spreading FUD about perl. It's 
absolutely not dead.” – Daenyth
“+1 + -1 = 0, then, is perl a zombie?” – joaquin
-- http://stackoverflow.com/questions/3384385/python-3-2-gil-good-bad

-- 
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] attempting to override __sa_instrumentation_manager__

2011-08-25 Thread Kent
Assume I have a class hierarchy:

class Base(object):
  __sa_instrumentation_manager__ = AttrManager

class Order(Base):
  __sa_instrumentation_manager__ = OrderAttrManager


This causes TypeError: multiple instrumentation implementations
specified in Order inheritance hierarchy:

I don't understand why or how I can go about overriding the
AttributeManager for a specific class.  I want 95% of the classes to
use AttrManager, but I want a specific one for OrderAttrManager.

What am I doing wrong?

-- 
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: attempting to override __sa_instrumentation_manager__

2011-08-25 Thread Kent
We are still running 0.6.4 so I think that was the only way to
implement events (set/append/remove), correct?


On Aug 25, 12:38 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 ho boy.  Why are you playing with instrumentation ?   That's a really obscure 
 feature we created literally for one product.   I'd love to blow it away.   
 Anyway, if that's the error its giving you, then that's definitely one of its 
 limitations :).

 On Aug 25, 2011, at 11:10 AM, Kent wrote:







  Assume I have a class hierarchy:

  class Base(object):
   __sa_instrumentation_manager__ = AttrManager

  class Order(Base):
   __sa_instrumentation_manager__ = OrderAttrManager

  This causes TypeError: multiple instrumentation implementations
  specified in Order inheritance hierarchy:

  I don't understand why or how I can go about overriding the
  AttributeManager for a specific class.  I want 95% of the classes to
  use AttrManager, but I want a specific one for OrderAttrManager.

  What am I doing wrong?

  --
  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 
  athttp://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.



Re: [sqlalchemy] ORM Event

2011-08-25 Thread Michael Bayer

On Aug 25, 2011, at 10:22 AM, Jaimy Azle wrote:

 On Thursday, August 25, 2011, 7:36:53 PM, Michael Bayer wrote:
 
 Thanks Michael,
 
 The Session is not usable in the way you're using it inside of
 after_insert and after_delete - in particular the modifications made
 to the state of the object that was just inserted will be discarded,
 and the add() will have no effect as the flush plan cannot be
 changed in these events.
 
 Still, there is an odd issue here, those mapper event only triggered
 on first instance only.

I would ask why you believe that's true - from what I can tell, you're using 
the Session.add() or something as a means to test that the event is triggered, 
which as I mentioned will have side effects.

A proper test as below indicates two inserts for Detail, one insert for Master, 
as expected:

import collections
total_insert_calls = collections.defaultdict(int)
total_delete_calls = collections.defaultdict(int)

def model_after_insert(mapper, connection, target):
total_insert_calls[mapper.class_] += 1

def model_after_delete(mapper, connection, target):
total_delete_calls[mapper.class_] += 1

...

assert total_insert_calls[Master] == 1
assert total_insert_calls[Detail] == 2
assert not total_delete_calls

script is attached.

 
 dt_1 = Detail(1, 1, 'This is detail')
 dt_2 = Detail(1, 2, 'This is detail')
 session.add(dt_1)
 session.add(dt_2)
 session.commit()  # only the first instance call after_insert
  # event, not all
 
 To modify the Session's flush plan within a flush event, use the
 before_flush() session event.
 
 How to retrieve affected instances with their state (being inserted,
 updated, or deleted) that belong to a flush operation? for this case I
 need to validate each instance after they were inserted or before they
 were deleted from a persistence storage and adjust some rows from
 another table.

Within before_flush() you work with the session.new, session.dirty, and 
session.deleted collections, as well as with attributes.get_history() to look 
at individual attribute changes.   Any of the versioning examples on the wiki 
at http://www.sqlalchemy.org/trac/wiki/UsageRecipes illustrate these techniques.

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

from sqlalchemy import create_engine, event
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import sessionmaker, mapper
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=engine)


import collections
total_insert_calls = collections.defaultdict(int)
total_delete_calls = collections.defaultdict(int)

def model_after_insert(mapper, connection, target):
total_insert_calls[mapper.class_] += 1

def model_after_delete(mapper, connection, target):
total_delete_calls[mapper.class_] += 1

event.listen(mapper, 'after_insert', model_after_insert)
event.listen(mapper, 'after_delete', model_after_delete)

class Master(Base):
 __tablename__ = 'master'
 id = Column(Integer, primary_key=True)
 name = Column(String)
 total = Column(Integer)

 def __init__(self, name):
   self.name = name
   self.total = 0

class Detail(Base):
 __tablename__ = 'detail'
 id = Column(Integer, primary_key=True)
 master = Column(Integer, primary_key=True)
 name = Column(String)

 def __init__(self, id, master, name):
   self.id = id
   self.name = name
   self.master = master

klass = Master

Base.metadata.create_all(engine)
session = Session()

master = Master('hello world')
session.add(master)
session.commit()

dt_1 = Detail(1, 1, 'This is detail')
dt_2 = Detail(1, 2, 'This is detail')
session.add(dt_1)
session.add(dt_2)
session.commit()

assert total_insert_calls[Master] == 1
assert total_insert_calls[Detail] == 2
assert not total_delete_calls

master = session.query(Master).filter_by(id = 1).first()
print('total ', master.total)


Re: [sqlalchemy] Re: attempting to override __sa_instrumentation_manager__

2011-08-25 Thread Michael Bayer
yikes!  are my docs that bad ?  attribute events, right here:  
http://www.sqlalchemy.org/docs/06/orm/interfaces.html#attribute-events


On Aug 25, 2011, at 12:41 PM, Kent wrote:

 We are still running 0.6.4 so I think that was the only way to
 implement events (set/append/remove), correct?
 
 
 On Aug 25, 12:38 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 ho boy.  Why are you playing with instrumentation ?   That's a really 
 obscure feature we created literally for one product.   I'd love to blow it 
 away.   Anyway, if that's the error its giving you, then that's definitely 
 one of its limitations :).
 
 On Aug 25, 2011, at 11:10 AM, Kent wrote:
 
 
 
 
 
 
 
 Assume I have a class hierarchy:
 
 class Base(object):
  __sa_instrumentation_manager__ = AttrManager
 
 class Order(Base):
  __sa_instrumentation_manager__ = OrderAttrManager
 
 This causes TypeError: multiple instrumentation implementations
 specified in Order inheritance hierarchy:
 
 I don't understand why or how I can go about overriding the
 AttributeManager for a specific class.  I want 95% of the classes to
 use AttrManager, but I want a specific one for OrderAttrManager.
 
 What am I doing wrong?
 
 --
 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 
 athttp://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.



[sqlalchemy] foreign_keys changing cascade behavior for relationships? users going away.

2011-08-25 Thread Daniel Robbins
Hi there.

I have an application that has three different databases in MySQL (InnoDB).
They are separated into distinct databases because sometimes I need to
reload a database from scratch without impacting the other databases. For
this reason, there are no ForeignKey() relationships defined at table
creation time between these three databases, so I can wipe and reload an
individual database at will.

There are still relationships between the databases, from a SQLAlchemy
perspective. Because I don't use ForeignKey(), I need to specify
foreign_keys in my relationship, as follows:

'user' : relationship(User, foreign_keys=[User.__table__.c.email],
primaryjoin=cls.__table__.c.user_email == User.__table__.c.email),

When I have this relationship in my AllocatedHardware object, and I delete
an AllocatedHardware record, this has the unfortunate site-effect of
deleting the user account from the users table. :( When I leave the
foreign_keys parameter out, then SQLAlchemy can't determine the join
condition.

The behavior I want is for the AllocatedHardware record to go away when I
delete it, without impacting my user accounts.

Can this be achieved with tweaking the cascade behavior? It seems like an
unexpected side-effect that specifying foreign_keys will result in cascading
deletes in tables that do not have any db-level foreign key relationships.

Thanks and Regards,

Daniel

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



Re: [sqlalchemy] ORM Event

2011-08-25 Thread Jaimy Azle
On Thursday, August 25, 2011, 11:44:48 PM, Michael Bayer wrote:

 I would ask why you believe that's true - from what I can tell,
 you're using the Session.add() or something as a means to test that
 the event is triggered, which as I mentioned will have side effects.

 A proper test as below indicates two inserts for Detail, one insert
 for Master, as expected:

Ups i believe it was my bad, combining two cases in one test.
Anyway, I got it, thanks.. :)

-- 
Salam,

-Jaimy Azle

“+1 for stating fact: Perl is dead. Please 
don't bring it back” – Matt Joiner
“-1 for spreading FUD about perl. It's 
absolutely not dead.” – Daenyth
“+1 + -1 = 0, then, is perl a zombie?” – joaquin
-- http://stackoverflow.com/questions/3384385/python-3-2-gil-good-bad

-- 
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: attempting to override __sa_instrumentation_manager__

2011-08-25 Thread Kent
Obviously not; thanks for pointing me, sorry I couldn't find it
myself.

On Aug 25, 12:45 pm, Michael Bayer mike...@zzzcomputing.com wrote:
 yikes!  are my docs that bad ?      attribute events, right here:  
 http://www.sqlalchemy.org/docs/06/orm/interfaces.html#attribute-events

 On Aug 25, 2011, at 12:41 PM, Kent wrote:







  We are still running 0.6.4 so I think that was the only way to
  implement events (set/append/remove), correct?

  On Aug 25, 12:38 pm, Michael Bayer mike...@zzzcomputing.com wrote:
  ho boy.  Why are you playing with instrumentation ?   That's a really 
  obscure feature we created literally for one product.   I'd love to blow 
  it away.   Anyway, if that's the error its giving you, then that's 
  definitely one of its limitations :).

  On Aug 25, 2011, at 11:10 AM, Kent wrote:

  Assume I have a class hierarchy:

  class Base(object):
   __sa_instrumentation_manager__ = AttrManager

  class Order(Base):
   __sa_instrumentation_manager__ = OrderAttrManager

  This causes TypeError: multiple instrumentation implementations
  specified in Order inheritance hierarchy:

  I don't understand why or how I can go about overriding the
  AttributeManager for a specific class.  I want 95% of the classes to
  use AttrManager, but I want a specific one for OrderAttrManager.

  What am I doing wrong?

  --
  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 
  athttp://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 
  athttp://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.



[sqlalchemy] Cascade in many-to-many relationships: when orphans are not orphans

2011-08-25 Thread Benjamin Sims
Thanks for the help with my query the other day - as ever response was swift
and bang on.

I'm now trying to set up another m:n relationship in ORM correctly.
Pseudocode:

parentA.children.append(child1)
parentA.children.append(child2)

parentB.children.append(child2)

session.delete(parentA)

At this stage, I would like child1 to be deleted and child2 to survive.

However, if I use (cascade = all), then both children will be deleted when
ParentA is. I hoped that delete-orphan would be applicable in this
situation, but that requires that single-parent be True, which I understand
it cannot for a true many-to-many.

So I guess what I am asking is - is it possible for child objects which have
still have remaining parents to survive, while deleting those with no
parents left?

Thanks,
Ben

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



Re: [sqlalchemy] Cascade in many-to-many relationships: when orphans are not orphans

2011-08-25 Thread Michael Bayer

On Aug 25, 2011, at 7:06 PM, Benjamin Sims wrote:

 Thanks for the help with my query the other day - as ever response was swift 
 and bang on.
 
 I'm now trying to set up another m:n relationship in ORM correctly. 
 Pseudocode:
 
 parentA.children.append(child1)
 parentA.children.append(child2)
 
 parentB.children.append(child2)
 
 session.delete(parentA)
 
 At this stage, I would like child1 to be deleted and child2 to survive. 
 
 However, if I use (cascade = all), then both children will be deleted when 
 ParentA is. I hoped that delete-orphan would be applicable in this situation, 
 but that requires that single-parent be True, which I understand it cannot 
 for a true many-to-many.
 
 So I guess what I am asking is - is it possible for child objects which have 
 still have remaining parents to survive, while deleting those with no parents 
 left?

That's not something supported by delete, delete-orphan cascade and its why 
the single_parent=True flag is required - so that users aren't misled into 
thinking it can work that way.

You'd need to roll this using attribute events most likely.   The potential 
expense is that you may have to emit SQL in order to load the full collection 
of parents for each child in order to detect the orphan condition (which is 
why SQLA doesn't support this automatically, it would be extremely inefficient 
implemented generically).


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