Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add recursion guard #468

Merged
merged 13 commits into from
Jan 16, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from typing import List

from sqlalchemy import ForeignKey, create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column, relationship

from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory, T


class Base(DeclarativeBase):
...


class Author(Base):
__tablename__ = "authors"

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

books: Mapped[List["Book"]] = relationship(
"Book",
uselist=True,
back_populates="author",
)


class Book(Base):
__tablename__ = "books"

id: Mapped[int] = mapped_column(primary_key=True)
author_id: Mapped[int] = mapped_column(ForeignKey(Author.id), nullable=False)
author: Mapped[Author] = relationship(
"Author",
uselist=False,
back_populates="books",
)


class BaseFactory(SQLAlchemyFactory[T]):
__is_base_factory__ = True
__set_relationships__ = True
__randomize_collection_length__ = True
__min_collection_length__ = 3


def test_custom_sqla_factory() -> None:
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
session = Session(engine)

BaseFactory.__session__ = session # Or using a callable that returns a session

author = BaseFactory.create_factory(Author).create_sync()
assert author.id is not None
assert author.id == author.books[0].author_id

book = BaseFactory.create_factory(Book).create_sync()
assert book.id is not None
assert book.author.books == [book]

BaseFactory._base_factories.remove(BaseFactory) # noqa: SLF001
guacs marked this conversation as resolved.
Show resolved Hide resolved
10 changes: 10 additions & 0 deletions docs/usage/library_factories/sqlalchemy_factory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ By default, this will add generated models to the session and then commit. This
Similarly for ``__async_session__`` and ``create_async``.


Adding global overrides
------------------------------

By combining the above and using other settings, a global base factory can be set up for other factories.

.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_4.py
:caption: Using persistence
:language: python


API reference
------------------------------
Full API docs are available :class:`here <polyfactory.factories.sqlalchemy_factory.SQLAlchemyFactory>`.
Loading
Loading