or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

containers.mdindex.mdproviders.mdresources.mdschema.mdwiring.md

resources.mddocs/

0

# Resource Management

1

2

Resource management provides base classes and providers for handling resource lifecycles with automatic initialization and cleanup. Resources represent objects that require explicit setup and teardown, such as database connections, file handles, or network connections.

3

4

## Capabilities

5

6

### Base Resource Classes

7

8

Abstract base classes that define the resource interface for synchronous and asynchronous resources.

9

10

```python { .api }

11

class Resource:

12

"""Abstract synchronous resource with initialization and cleanup."""

13

def __init__(self, *args, **kwargs): ...

14

15

def init(self, *args, **kwargs):

16

"""

17

Initialize the resource.

18

19

Parameters:

20

- *args: Positional arguments for initialization

21

- **kwargs: Keyword arguments for initialization

22

23

Returns:

24

The initialized resource object

25

"""

26

27

def shutdown(self, resource):

28

"""

29

Shutdown and cleanup the resource.

30

31

Parameters:

32

- resource: The resource object to cleanup

33

"""

34

35

def __enter__(self):

36

"""Context manager entry."""

37

38

def __exit__(self, *exc_info):

39

"""Context manager exit with cleanup."""

40

41

class AsyncResource:

42

"""Abstract asynchronous resource with async initialization and cleanup."""

43

def __init__(self, *args, **kwargs): ...

44

45

async def init(self, *args, **kwargs):

46

"""

47

Asynchronously initialize the resource.

48

49

Parameters:

50

- *args: Positional arguments for initialization

51

- **kwargs: Keyword arguments for initialization

52

53

Returns:

54

The initialized resource object

55

"""

56

57

async def shutdown(self, resource):

58

"""

59

Asynchronously shutdown and cleanup the resource.

60

61

Parameters:

62

- resource: The resource object to cleanup

63

"""

64

65

async def __aenter__(self):

66

"""Async context manager entry."""

67

68

async def __aexit__(self, *exc_info):

69

"""Async context manager exit with cleanup."""

70

```

71

72

### Synchronous Resource Implementation

73

74

Implementation pattern for synchronous resources that require initialization and cleanup.

75

76

Usage example:

77

78

```python

79

from dependency_injector.resources import Resource

80

81

class DatabaseResource(Resource):

82

def init(self, connection_string, pool_size=10):

83

"""Initialize database connection pool."""

84

print(f"Connecting to database: {connection_string}")

85

connection_pool = create_connection_pool(

86

connection_string,

87

pool_size=pool_size

88

)

89

print(f"Created connection pool with {pool_size} connections")

90

return connection_pool

91

92

def shutdown(self, connection_pool):

93

"""Close all database connections."""

94

print("Closing database connection pool")

95

connection_pool.close_all()

96

print("Database connections closed")

97

98

# Usage with provider

99

from dependency_injector import providers

100

101

database = providers.Resource(

102

DatabaseResource,

103

connection_string="postgresql://localhost/mydb",

104

pool_size=20

105

)

106

107

# Initialize resource

108

db_pool = database() # Calls init() method

109

# Use database pool

110

result = db_pool.execute("SELECT * FROM users")

111

# Cleanup is handled automatically or manually

112

database.shutdown() # Calls shutdown() method

113

```

114

115

### Asynchronous Resource Implementation

116

117

Implementation pattern for asynchronous resources with async/await support.

118

119

Usage example:

120

121

```python

122

from dependency_injector.resources import AsyncResource

123

import asyncio

124

import aioredis

125

126

class RedisResource(AsyncResource):

127

async def init(self, host="localhost", port=6379, db=0):

128

"""Initialize async Redis connection."""

129

print(f"Connecting to Redis: {host}:{port}/{db}")

130

redis_client = await aioredis.from_url(

131

f"redis://{host}:{port}/{db}"

132

)

133

print("Redis connection established")

134

return redis_client

135

136

async def shutdown(self, redis_client):

137

"""Close Redis connection."""

138

print("Closing Redis connection")

139

await redis_client.close()

140

print("Redis connection closed")

141

142

# Usage with provider

143

redis = providers.Resource(

144

RedisResource,

145

host="localhost",

146

port=6379,

147

db=0

148

)

149

150

# Async usage

151

async def main():

152

redis_client = await redis() # Calls init() method

153

await redis_client.set("key", "value")

154

value = await redis_client.get("key")

155

print(f"Retrieved value: {value}")

156

await redis.shutdown() # Calls shutdown() method

157

158

asyncio.run(main())

159

```

160

161

### File Resource Implementation

162

163

Example of file resource management with proper cleanup.

164

165

```python

166

from dependency_injector.resources import Resource

167

168

class FileResource(Resource):

169

def init(self, filepath, mode="r", encoding="utf-8"):

170

"""Open file handle."""

171

print(f"Opening file: {filepath} (mode: {mode})")

172

file_handle = open(filepath, mode, encoding=encoding)

173

return file_handle

174

175

def shutdown(self, file_handle):

176

"""Close file handle."""

177

print(f"Closing file: {file_handle.name}")

178

file_handle.close()

179

180

# Usage

181

config_file = providers.Resource(

182

FileResource,

183

filepath="config.json",

184

mode="r"

185

)

186

187

# Use as context manager

188

with config_file() as f:

189

config_data = f.read()

190

# File is automatically closed

191

```

192

193

### HTTP Client Resource Implementation

194

195

Example of HTTP client resource with connection pooling.

196

197

```python

198

from dependency_injector.resources import AsyncResource

199

import aiohttp

200

201

class HttpClientResource(AsyncResource):

202

async def init(self, base_url, timeout=30, connector_limit=100):

203

"""Initialize HTTP client session."""

204

print(f"Creating HTTP client for: {base_url}")

205

timeout_config = aiohttp.ClientTimeout(total=timeout)

206

connector = aiohttp.TCPConnector(limit=connector_limit)

207

208

session = aiohttp.ClientSession(

209

base_url=base_url,

210

timeout=timeout_config,

211

connector=connector

212

)

213

print("HTTP client session created")

214

return session

215

216

async def shutdown(self, session):

217

"""Close HTTP client session."""

218

print("Closing HTTP client session")

219

await session.close()

220

print("HTTP client session closed")

221

222

# Usage

223

api_client = providers.Resource(

224

HttpClientResource,

225

base_url="https://api.example.com",

226

timeout=60

227

)

228

229

async def make_request():

230

client = await api_client()

231

async with client.get("/users") as response:

232

data = await response.json()

233

return data

234

```

235

236

### Resource Provider Integration

237

238

Resources integrate with the dependency injection system through resource providers.

239

240

```python

241

from dependency_injector import containers, providers

242

from dependency_injector.resources import Resource

243

244

class DatabaseResource(Resource):

245

def init(self, connection_string):

246

return create_database_connection(connection_string)

247

248

def shutdown(self, connection):

249

connection.close()

250

251

class Container(containers.DeclarativeContainer):

252

config = providers.Configuration()

253

254

# Resource provider

255

database = providers.Resource(

256

DatabaseResource,

257

connection_string=config.database.url

258

)

259

260

# Other providers can use the resource

261

user_repository = providers.Factory(

262

UserRepository,

263

database=database # Automatically initialized resource

264

)

265

266

# Container automatically manages resource lifecycle

267

container = Container()

268

container.config.from_dict({

269

"database": {"url": "postgresql://localhost/mydb"}

270

})

271

272

# Initialize all resources

273

await container.init_resources()

274

275

# Use services that depend on resources

276

user_repo = container.user_repository()

277

users = user_repo.get_all_users()

278

279

# Shutdown all resources

280

await container.shutdown_resources()

281

```

282

283

### Resource Context Managers

284

285

Resources support context manager protocols for automatic cleanup.

286

287

```python

288

# Synchronous context manager

289

class DatabaseResource(Resource):

290

def init(self, connection_string):

291

return create_connection(connection_string)

292

293

def shutdown(self, connection):

294

connection.close()

295

296

# Usage as context manager

297

database = providers.Resource(DatabaseResource, "postgresql://localhost/db")

298

299

with database() as db_connection:

300

# Use database connection

301

result = db_connection.execute("SELECT * FROM users")

302

# Connection is automatically closed

303

304

# Asynchronous context manager

305

class AsyncDatabaseResource(AsyncResource):

306

async def init(self, connection_string):

307

return await create_async_connection(connection_string)

308

309

async def shutdown(self, connection):

310

await connection.close()

311

312

# Usage as async context manager

313

async_database = providers.Resource(AsyncDatabaseResource, "postgresql://localhost/db")

314

315

async with async_database() as db_connection:

316

# Use async database connection

317

result = await db_connection.execute("SELECT * FROM users")

318

# Connection is automatically closed

319

```

320

321

### Resource Dependency Injection

322

323

Resources can be injected into functions and methods using dependency wiring.

324

325

```python

326

from dependency_injector.wiring import inject, Provide, Closing

327

328

@inject

329

def process_users(

330

database = Provide[Container.database],

331

cache = Provide[Container.redis],

332

# Resource cleanup markers

333

db_cleanup = Closing[Container.database],

334

cache_cleanup = Closing[Container.redis]

335

):

336

# Use resources

337

users = database.query("SELECT * FROM users")

338

cache.set("users", users)

339

340

# Resources will be automatically cleaned up

341

return users

342

343

# Wire container

344

container.wire(modules=[__name__])

345

```

346

347

### Resource Error Handling

348

349

Proper error handling in resource initialization and cleanup.

350

351

```python

352

from dependency_injector.resources import Resource

353

354

class RobustDatabaseResource(Resource):

355

def init(self, connection_string, max_retries=3):

356

"""Initialize with retry logic."""

357

for attempt in range(max_retries):

358

try:

359

print(f"Database connection attempt {attempt + 1}")

360

connection = create_connection(connection_string)

361

print("Database connection successful")

362

return connection

363

except ConnectionError as e:

364

print(f"Connection failed: {e}")

365

if attempt == max_retries - 1:

366

raise

367

time.sleep(2 ** attempt) # Exponential backoff

368

369

def shutdown(self, connection):

370

"""Shutdown with error handling."""

371

try:

372

if connection and not connection.is_closed():

373

connection.close()

374

print("Database connection closed")

375

except Exception as e:

376

print(f"Error closing database connection: {e}")

377

# Log error but don't raise to avoid masking original exceptions

378

```

379

380

### Resource Composition

381

382

Combining multiple resources into composite resources.

383

384

```python

385

class CompositeResource(Resource):

386

def init(self, db_config, redis_config):

387

"""Initialize multiple resources."""

388

database = DatabaseResource().init(**db_config)

389

redis = RedisResource().init(**redis_config)

390

391

return {

392

"database": database,

393

"redis": redis

394

}

395

396

def shutdown(self, resources):

397

"""Shutdown all resources."""

398

if "database" in resources:

399

DatabaseResource().shutdown(resources["database"])

400

if "redis" in resources:

401

RedisResource().shutdown(resources["redis"])

402

403

# Usage

404

composite = providers.Resource(

405

CompositeResource,

406

db_config={"connection_string": "postgresql://localhost/db"},

407

redis_config={"host": "localhost", "port": 6379}

408

)

409

```