-
-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add sqlalchemy factory (initial) * feat: Add Sqlalchemy factory (#342) * feat: Add SQLAlchemyFactory table column parsing * docs: Add SQLAlchemy reference * docs: amend link * doc: amend link * Revert type updates * feat: add SQLAlchemy relationship configuration * feat: improve mapping for SQLAlchemy ARRAY * feat: SQLAlchemy test hints for 3.8 * feat: SQLAlchemy test hints for 3.8 * feat: SQLAlchemy test hints for 3.8 * feat: SQLAlchemy factory hints for 3.8 * feat: add extra attributes for SQLAlchemyFactory * feat: resolve SQLAlchemyFactory type issues * feat: fix rebase errors * feat: Add SQLA persistence handles, update class attributes * docs: Add SQLAFactory docs * test: add missing __init__ files, fix imports, fix rebase errors * docs: fix SQLA class ref --------- Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com>
- Loading branch information
Showing
16 changed files
with
806 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
23 changes: 23 additions & 0 deletions
23
docs/examples/library_factories/sqlalchemy_factory/test_example_1.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column | ||
|
||
from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory | ||
|
||
|
||
class Base(DeclarativeBase): | ||
... | ||
|
||
|
||
class Author(Base): | ||
__tablename__ = "authors" | ||
|
||
id: Mapped[int] = mapped_column(primary_key=True) | ||
name: Mapped[str] | ||
|
||
|
||
class AuthorFactory(SQLAlchemyFactory[Author]): | ||
__model__ = Author | ||
|
||
|
||
def test_sqla_factory() -> None: | ||
author = AuthorFactory.build() | ||
assert isinstance(author, Author) |
46 changes: 46 additions & 0 deletions
46
docs/examples/library_factories/sqlalchemy_factory/test_example_2.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
from typing import List | ||
|
||
from sqlalchemy import ForeignKey | ||
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship | ||
|
||
from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory | ||
|
||
|
||
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) | ||
|
||
|
||
class Book(Base): | ||
__tablename__ = "books" | ||
|
||
id: Mapped[int] = mapped_column(primary_key=True) | ||
author_id: Mapped[int] = mapped_column(ForeignKey(Author.id)) | ||
|
||
|
||
class AuthorFactory(SQLAlchemyFactory[Author]): | ||
__model__ = Author | ||
|
||
|
||
class AuthorFactoryWithRelationship(SQLAlchemyFactory[Author]): | ||
__model__ = Author | ||
__set_relationships__ = True | ||
|
||
|
||
def test_sqla_factory_without_relationship() -> None: | ||
author = AuthorFactory.build() | ||
assert author.books == [] | ||
|
||
|
||
def test_sqla_factory() -> None: | ||
author = AuthorFactoryWithRelationship.build() | ||
assert isinstance(author, Author) | ||
assert isinstance(author.books[0], Book) |
43 changes: 43 additions & 0 deletions
43
docs/examples/library_factories/sqlalchemy_factory/test_example_3.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
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 | ||
|
||
|
||
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) | ||
|
||
|
||
class Book(Base): | ||
__tablename__ = "books" | ||
|
||
id: Mapped[int] = mapped_column(primary_key=True) | ||
author_id: Mapped[int] = mapped_column(ForeignKey(Author.id)) | ||
|
||
|
||
class AuthorFactory(SQLAlchemyFactory[Author]): | ||
__model__ = Author | ||
__set_relationships__ = True | ||
|
||
|
||
def test_sqla_factory_persistence() -> None: | ||
engine = create_engine("sqlite:///:memory:") | ||
Base.metadata.create_all(engine) | ||
session = Session(engine) | ||
|
||
AuthorFactory.__session__ = session # Or using a callable that returns a session | ||
|
||
author = AuthorFactory.create_sync() | ||
assert author.id is not None | ||
assert author.id == author.books[0].author_id |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,3 +15,4 @@ factories | |
odmantic_odm_factory | ||
beanie_odm_factory | ||
attrs_factory | ||
sqlalchemy_factory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
sqlalchemy_factory | ||
================== | ||
|
||
.. automodule:: polyfactory.factories.sqlalchemy_factory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
SQLAlchemyFactory | ||
=================== | ||
|
||
Basic usage is like other factories | ||
|
||
.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_1.py | ||
:caption: Declaring a factory for a SQLAlchemy model | ||
:language: python | ||
|
||
Configurations | ||
------------------------------ | ||
|
||
By default, relationships will not be set. This can be overridden via ``__set_relationships__``. | ||
|
||
.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_2.py | ||
:caption: Setting relationships | ||
:language: python | ||
|
||
.. note:: | ||
In general, foreign keys are not automatically generated by ``.build``. This can be resolved by setting the fields yourself and/or using ``create_sync``/ ``create_async`` so models can be added to a SQLA session so these are set. | ||
|
||
|
||
Persistence | ||
------------------------------ | ||
|
||
A handler is provided to allow persistence. This can be used by setting ``__session__`` attribute on a factory. | ||
|
||
.. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_3.py | ||
:caption: Using persistence | ||
:language: python | ||
|
||
By default, this will add generated models to the session and then commit. This can be customised further by setting ``__sync_persistence__``. | ||
|
||
Similarly for ``__async_session__`` and ``create_async``. | ||
|
||
|
||
API reference | ||
------------------------------ | ||
Full API docs are available :class:`here <polyfactory.factories.sqlalchemy_factory.SQLAlchemyFactory>`. |
Oops, something went wrong.