Saturday, 18 November 2023

SQL Alchemy v2 is after_transaction_end needed for nested session

In Setting Up a SQLAlchemy and Pytest Based Test Suite (published May 2022 with SQLAlchemy v1), for the transactional testing, it uses the below code snippet. Note I cleaned it up a bit for this post:

# conftest.py

import pytest

# Import a session factory in our app code. Possibly created using
# `sessionmaker()`
from myapp.db import Session

@pytest.fixture(autouse=True)
def session(connection):
    transaction = connection.begin()
    session = Session(bind=connection)
    session.begin_nested()

    @event.listens_for(session, "after_transaction_end")
    def restart_savepoint(db_session, ended_transaction):
        if ended_transaction.nested and not ended_transaction._parent.nested:
            session.expire_all()
            session.begin_nested()

    yield session

    Session.remove()
    transaction.rollback()

I am now working with SQLAlchemy v2 in November 2023, and have three questions around the restart_savepoint inner function:

  • Can you explain the ended_transaction.nested and not ended_transaction._parent.nested logic?
  • Is this restart_savepoint behavior still necessary with SQL Alchemy v2?
  • Is the Session(bind=connection) still necessary with SQL Alchemy v2?

I am thinking the below is equally viable:

@pytest.fixture(autouse=True)
def session(connection):
    with Session() as session, session.begin(nested=True):
        yield session


from SQL Alchemy v2 is after_transaction_end needed for nested session

No comments:

Post a Comment