Skip to content

Bug: SQLAlchemyFactory async persistence does not close session #866

Description

@Nnonexistent

Description

When using SQLAlchemyFactory async creation with an async session provider, polyfactory creates an AsyncSession but never closes it in SQLAASyncPersistence. The async persistence implementation commits and refreshes objects, but there is no session close/cleanup step.

I think there should be either some kind of session management mechanism to span single session across multiple factories calls or at least a call of .close() for a used session.

URL to code causing the issue

No response

MCVE

from unittest.mock import patch
import asyncio

from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


class Base(DeclarativeBase):
    pass



class Model(Base):
    __tablename__ = 'model'

    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str]

engine = create_async_engine('sqlite+aiosqlite:///:memory:')
session_maker = async_sessionmaker(bind=engine)

class ModelFactory(SQLAlchemyFactory[Model]):
    __model__ = Model
    __async_session__ = session_maker


@patch.object(AsyncSession, 'close', autospec=True)
async def main(mock) -> None:
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

    await ModelFactory.create_async(name='test')
    print(mock.call_count)  # prints 0, expected 1


if __name__ == '__main__':
    asyncio.run(main())

Steps to reproduce

1. Define a `SQLAlchemyFactory` subclass with async_session set to an `async_sessionmaker`.
2. Call `.create_async` or `.create_batch_async`.
3. Observe that polyfactory-created sessions are not explicitly closed in the async persistence implementation.

Screenshots

"In the format of: ![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)"

Logs

The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <aiosqlite.core.Connection object at 0x7f59272ed160>>, which will be terminated.  Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle.
<sys>:0: SAWarning: The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection <aiosqlite.core.Connection object at 0x7f59272ed160>>, which will be terminated.  Please ensure that SQLAlchemy pooled connections are returned to the pool explicitly, either by calling ``close()`` or by using appropriate context managers to manage their lifecycle.

Release Version

2.22.2

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions