0
# Dependency Wiring
1
2
Dependency wiring enables automatic injection of dependencies into functions, methods, and class attributes. It provides decorators and markers for seamless integration with existing code without requiring manual dependency resolution.
3
4
## Capabilities
5
6
### Core Wiring Functions
7
8
Primary functions for setting up and managing dependency injection.
9
10
```python { .api }
11
def wire(container, modules=None, packages=None, from_package=None):
12
"""
13
Wire dependencies into modules and packages.
14
15
Parameters:
16
- container: Container with providers to inject
17
- modules: List of modules to wire
18
- packages: List of packages to wire
19
- from_package: Base package for relative imports
20
"""
21
22
def unwire(container=None, modules=None, packages=None, from_package=None):
23
"""
24
Remove dependency wiring from modules and packages.
25
26
Parameters:
27
- container: Container to unwire (optional)
28
- modules: List of modules to unwire
29
- packages: List of packages to unwire
30
- from_package: Base package for relative imports
31
"""
32
33
def inject(fn):
34
"""
35
Decorator for dependency injection into functions and methods.
36
37
Parameters:
38
- fn: Function or method to inject dependencies into
39
40
Returns:
41
Wrapped function with dependency injection
42
"""
43
```
44
45
Usage example:
46
47
```python
48
from dependency_injector import containers, providers
49
from dependency_injector.wiring import inject, Provide, wire
50
51
# Define container
52
class Container(containers.DeclarativeContainer):
53
user_service = providers.Factory(UserService)
54
55
# Wire container to current module
56
container = Container()
57
wire(container=container, modules=[__name__])
58
59
# Use dependency injection
60
@inject
61
def get_user(user_id: int, service: UserService = Provide[Container.user_service]):
62
return service.get_user(user_id)
63
```
64
65
### Dependency Markers
66
67
Markers specify what and how dependencies should be injected.
68
69
```python { .api }
70
class Provide:
71
"""Marker for dependency injection - provides instance."""
72
def __class_getitem__(cls, provider): ...
73
74
class Provider:
75
"""Marker for provider injection - provides provider object."""
76
def __class_getitem__(cls, provider): ...
77
78
class Closing:
79
"""Marker for resource closing injection."""
80
def __class_getitem__(cls, provider): ...
81
```
82
83
Usage examples:
84
85
```python
86
# Provide instance injection
87
@inject
88
def handler(service: UserService = Provide[Container.user_service]):
89
return service.process()
90
91
# Provider injection (get the provider, not the instance)
92
@inject
93
def factory_handler(service_factory = Provider[Container.user_service]):
94
# Create multiple instances
95
service1 = service_factory()
96
service2 = service_factory()
97
return [service1, service2]
98
99
# Resource closing injection (for cleanup)
100
@inject
101
def process_with_cleanup(
102
database = Provide[Container.database],
103
db_resource = Closing[Container.database]
104
):
105
# Use database
106
result = database.query("SELECT * FROM users")
107
# db_resource will be closed automatically
108
return result
109
```
110
111
### Type Annotations Support
112
113
Wiring supports Python type annotations for cleaner syntax.
114
115
```python
116
from typing import Annotated
117
from dependency_injector.wiring import Provide
118
119
@inject
120
def typed_handler(
121
service: Annotated[UserService, Provide[Container.user_service]]
122
):
123
return service.process()
124
125
# Alternative syntax
126
@inject
127
def alt_handler(service: UserService = Provide[Container.user_service]):
128
return service.process()
129
```
130
131
### Configuration Modifiers
132
133
Modifiers for configuration providers to transform values during injection.
134
135
```python { .api }
136
def as_int():
137
"""Return int type modifier."""
138
139
def as_float():
140
"""Return float type modifier."""
141
142
def as_(type_):
143
"""Return custom type modifier."""
144
145
def required():
146
"""Return required configuration modifier."""
147
148
def invariant(id):
149
"""Return invariant configuration modifier."""
150
151
def provided():
152
"""Return provided instance modifier."""
153
```
154
155
Usage example:
156
157
```python
158
from dependency_injector.wiring import as_int, required, provided
159
160
class Container(containers.DeclarativeContainer):
161
config = providers.Configuration()
162
database = providers.Singleton(Database, host=config.host)
163
164
@inject
165
def configure_app(
166
# Type conversion
167
port: int = Provide[Container.config.port, as_int()],
168
169
# Required configuration
170
secret_key: str = Provide[Container.config.secret_key, required()],
171
172
# Provided instance access
173
db_host: str = Provide[Container.database, provided().host]
174
):
175
app.config["PORT"] = port
176
app.config["SECRET_KEY"] = secret_key
177
app.config["DB_HOST"] = db_host
178
```
179
180
### Class Attribute Injection
181
182
Inject dependencies into class attributes using markers.
183
184
```python
185
from dependency_injector.wiring import Provide
186
187
class UserController:
188
# Class attribute injection
189
user_service = Provide[Container.user_service]
190
config = Provider[Container.config]
191
192
def get_user(self, user_id: int):
193
return self.user_service.get_user(user_id)
194
195
def get_config_value(self, key: str):
196
return self.config().get(key)
197
198
# Wire the container
199
wire(container=container, modules=[__name__])
200
201
# Use the controller
202
controller = UserController()
203
user = controller.get_user(123)
204
```
205
206
### Async Support
207
208
Wiring works seamlessly with async functions and coroutines.
209
210
```python
211
@inject
212
async def async_handler(
213
service: AsyncUserService = Provide[Container.async_user_service]
214
):
215
result = await service.process_async()
216
return result
217
218
@inject
219
async def async_generator(
220
data_service: DataService = Provide[Container.data_service]
221
):
222
async for item in data_service.stream_data():
223
yield item
224
```
225
226
### Framework Integration
227
228
Wiring integrates with popular Python web frameworks.
229
230
#### FastAPI Integration
231
232
```python
233
from fastapi import FastAPI, Depends
234
from dependency_injector.wiring import inject, Provide
235
236
app = FastAPI()
237
238
@app.get("/users/{user_id}")
239
@inject
240
def get_user(
241
user_id: int,
242
service: UserService = Depends(Provide[Container.user_service])
243
):
244
return service.get_user(user_id)
245
246
# Wire the container
247
container.wire(modules=[__name__])
248
```
249
250
#### Flask Integration
251
252
```python
253
from flask import Flask
254
from dependency_injector.wiring import inject, Provide
255
256
app = Flask(__name__)
257
258
@app.route("/users/<int:user_id>")
259
@inject
260
def get_user(user_id: int, service: UserService = Provide[Container.user_service]):
261
return service.get_user(user_id)
262
263
# Wire the container
264
container.wire(modules=[__name__])
265
```
266
267
#### Django Integration
268
269
```python
270
from django.http import JsonResponse
271
from dependency_injector.wiring import inject, Provide
272
273
@inject
274
def user_view(request, user_id, service: UserService = Provide[Container.user_service]):
275
user = service.get_user(user_id)
276
return JsonResponse({"user": user})
277
278
# Wire in Django app configuration
279
container.wire(modules=["myapp.views"])
280
```
281
282
### Auto-Loading
283
284
Automatic wiring of containers when modules are imported.
285
286
```python { .api }
287
class AutoLoader:
288
"""Auto-wiring module loader."""
289
def register_containers(self, *containers): ...
290
def unregister_containers(self, *containers): ...
291
def install(self): ...
292
def uninstall(self): ...
293
294
def register_loader_containers(*containers):
295
"""Register containers in auto-wiring module loader."""
296
297
def unregister_loader_containers(*containers):
298
"""Unregister containers from auto-wiring module loader."""
299
300
def install_loader():
301
"""Install auto-wiring module loader hook."""
302
303
def uninstall_loader():
304
"""Uninstall auto-wiring module loader hook."""
305
306
def is_loader_installed() -> bool:
307
"""Check if auto-wiring module loader hook is installed."""
308
```
309
310
Usage example:
311
312
```python
313
from dependency_injector.wiring import (
314
register_loader_containers,
315
install_loader
316
)
317
318
# Register containers for auto-loading
319
register_loader_containers(container)
320
install_loader()
321
322
# Now any imported module will be automatically wired
323
import myapp.handlers # Automatically wired
324
import myapp.services # Automatically wired
325
```
326
327
### Method Injection Patterns
328
329
Different patterns for injecting dependencies into methods.
330
331
#### Instance Method Injection
332
333
```python
334
class UserController:
335
@inject
336
def get_user(
337
self,
338
user_id: int,
339
service: UserService = Provide[Container.user_service]
340
):
341
return service.get_user(user_id)
342
```
343
344
#### Class Method Injection
345
346
```python
347
class UserService:
348
@classmethod
349
@inject
350
def create_instance(
351
cls,
352
database: Database = Provide[Container.database]
353
):
354
return cls(database)
355
```
356
357
#### Static Method Injection
358
359
```python
360
class UserUtils:
361
@staticmethod
362
@inject
363
def validate_user(
364
user_data: dict,
365
validator: UserValidator = Provide[Container.user_validator]
366
):
367
return validator.validate(user_data)
368
```
369
370
### Error Handling
371
372
Warning and error handling for wiring issues.
373
374
```python { .api }
375
class DIWiringWarning(RuntimeWarning):
376
"""Warning for dependency injection wiring issues."""
377
```
378
379
Common wiring issues and solutions:
380
381
```python
382
# Clear wiring cache if needed
383
from dependency_injector.wiring import clear_cache
384
clear_cache()
385
386
# Handle wiring warnings
387
import warnings
388
from dependency_injector.wiring import DIWiringWarning
389
390
warnings.filterwarnings("ignore", category=DIWiringWarning)
391
```
392
393
### Advanced Wiring Patterns
394
395
#### Conditional Injection
396
397
```python
398
@inject
399
def conditional_handler(
400
service: UserService = Provide[Container.user_service],
401
debug_mode: bool = Provide[Container.config.debug, as_(bool)]
402
):
403
if debug_mode:
404
print(f"Using service: {service}")
405
return service.process()
406
```
407
408
#### Multiple Provider Injection
409
410
```python
411
@inject
412
def multi_service_handler(
413
user_service: UserService = Provide[Container.user_service],
414
email_service: EmailService = Provide[Container.email_service],
415
logger: Logger = Provide[Container.logger]
416
):
417
user = user_service.get_user(123)
418
email_service.send_email(user.email, "Welcome!")
419
logger.info(f"Sent welcome email to {user.email}")
420
```
421
422
#### Resource Cleanup
423
424
```python
425
@inject
426
def process_with_resources(
427
database = Provide[Container.database],
428
redis = Provide[Container.redis],
429
db_cleanup = Closing[Container.database],
430
redis_cleanup = Closing[Container.redis]
431
):
432
# Use resources
433
data = database.query("SELECT * FROM users")
434
redis.set("cache_key", data)
435
436
# Resources will be automatically cleaned up
437
return data
438
```
439
440
## Auto-loading Functions
441
442
Advanced wiring functions for automatic container loading and management.
443
444
```python { .api }
445
def register_loader_containers(*containers):
446
"""Register containers for auto-loading."""
447
448
def unregister_loader_containers(*containers):
449
"""Unregister containers from auto-loading."""
450
451
def install_loader():
452
"""Install auto-wiring loader."""
453
454
def uninstall_loader():
455
"""Uninstall auto-wiring loader."""
456
457
def is_loader_installed() -> bool:
458
"""Check if auto-wiring loader is installed."""
459
460
def clear_cache():
461
"""Clear wiring caches."""
462
```