0
# Container Management
1
2
Core container functionality for creating, configuring, and managing dependency injection containers. Containers handle dependency creation, caching, lifecycle management, and scope transitions.
3
4
## Capabilities
5
6
### Container Creation
7
8
Factory functions for creating dependency injection containers with provider registration and configuration options.
9
10
```python { .api }
11
def make_container(
12
*providers: BaseProvider,
13
scopes: type[BaseScope] = Scope,
14
context: dict[Any, Any] | None = None,
15
lock_factory: Callable[[], Any] = Lock,
16
skip_validation: bool = False,
17
start_scope: BaseScope | None = None,
18
validation_settings: ValidationSettings = DEFAULT_VALIDATION
19
) -> Container:
20
"""
21
Create a synchronous dependency injection container.
22
23
Parameters:
24
- providers: Provider instances containing dependency definitions
25
- scopes: Scope hierarchy class (default: Scope)
26
- context: Initial context values (deprecated)
27
- lock_factory: Factory for creating thread locks
28
- skip_validation: Skip dependency graph validation
29
- start_scope: Initial scope to enter
30
- validation_settings: Validation configuration
31
32
Returns:
33
Container instance ready for dependency resolution
34
"""
35
36
def make_async_container(
37
*providers: BaseProvider,
38
scopes: type[BaseScope] = Scope,
39
context: dict[Any, Any] | None = None,
40
lock_factory: Callable[[], AbstractAsyncContextManager[Any]] | None = Lock,
41
skip_validation: bool = False,
42
start_scope: BaseScope | None = None,
43
validation_settings: ValidationSettings = DEFAULT_VALIDATION
44
) -> AsyncContainer:
45
"""
46
Create an asynchronous dependency injection container.
47
48
Parameters:
49
- providers: Provider instances containing dependency definitions
50
- scopes: Scope hierarchy class (default: Scope)
51
- context: Initial context values (deprecated)
52
- lock_factory: Factory for creating async context manager locks
53
- skip_validation: Skip dependency graph validation
54
- start_scope: Initial scope to enter
55
- validation_settings: Validation configuration
56
57
Returns:
58
AsyncContainer instance ready for async dependency resolution
59
"""
60
```
61
62
**Usage Example:**
63
64
```python
65
from dishka import make_container, Provider, Scope
66
67
# Create providers
68
provider1 = Provider()
69
provider2 = Provider(scope=Scope.APP)
70
71
# Create container
72
container = make_container(
73
provider1,
74
provider2,
75
skip_validation=False,
76
start_scope=Scope.APP
77
)
78
```
79
80
### Synchronous Container
81
82
Main container class for synchronous dependency injection with lifecycle management and scope handling.
83
84
```python { .api }
85
class Container:
86
def __init__(
87
self,
88
registry: Registry,
89
*child_registries: Registry,
90
parent_container: Container | None = None,
91
context: dict[Any, Any] | None = None,
92
lock_factory: Callable[[], Any] = Lock,
93
close_parent: bool = False
94
): ...
95
96
def get(self, dependency_type: type[T], component: str = DEFAULT_COMPONENT) -> T:
97
"""
98
Resolve a dependency by type and optional component.
99
100
Parameters:
101
- dependency_type: The type to resolve
102
- component: Component identifier for isolation (default: "")
103
104
Returns:
105
Instance of the requested type
106
107
Raises:
108
- NoFactoryError: No factory found for the dependency
109
- DependencyCycleError: Circular dependency detected
110
"""
111
112
def __call__(
113
self,
114
context: dict[Any, Any] | None = None,
115
lock_factory: Callable[[], Any] | None = None,
116
scope: BaseScope | None = None
117
) -> ContextWrapper:
118
"""
119
Enter a child scope, returning a context manager.
120
121
Parameters:
122
- context: Additional context values (deprecated)
123
- lock_factory: Lock factory for the child container
124
- scope: Specific scope to enter (default: next in hierarchy)
125
126
Returns:
127
ContextWrapper that provides access to child container
128
"""
129
130
def close(self, exception: BaseException | None = None) -> None:
131
"""
132
Close the container and clean up resources.
133
134
Parameters:
135
- exception: Exception that caused the close (for cleanup context)
136
"""
137
138
@property
139
def scope(self) -> BaseScope:
140
"""Current scope of the container"""
141
142
@property
143
def context(self) -> MutableMapping[DependencyKey, Any]:
144
"""Context mapping (deprecated, use from_context instead)"""
145
```
146
147
**Usage Example:**
148
149
```python
150
# Get dependencies
151
client = container.get(SomeClient) # APP-scoped dependency
152
client2 = container.get(SomeClient) # Same instance
153
154
# Enter child scope
155
with container() as request_container:
156
service = request_container.get(Service) # REQUEST-scoped
157
service2 = request_container.get(Service) # Same instance in this scope
158
# Automatically closed when exiting context
159
160
# Clean up
161
container.close()
162
```
163
164
### Asynchronous Container
165
166
Asynchronous container class providing the same functionality as Container but with async/await support.
167
168
```python { .api }
169
class AsyncContainer:
170
def __init__(
171
self,
172
registry: Registry,
173
*child_registries: Registry,
174
parent_container: AsyncContainer | None = None,
175
context: dict[Any, Any] | None = None,
176
lock_factory: Callable[[], Any] = Lock,
177
close_parent: bool = False
178
): ...
179
180
async def get(self, dependency_type: type[T], component: str = DEFAULT_COMPONENT) -> T:
181
"""
182
Asynchronously resolve a dependency by type and optional component.
183
184
Parameters:
185
- dependency_type: The type to resolve
186
- component: Component identifier for isolation (default: "")
187
188
Returns:
189
Instance of the requested type
190
191
Raises:
192
- NoFactoryError: No factory found for the dependency
193
- DependencyCycleError: Circular dependency detected
194
"""
195
196
def __call__(
197
self,
198
context: dict[Any, Any] | None = None,
199
lock_factory: Callable[[], Any] | None = None,
200
scope: BaseScope | None = None
201
) -> AsyncContextWrapper:
202
"""
203
Enter a child scope, returning an async context manager.
204
205
Parameters:
206
- context: Additional context values (deprecated)
207
- lock_factory: Lock factory for the child container
208
- scope: Specific scope to enter (default: next in hierarchy)
209
210
Returns:
211
AsyncContextWrapper that provides access to child container
212
"""
213
214
async def close(self, exception: BaseException | None = None) -> None:
215
"""
216
Asynchronously close the container and clean up resources.
217
218
Parameters:
219
- exception: Exception that caused the close (for cleanup context)
220
"""
221
222
@property
223
def scope(self) -> BaseScope:
224
"""Current scope of the container"""
225
226
@property
227
def context(self) -> MutableMapping[DependencyKey, Any]:
228
"""Context mapping (deprecated, use from_context instead)"""
229
```
230
231
**Usage Example:**
232
233
```python
234
import asyncio
235
from dishka import make_async_container
236
237
async def main():
238
# Create async container
239
container = make_async_container(provider)
240
241
# Get dependencies
242
client = await container.get(SomeClient)
243
244
# Enter child scope
245
async with container() as request_container:
246
service = await request_container.get(Service)
247
# Use service
248
# Automatically closed when exiting context
249
250
# Clean up
251
await container.close()
252
253
asyncio.run(main())
254
```
255
256
### Context Management
257
258
The context wrapper classes manage scope transitions and provide clean resource management.
259
260
```python { .api }
261
class ContextWrapper:
262
"""Context manager for synchronous container scope transitions"""
263
def __enter__(self) -> Container: ...
264
def __exit__(self, exc_type, exc_val, exc_tb) -> None: ...
265
266
class AsyncContextWrapper:
267
"""Async context manager for asynchronous container scope transitions"""
268
async def __aenter__(self) -> AsyncContainer: ...
269
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None: ...
270
```
271
272
### Error Handling
273
274
Common exceptions that may be raised during container operations:
275
276
```python { .api }
277
class DishkaError(Exception):
278
"""Base exception class for all Dishka-related errors"""
279
280
class NoFactoryError(DishkaError):
281
"""
282
Raised when no factory is found for a requested dependency.
283
284
Attributes:
285
- requested: DependencyKey for the missing dependency
286
- path: Sequence of dependencies that led to this request
287
"""
288
289
class CycleDependenciesError(DishkaError):
290
"""
291
Raised when a circular dependency is detected in the dependency graph.
292
293
Attributes:
294
- path: Sequence of dependencies forming the cycle
295
"""
296
297
class NoChildScopesError(DishkaError):
298
"""Raised when trying to enter a child scope but none are available"""
299
300
class ChildScopeNotFoundError(DishkaError):
301
"""
302
Raised when a specific child scope cannot be found.
303
304
Attributes:
305
- child_scope: The scope that was requested
306
- current_scope: The current container scope
307
"""
308
309
class ExitError(DishkaError):
310
"""Raised when an error occurs during container exit/cleanup"""
311
312
class NoContextValueError(DishkaError):
313
"""Raised when a required context value is not found"""
314
315
class InvalidGraphError(DishkaError):
316
"""Raised when the dependency graph is invalid or malformed"""
317
318
class UnsupportedFactoryError(DishkaError):
319
"""Raised when a factory type is not supported by the container"""
320
```