0
# Persistence
1
2
Protocols and handlers for persisting generated data to databases and storage systems. Polyfactory provides both synchronous and asynchronous persistence integration, allowing generated instances to be automatically saved during creation.
3
4
## Capabilities
5
6
### Synchronous Persistence Protocol
7
8
Protocol definition for synchronous persistence handlers that can save single instances or batches of instances.
9
10
```python { .api }
11
class SyncPersistenceProtocol:
12
"""
13
Protocol for synchronous persistence operations.
14
15
Implement this protocol to create custom persistence handlers
16
that can save generated instances to databases or storage systems.
17
"""
18
19
def save(self, data: T) -> T:
20
"""
21
Save a single instance synchronously.
22
23
Parameters:
24
- data: Instance to persist
25
26
Returns:
27
The persisted instance (may include database-generated fields)
28
"""
29
30
def save_many(self, data: list[T]) -> list[T]:
31
"""
32
Save multiple instances synchronously.
33
34
Parameters:
35
- data: List of instances to persist
36
37
Returns:
38
List of persisted instances
39
"""
40
```
41
42
### Asynchronous Persistence Protocol
43
44
Protocol definition for asynchronous persistence handlers supporting non-blocking database operations.
45
46
```python { .api }
47
class AsyncPersistenceProtocol:
48
"""
49
Protocol for asynchronous persistence operations.
50
51
Implement this protocol to create custom async persistence handlers
52
for non-blocking database operations.
53
"""
54
55
async def save(self, data: T) -> T:
56
"""
57
Save a single instance asynchronously.
58
59
Parameters:
60
- data: Instance to persist
61
62
Returns:
63
The persisted instance (may include database-generated fields)
64
"""
65
66
async def save_many(self, data: list[T]) -> list[T]:
67
"""
68
Save multiple instances asynchronously.
69
70
Parameters:
71
- data: List of instances to persist
72
73
Returns:
74
List of persisted instances
75
"""
76
```
77
78
### SQLAlchemy Synchronous Persistence
79
80
Built-in persistence handler for SQLAlchemy models with synchronous database operations.
81
82
```python { .api }
83
class SQLASyncPersistence:
84
"""
85
Synchronous persistence handler for SQLAlchemy models.
86
87
Handles database sessions, commits, and relationship management
88
for SQLAlchemy ORM models.
89
"""
90
91
def __init__(self, session: Session) -> None:
92
"""
93
Initialize with SQLAlchemy session.
94
95
Parameters:
96
- session: SQLAlchemy session for database operations
97
"""
98
99
def save(self, data: T) -> T:
100
"""Save single SQLAlchemy model instance."""
101
102
def save_many(self, data: list[T]) -> list[T]:
103
"""Save multiple SQLAlchemy model instances."""
104
```
105
106
**Usage Example:**
107
```python
108
from sqlalchemy import create_engine, Column, Integer, String
109
from sqlalchemy.orm import sessionmaker, declarative_base
110
from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory, SQLASyncPersistence
111
112
Base = declarative_base()
113
114
class User(Base):
115
__tablename__ = 'users'
116
id = Column(Integer, primary_key=True)
117
name = Column(String(50))
118
email = Column(String(100))
119
120
# Setup database
121
engine = create_engine('sqlite:///test.db')
122
Base.metadata.create_all(engine)
123
Session = sessionmaker(bind=engine)
124
session = Session()
125
126
class UserFactory(SQLAlchemyFactory[User]):
127
__model__ = User
128
__sync_persistence__ = SQLASyncPersistence(session)
129
130
# Create and persist user
131
user = UserFactory.create_sync() # Automatically saved to database
132
users = UserFactory.create_batch_sync(5) # 5 users saved to database
133
```
134
135
### SQLAlchemy Asynchronous Persistence
136
137
Built-in persistence handler for SQLAlchemy models with asynchronous database operations.
138
139
```python { .api }
140
class SQLAASyncPersistence:
141
"""
142
Asynchronous persistence handler for SQLAlchemy models.
143
144
Handles async database sessions, commits, and relationship management
145
for SQLAlchemy ORM models with asyncio support.
146
"""
147
148
def __init__(self, session: AsyncSession) -> None:
149
"""
150
Initialize with SQLAlchemy async session.
151
152
Parameters:
153
- session: SQLAlchemy async session for database operations
154
"""
155
156
async def save(self, data: T) -> T:
157
"""Save single SQLAlchemy model instance asynchronously."""
158
159
async def save_many(self, data: list[T]) -> list[T]:
160
"""Save multiple SQLAlchemy model instances asynchronously."""
161
```
162
163
**Usage Example:**
164
```python
165
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
166
from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory, SQLAASyncPersistence
167
168
# Setup async database
169
engine = create_async_engine('sqlite+aiosqlite:///async_test.db')
170
AsyncSessionLocal = async_sessionmaker(engine)
171
172
class UserFactory(SQLAlchemyFactory[User]):
173
__model__ = User
174
175
@classmethod
176
async def setup_persistence(cls):
177
session = AsyncSessionLocal()
178
cls.__async_persistence__ = SQLAASyncPersistence(session)
179
180
# Usage
181
await UserFactory.setup_persistence()
182
user = await UserFactory.create_async() # Async save to database
183
users = await UserFactory.create_batch_async(5) # Async batch save
184
```
185
186
### Custom Persistence Implementation
187
188
Create custom persistence handlers by implementing the persistence protocols.
189
190
**Synchronous Custom Persistence:**
191
```python
192
from polyfactory import SyncPersistenceProtocol
193
import json
194
195
class JSONFilePersistence(SyncPersistenceProtocol[dict]):
196
def __init__(self, file_path: str):
197
self.file_path = file_path
198
self.data = []
199
200
def save(self, data: dict) -> dict:
201
# Add ID if not present
202
if 'id' not in data:
203
data['id'] = len(self.data) + 1
204
205
self.data.append(data)
206
207
# Save to file
208
with open(self.file_path, 'w') as f:
209
json.dump(self.data, f, indent=2)
210
211
return data
212
213
def save_many(self, data: list[dict]) -> list[dict]:
214
return [self.save(item) for item in data]
215
216
# Usage with TypedDict factory
217
from typing import TypedDict
218
from polyfactory.factories import TypedDictFactory
219
220
class UserDict(TypedDict):
221
name: str
222
email: str
223
224
class UserDictFactory(TypedDictFactory[UserDict]):
225
__model__ = UserDict
226
__sync_persistence__ = JSONFilePersistence('users.json')
227
228
# Creates user and saves to JSON file
229
user = UserDictFactory.create_sync()
230
```
231
232
**Asynchronous Custom Persistence:**
233
```python
234
import asyncio
235
import aiofiles
236
import json
237
238
class AsyncJSONFilePersistence(AsyncPersistenceProtocol[dict]):
239
def __init__(self, file_path: str):
240
self.file_path = file_path
241
self.data = []
242
243
async def save(self, data: dict) -> dict:
244
if 'id' not in data:
245
data['id'] = len(self.data) + 1
246
247
self.data.append(data)
248
249
# Async file write
250
async with aiofiles.open(self.file_path, 'w') as f:
251
await f.write(json.dumps(self.data, indent=2))
252
253
return data
254
255
async def save_many(self, data: list[dict]) -> list[dict]:
256
results = []
257
for item in data:
258
result = await self.save(item)
259
results.append(result)
260
return results
261
262
class UserDictFactory(TypedDictFactory[UserDict]):
263
__model__ = UserDict
264
__async_persistence__ = AsyncJSONFilePersistence('async_users.json')
265
266
# Async usage
267
user = await UserDictFactory.create_async()
268
```
269
270
### Factory Persistence Configuration
271
272
Configure persistence at the factory class level using class attributes:
273
274
```python { .api }
275
class ExampleFactory(BaseFactory[Model]):
276
__model__ = Model
277
__sync_persistence__: SyncPersistenceProtocol | None = None
278
__async_persistence__: AsyncPersistenceProtocol | None = None
279
```
280
281
**Configuration Examples:**
282
```python
283
# Single persistence handler
284
class UserFactory(DataclassFactory[User]):
285
__model__ = User
286
__sync_persistence__ = CustomSyncHandler()
287
288
# Both sync and async handlers
289
class FlexibleFactory(DataclassFactory[User]):
290
__model__ = User
291
__sync_persistence__ = CustomSyncHandler()
292
__async_persistence__ = CustomAsyncHandler()
293
294
# Runtime configuration
295
UserFactory.__sync_persistence__ = new_handler
296
```
297
298
### Error Handling
299
300
Persistence operations can raise configuration exceptions when handlers are not properly configured:
301
302
```python
303
from polyfactory.exceptions import ConfigurationException
304
305
try:
306
# This will raise ConfigurationException if no sync persistence configured
307
user = UserFactory.create_sync()
308
except ConfigurationException as e:
309
print(f"Persistence not configured: {e}")
310
311
try:
312
# This will raise ConfigurationException if no async persistence configured
313
user = await UserFactory.create_async()
314
except ConfigurationException as e:
315
print(f"Async persistence not configured: {e}")
316
```