litestar-org / litestar-org/polyfactory
Enhancement: Add an optional database parameter to BaseFactory.create_{a}sync
- Dominant language
- Python
- Stars
- 1.5k
- Forks
- 120
- PR merge metrics
- No merged PRs in 30d
Description
### Summary
Both `create_sync` and `create_async` currently accept kwargs but forward them directly to the `build` or `batch` methods.
They also both call `_get_sync_persistence` which allows to dynamically create a __{a}sync_persistence__ instance but is not receiving any parameters.
My idea is to allow for a single `database: Any | None` parameter to be passed from the `create_{a}sync` methods to `_get_async_persistence` and add an `__init__` to both `{As,S}yncPersistenceProtocol`.
We could then use it at runtime in tests to specify a particular database in which to create the object.
See the next example which might be clearer.
The database used here does not exists but looks like Mongo which is what I used in the real project.
```py
# persistence.py
@runtime_checkable
class SyncPersistenceProtocol(Protocol[T]):
database: Any | None
def __init__(self, database: Any | None = None):
self.database = database
...
```
```py
# factories.base.py
class BaseFactory(ABC, Generic[T]):
@classmethod
def _get_sync_persistence(cls, database: Any | None = None) -> SyncPersistenceProtocol[T]:
...
if cls.__sync_persistence__:
return cls.__sync_persistence__(database) if callable(cls.__sync_persistence__) else cls.__sync_persistence__
...
...
@classmethod
def create_sync(cls, database: Any | None = None, **kwargs: Any) -> T:
...
return cls._get_sync_persistence(database).save(data=cls.build(**kwargs))
```
```py
# tests.factories.py
class SyncPersistenceHandler(SyncPersistenceProtocol[Person]):
def save(self, person: Person) -> Person:
self.database.person_collection.insert_one(person.model_dump())
return person
def save_many(self, data: list[Person]) -> list[Person]:
self.database.person_collection.insert_many([person.model_dump() for person in data])
return data
class PersonFactory(ModelFactory[Person]):
__sync_persistence__ = SyncPersistenceHandler
...
```
```
# tests.test_person.py
@fixure
def database(settings):
client = Client(settings)
return client.database
def test_create(database):
person = PersonFactory.create_sync(database=database, age=42)
assert database.person_collection.exists(id=person.id)
```
### Basic Example
_No response_
### Drawbacks and Impact
_No response_
### Unresolved questions
_No response_
Contributor guide
Research direction
Start with persistence.py and factories.base.py, focusing on the SyncPersistenceProtocol, AsyncPersistenceProtocol, and BaseFactory create_sync/create_async paths. Review tests.test_person.py for the persistence-handler usage, then add coverage showing a supplied database reaches both sync and async persistence instances and that object creation still succeeds.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- database, testing
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100