or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

customization.mdfactory-operations.mdfield-configuration.mdindex.mdpersistence.mdspecialized-factories.md

persistence.mddocs/

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

```