Re: [sqlalchemy] Cascade_backrefs Behavior Deprecated For Removal In 2.0

2022-04-05 Thread Mike Bayer


On Tue, Apr 5, 2022, at 3:09 PM, Thorsten von Stein wrote:
> Thanks, Mike. Yes, I am using the scoped session. Am I understanding you 
> correctly that, when using the scoped session, there is no penalty when 
> calling the sessionmaker repeatedly, but that you still prefer passing around 
> sessions as parameters for transparency reasons?

the scoped_session doesn't call "sessionmaker" repeatedly; it calls it once per 
thread, until you say scoped_session.remove().  it's a thread local registry 
for a persistent Session object.

I do prefer passing sessions around as global registries tend to be forgotten 
and contribute to the "implicitness" of a program.


> 
> On Tuesday, April 5, 2022 at 11:58:33 AM UTC-7 Mike Bayer wrote:
>> 
>> 
>> On Tue, Apr 5, 2022, at 1:02 PM, Thorsten von Stein wrote:
>>> I'm currently trying to get my applications ready for SQLAlchemy 2.0. A 
>>> change that has forces code changes in numerous places is the removal of 
>>> the automatic addition of new instances to the session upon establishing a 
>>> relationship with an object already in the session. In the explanation of 
>>> the change this is described "not generally a desirable behavior". However, 
>>> it is a behavior on which I currently completely rely for persisting new 
>>> instances. Since, in my system, new instances are always connected to a 
>>> parent object, I never had to add any object explicitly to a session, and 
>>> so session objects are currently basically absent from the application code.
>>> 
>>> Here are my questions:
>>> - Will there be a way to turn back on this behavior in 2.0? I would be 
>>> thrilled if there was, but I fear the answer is negative.
>> 
>> the whole behavior is done using event handlers which is public API.  so you 
>> could set up the attributeevents.append() [1] and attributeevents.set() [2] 
>> event handlers to add the local side to the session:
>> 
>> from sqlalchemy import Column
>> from sqlalchemy import create_engine
>> from sqlalchemy import event
>> from sqlalchemy import ForeignKey
>> from sqlalchemy import Integer
>> from sqlalchemy import String
>> from sqlalchemy.orm import declarative_base
>> from sqlalchemy.orm import object_session
>> from sqlalchemy.orm import relationship
>> from sqlalchemy.orm import Session
>> from sqlalchemy.orm import configure_mappers
>> 
>> Base = declarative_base()
>> 
>> 
>> class A(Base):
>> __tablename__ = "a"
>> 
>> id = Column(Integer, primary_key=True)
>> data = Column(String)
>> bs = relationship("B", backref="a")
>> 
>> 
>> class B(Base):
>> __tablename__ = "b"
>> id = Column(Integer, primary_key=True)
>> a_id = Column(ForeignKey("a.id"))
>> data = Column(String)
>> 
>> configure_mappers()
>> 
>> @event.listens_for(B.a, "set")
>> def set_(target, newvalue, oldvalue, initiator):
>> sess = object_session(newvalue)
>> if target not in sess:
>> sess.add(target)
>> 
>> 
>> e = create_engine("sqlite://", echo=True)
>> Base.metadata.create_all(e)
>> 
>> s = Session(e)
>> 
>> a1 = A()
>> s.add(a1)
>> s.commit()
>> 
>> 
>> b1 = B(a=a1)
>> assert b1 in s.new
>> 
>> 
>> 
>> [1] 
>> https://docs.sqlalchemy.org/en/14/orm/events.html?highlight=attributeevents#sqlalchemy.orm.AttributeEvents.append
>> [2] 
>> https://docs.sqlalchemy.org/en/14/orm/events.html?highlight=attributeevents#sqlalchemy.orm.AttributeEvents.set
>> 
>> there's an example of how to add new attribute events automatically at 
>> https://docs.sqlalchemy.org/en/14/_modules/examples/custom_attributes/listen_for_events.html
>>  , though you'd want to alter it to test each new attribute for being an 
>> "object" based attribute.
>> 
>> 
>>> - How would you recommend dealing with the situation: Either passing 
>>> sessions as additional parameters to any function or method that creates 
>>> new objects, or, calling the session maker within each such function? In 
>>> particular, is there any particular downside to the latter?
>> 
>> 
>> For a given chain of methods that are working in the same transaction I 
>> would have a Session that's passed around to all of them, likely via some 
>> contextual object, so that they can all ensure the object is added to the 
>> persistence context as needed.  calling a sessionmaker inside of each 
>> method implies you're building a new session/transaction inside of each 
>> method which means each method would need to commit its own transaction, did 
>> you mean the scoped_session()?  scoped_session is an option as well if you 
>> are already using that, though I favor an explicit session/context being 
>> passed around as this allows functions and methods to explicitly state that 
>> they need to take place within this particular kind of context.
>> 
>> 
>>> 
>>> 
>>> 
>>> 
>>> 
>>> -- 
>>> SQLAlchemy - 
>>> The Python SQL Toolkit and Object Relational Mapper
>>>  
>>> http://www.sqlalchemy.org/
>>>  
>>> To post example code, please provide an MCVE: Minimal, Complete, and 
>>> Verifiable 

Re: [sqlalchemy] Cascade_backrefs Behavior Deprecated For Removal In 2.0

2022-04-05 Thread Thorsten von Stein
Thanks, Mike. Yes, I am using the scoped session. Am I understanding you 
correctly that, when using the scoped session, there is no penalty when 
calling the sessionmaker repeatedly, but that you still prefer passing 
around sessions as parameters for transparency reasons?

On Tuesday, April 5, 2022 at 11:58:33 AM UTC-7 Mike Bayer wrote:

>
>
> On Tue, Apr 5, 2022, at 1:02 PM, Thorsten von Stein wrote:
>
> I'm currently trying to get my applications ready for SQLAlchemy 2.0. A 
> change that has forces code changes in numerous places is the removal of 
> the automatic addition of new instances to the session upon establishing a 
> relationship with an object already in the session. In the explanation of 
> the change this is described "not generally a desirable behavior". However, 
> it is a behavior on which I currently completely rely for persisting new 
> instances. Since, in my system, new instances are always connected to a 
> parent object, I never had to add any object explicitly to a session, and 
> so session objects are currently basically absent from the application code.
>
> Here are my questions:
> - Will there be a way to turn back on this behavior in 2.0? I would be 
> thrilled if there was, but I fear the answer is negative.
>
>
> the whole behavior is done using event handlers which is public API.  so 
> you could set up the attributeevents.append() [1] and attributeevents.set() 
> [2] event handlers to add the local side to the session:
>
> from sqlalchemy import Column
> from sqlalchemy import create_engine
> from sqlalchemy import event
> from sqlalchemy import ForeignKey
> from sqlalchemy import Integer
> from sqlalchemy import String
> from sqlalchemy.orm import declarative_base
> from sqlalchemy.orm import object_session
> from sqlalchemy.orm import relationship
> from sqlalchemy.orm import Session
> from sqlalchemy.orm import configure_mappers
>
> Base = declarative_base()
>
>
> class A(Base):
> __tablename__ = "a"
>
> id = Column(Integer, primary_key=True)
> data = Column(String)
> bs = relationship("B", backref="a")
>
>
> class B(Base):
> __tablename__ = "b"
> id = Column(Integer, primary_key=True)
> a_id = Column(ForeignKey("a.id"))
> data = Column(String)
>
> configure_mappers()
>
> @event.listens_for(B.a, "set")
> def set_(target, newvalue, oldvalue, initiator):
> sess = object_session(newvalue)
> if target not in sess:
> sess.add(target)
>
>
> e = create_engine("sqlite://", echo=True)
> Base.metadata.create_all(e)
>
> s = Session(e)
>
> a1 = A()
> s.add(a1)
> s.commit()
>
>
> b1 = B(a=a1)
> assert b1 in s.new
>
>
>
> [1] 
> https://docs.sqlalchemy.org/en/14/orm/events.html?highlight=attributeevents#sqlalchemy.orm.AttributeEvents.append
> [2] 
> https://docs.sqlalchemy.org/en/14/orm/events.html?highlight=attributeevents#sqlalchemy.orm.AttributeEvents.set
>
> there's an example of how to add new attribute events automatically at 
> https://docs.sqlalchemy.org/en/14/_modules/examples/custom_attributes/listen_for_events.html
>  
> , though you'd want to alter it to test each new attribute for being an 
> "object" based attribute.
>
>
> - How would you recommend dealing with the situation: Either passing 
> sessions as additional parameters to any function or method that creates 
> new objects, or, calling the session maker within each such function? In 
> particular, is there any particular downside to the latter?
>
>
>
> For a given chain of methods that are working in the same transaction I 
> would have a Session that's passed around to all of them, likely via some 
> contextual object, so that they can all ensure the object is added to the 
> persistence context as needed.  calling a sessionmaker inside of each 
> method implies you're building a new session/transaction inside of each 
> method which means each method would need to commit its own transaction, 
> did you mean the scoped_session()?  scoped_session is an option as well if 
> you are already using that, though I favor an explicit session/context 
> being passed around as this allows functions and methods to explicitly 
> state that they need to take place within this particular kind of context.
>
>
>
>
>
>
> -- 
> SQLAlchemy - 
> The Python SQL Toolkit and Object Relational Mapper
>  
> http://www.sqlalchemy.org/
>  
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> description.
> --- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/792f9a59-2a9f-4dfb-82f0-82ef7f5e4328n%40googlegroups.com
>  
> 

Re: [sqlalchemy] Cascade_backrefs Behavior Deprecated For Removal In 2.0

2022-04-05 Thread Mike Bayer


On Tue, Apr 5, 2022, at 1:02 PM, Thorsten von Stein wrote:
> I'm currently trying to get my applications ready for SQLAlchemy 2.0. A 
> change that has forces code changes in numerous places is the removal of the 
> automatic addition of new instances to the session upon establishing a 
> relationship with an object already in the session. In the explanation of the 
> change this is described "not generally a desirable behavior". However, it is 
> a behavior on which I currently completely rely for persisting new instances. 
> Since, in my system, new instances are always connected to a parent object, I 
> never had to add any object explicitly to a session, and so session objects 
> are currently basically absent from the application code.
> 
> Here are my questions:
> - Will there be a way to turn back on this behavior in 2.0? I would be 
> thrilled if there was, but I fear the answer is negative.

the whole behavior is done using event handlers which is public API.  so you 
could set up the attributeevents.append() [1] and attributeevents.set() [2] 
event handlers to add the local side to the session:

from sqlalchemy import Column
from sqlalchemy import create_engine
from sqlalchemy import event
from sqlalchemy import ForeignKey
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import object_session
from sqlalchemy.orm import relationship
from sqlalchemy.orm import Session
from sqlalchemy.orm import configure_mappers

Base = declarative_base()


class A(Base):
__tablename__ = "a"

id = Column(Integer, primary_key=True)
data = Column(String)
bs = relationship("B", backref="a")


class B(Base):
__tablename__ = "b"
id = Column(Integer, primary_key=True)
a_id = Column(ForeignKey("a.id"))
data = Column(String)

configure_mappers()

@event.listens_for(B.a, "set")
def set_(target, newvalue, oldvalue, initiator):
sess = object_session(newvalue)
if target not in sess:
sess.add(target)


e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)

s = Session(e)

a1 = A()
s.add(a1)
s.commit()


b1 = B(a=a1)
assert b1 in s.new



[1] 
https://docs.sqlalchemy.org/en/14/orm/events.html?highlight=attributeevents#sqlalchemy.orm.AttributeEvents.append
[2] 
https://docs.sqlalchemy.org/en/14/orm/events.html?highlight=attributeevents#sqlalchemy.orm.AttributeEvents.set

there's an example of how to add new attribute events automatically at 
https://docs.sqlalchemy.org/en/14/_modules/examples/custom_attributes/listen_for_events.html
 , though you'd want to alter it to test each new attribute for being an 
"object" based attribute.


> - How would you recommend dealing with the situation: Either passing sessions 
> as additional parameters to any function or method that creates new objects, 
> or, calling the session maker within each such function? In particular, is 
> there any particular downside to the latter?


For a given chain of methods that are working in the same transaction I would 
have a Session that's passed around to all of them, likely via some contextual 
object, so that they can all ensure the object is added to the persistence 
context as needed.  calling a sessionmaker inside of each method implies 
you're building a new session/transaction inside of each method which means 
each method would need to commit its own transaction, did you mean the 
scoped_session()?  scoped_session is an option as well if you are already using 
that, though I favor an explicit session/context being passed around as this 
allows functions and methods to explicitly state that they need to take place 
within this particular kind of context.


> 
> 
> 
> 
> 
> -- 
> SQLAlchemy - 
> The Python SQL Toolkit and Object Relational Mapper
>  
> http://www.sqlalchemy.org/
>  
> To post example code, please provide an MCVE: Minimal, Complete, and 
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> description.
> --- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/sqlalchemy/792f9a59-2a9f-4dfb-82f0-82ef7f5e4328n%40googlegroups.com
>  
> .

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to