pico-ioc 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pico_ioc-0.3.1/PKG-INFO +239 -0
- pico_ioc-0.3.1/README.md +216 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/src/pico_ioc/__init__.py +63 -121
- pico_ioc-0.3.1/src/pico_ioc/_version.py +1 -0
- pico_ioc-0.3.1/src/pico_ioc.egg-info/PKG-INFO +239 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/tests/test_pico_ioc.py +11 -61
- pico_ioc-0.3.0/PKG-INFO +0 -228
- pico_ioc-0.3.0/README.md +0 -205
- pico_ioc-0.3.0/src/pico_ioc/_version.py +0 -1
- pico_ioc-0.3.0/src/pico_ioc.egg-info/PKG-INFO +0 -228
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/.github/workflows/ci.yml +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/.github/workflows/publish-to-pypi.yml +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/Dockerfile.test +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/Makefile +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/pyproject.toml +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/setup.cfg +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/src/pico_ioc.egg-info/SOURCES.txt +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/src/pico_ioc.egg-info/dependency_links.txt +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/src/pico_ioc.egg-info/top_level.txt +0 -0
- {pico_ioc-0.3.0 → pico_ioc-0.3.1}/tox.ini +0 -0
pico_ioc-0.3.1/PKG-INFO
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pico-ioc
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: A minimalist, zero-dependency Inversion of Control (IoC) container for Python.
|
|
5
|
+
Author-email: David Perez Cabrera <dperezcabrera@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/dperezcabrera/pico-ioc
|
|
7
|
+
Project-URL: Repository, https://github.com/dperezcabrera/pico-ioc
|
|
8
|
+
Project-URL: Issue Tracker, https://github.com/dperezcabrera/pico-ioc/issues
|
|
9
|
+
Keywords: ioc,di,dependency injection,inversion of control,decorator
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# 📦 Pico-IoC: A Minimalist IoC Container for Python
|
|
25
|
+
|
|
26
|
+
[](https://pypi.org/project/pico-ioc/)
|
|
27
|
+
[](https://opensource.org/licenses/MIT)
|
|
28
|
+

|
|
29
|
+
|
|
30
|
+
**Pico-IoC** is a tiny, zero-dependency, decorator-based Inversion of Control container for Python.
|
|
31
|
+
Build loosely-coupled, testable apps without manual wiring. Inspired by the Spring ecosystem.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## ✨ Key Features
|
|
36
|
+
|
|
37
|
+
* **Zero dependencies** — pure Python.
|
|
38
|
+
* **Decorator API** — `@component`, `@factory_component`, `@provides`.
|
|
39
|
+
* **Auto discovery** — scans a package and registers components.
|
|
40
|
+
* **Eager by default, fail-fast** — non-lazy bindings are instantiated immediately after `init()`. Missing deps fail startup.
|
|
41
|
+
* **Opt-in lazy** — set `lazy=True` to defer creation (wrapped in `ComponentProxy`).
|
|
42
|
+
* **Factories** — encapsulate complex creation logic.
|
|
43
|
+
* **Smart resolution** — by **parameter name**, then **type annotation**, then **MRO fallback**, then **string(name)**.
|
|
44
|
+
* **Re-entrancy guard** — prevents `get()` during scanning.
|
|
45
|
+
* **Auto-exclude caller** — `init()` skips the calling module to avoid double scanning.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 📦 Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install pico-ioc
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🚀 Quick Start
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from pico_ioc import component, init
|
|
61
|
+
|
|
62
|
+
@component
|
|
63
|
+
class AppConfig:
|
|
64
|
+
def get_db_url(self):
|
|
65
|
+
return "postgresql://user:pass@host/db"
|
|
66
|
+
|
|
67
|
+
@component
|
|
68
|
+
class DatabaseService:
|
|
69
|
+
def __init__(self, config: AppConfig):
|
|
70
|
+
self._cs = config.get_db_url()
|
|
71
|
+
def get_data(self):
|
|
72
|
+
return f"Data from {self._cs}"
|
|
73
|
+
|
|
74
|
+
container = init(__name__) # blueprint runs here (eager + fail-fast)
|
|
75
|
+
db = container.get(DatabaseService)
|
|
76
|
+
print(db.get_data())
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🧩 Custom Component Keys
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from pico_ioc import component, init
|
|
85
|
+
|
|
86
|
+
@component(name="config") # custom key
|
|
87
|
+
class AppConfig:
|
|
88
|
+
db_url = "postgresql://user:pass@localhost/db"
|
|
89
|
+
|
|
90
|
+
@component
|
|
91
|
+
class Repository:
|
|
92
|
+
def __init__(self, config: "config"): # resolve by NAME
|
|
93
|
+
self.url = config.db_url
|
|
94
|
+
|
|
95
|
+
container = init(__name__)
|
|
96
|
+
print(container.get("config").db_url)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 🏭 Factories and `@provides`
|
|
102
|
+
|
|
103
|
+
* Default is **eager** (`lazy=False`). Eager bindings are constructed at the end of `init()`.
|
|
104
|
+
* Use `lazy=True` for on-first-use creation via `ComponentProxy`.
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from pico_ioc import factory_component, provides, init
|
|
108
|
+
|
|
109
|
+
COUNTER = {"value": 0}
|
|
110
|
+
|
|
111
|
+
@factory_component
|
|
112
|
+
class ServicesFactory:
|
|
113
|
+
@provides(key="heavy_service", lazy=True)
|
|
114
|
+
def heavy(self):
|
|
115
|
+
COUNTER["value"] += 1
|
|
116
|
+
return {"payload": "hello"}
|
|
117
|
+
|
|
118
|
+
container = init(__name__)
|
|
119
|
+
svc = container.get("heavy_service") # not created yet
|
|
120
|
+
print(COUNTER["value"]) # 0
|
|
121
|
+
print(svc["payload"]) # triggers creation
|
|
122
|
+
print(COUNTER["value"]) # 1
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 🧠 Dependency Resolution Order
|
|
128
|
+
|
|
129
|
+
1. parameter **name**
|
|
130
|
+
2. exact **type annotation**
|
|
131
|
+
3. **MRO fallback** (walk base classes)
|
|
132
|
+
4. `str(name)`
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## ⚡ Eager vs. Lazy (Blueprint Behavior)
|
|
137
|
+
|
|
138
|
+
At the end of `init()`, Pico-IoC performs a **blueprint**:
|
|
139
|
+
|
|
140
|
+
- **Eager** (`lazy=False`, default): instantiated immediately; failures stop startup.
|
|
141
|
+
- **Lazy** (`lazy=True`): returns a `ComponentProxy`; instantiated on first real use.
|
|
142
|
+
|
|
143
|
+
**Lifecycle:**
|
|
144
|
+
|
|
145
|
+
┌───────────────────────┐
|
|
146
|
+
│ init() │
|
|
147
|
+
└───────────────────────┘
|
|
148
|
+
│
|
|
149
|
+
▼
|
|
150
|
+
┌───────────────────────┐
|
|
151
|
+
│ Scan & bind deps │
|
|
152
|
+
└───────────────────────┘
|
|
153
|
+
│
|
|
154
|
+
▼
|
|
155
|
+
┌─────────────────────────────┐
|
|
156
|
+
│ Blueprint instantiates all │
|
|
157
|
+
│ non-lazy (eager) beans │
|
|
158
|
+
└─────────────────────────────┘
|
|
159
|
+
│
|
|
160
|
+
┌───────────────────────┐
|
|
161
|
+
│ Container ready │
|
|
162
|
+
└───────────────────────┘
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
**Best practice:** keep eager+fail-fast for production parity with Spring; use lazy only for heavy/optional deps or to support negative tests.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 🔄 Migration Guide (v0.2.1 → v0.3.0)
|
|
170
|
+
|
|
171
|
+
* **Defaults changed:** `@component` and `@provides` now default to `lazy=False` (eager).
|
|
172
|
+
* **Proxy renamed:** `LazyProxy` → `ComponentProxy` (only relevant if referenced directly).
|
|
173
|
+
* **Tests/fixtures:** components intentionally missing deps should be marked `@component(lazy=True)` (to avoid failing `init()`), or excluded from the scan.
|
|
174
|
+
|
|
175
|
+
Example fix for an intentional failure case:
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
@component(lazy=True)
|
|
179
|
+
class MissingDep:
|
|
180
|
+
def __init__(self, missing):
|
|
181
|
+
self.missing = missing
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 🛠 API Reference
|
|
187
|
+
|
|
188
|
+
### `init(root, *, exclude=None, auto_exclude_caller=True) -> PicoContainer`
|
|
189
|
+
|
|
190
|
+
Scan and bind components in `root` (str module name or module).
|
|
191
|
+
Skips the calling module if `auto_exclude_caller=True`.
|
|
192
|
+
Runs blueprint (instantiate all `lazy=False` bindings).
|
|
193
|
+
|
|
194
|
+
### `@component(cls=None, *, name=None, lazy=False)`
|
|
195
|
+
|
|
196
|
+
Register a class as a component.
|
|
197
|
+
Use `name` for a custom key.
|
|
198
|
+
Set `lazy=True` to defer creation.
|
|
199
|
+
|
|
200
|
+
### `@factory_component`
|
|
201
|
+
|
|
202
|
+
Mark a class as a component factory (its methods can `@provides` bindings).
|
|
203
|
+
|
|
204
|
+
### `@provides(key, *, lazy=False)`
|
|
205
|
+
|
|
206
|
+
Declare that a factory method provides a component under `key`.
|
|
207
|
+
Set `lazy=True` for deferred creation (`ComponentProxy`).
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 🧪 Testing
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
pip install tox
|
|
215
|
+
tox -e py311
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Tip: for “missing dependency” tests, mark those components as `lazy=True` so `init()` remains fail-fast for real components while your test still asserts failure on resolution.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## ❓ FAQ
|
|
223
|
+
|
|
224
|
+
**Q: Can I make the container lenient at startup?**
|
|
225
|
+
A: By design it’s strict. Prefer `lazy=True` on specific bindings or exclude problem modules from the scan.
|
|
226
|
+
|
|
227
|
+
**Q: Thread safety?**
|
|
228
|
+
A: Container uses `ContextVar` to guard re-entrancy during scanning. Singletons are created once per container; typical usage is in single-threaded app startup, then read-mostly.
|
|
229
|
+
|
|
230
|
+
**Q: Frameworks?**
|
|
231
|
+
A: Framework-agnostic. Works with Flask, FastAPI, CLIs, scripts, etc.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 📜 License
|
|
236
|
+
|
|
237
|
+
MIT — see [LICENSE](https://opensource.org/licenses/MIT)
|
|
238
|
+
|
|
239
|
+
|
pico_ioc-0.3.1/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# 📦 Pico-IoC: A Minimalist IoC Container for Python
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/pico-ioc/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
**Pico-IoC** is a tiny, zero-dependency, decorator-based Inversion of Control container for Python.
|
|
8
|
+
Build loosely-coupled, testable apps without manual wiring. Inspired by the Spring ecosystem.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## ✨ Key Features
|
|
13
|
+
|
|
14
|
+
* **Zero dependencies** — pure Python.
|
|
15
|
+
* **Decorator API** — `@component`, `@factory_component`, `@provides`.
|
|
16
|
+
* **Auto discovery** — scans a package and registers components.
|
|
17
|
+
* **Eager by default, fail-fast** — non-lazy bindings are instantiated immediately after `init()`. Missing deps fail startup.
|
|
18
|
+
* **Opt-in lazy** — set `lazy=True` to defer creation (wrapped in `ComponentProxy`).
|
|
19
|
+
* **Factories** — encapsulate complex creation logic.
|
|
20
|
+
* **Smart resolution** — by **parameter name**, then **type annotation**, then **MRO fallback**, then **string(name)**.
|
|
21
|
+
* **Re-entrancy guard** — prevents `get()` during scanning.
|
|
22
|
+
* **Auto-exclude caller** — `init()` skips the calling module to avoid double scanning.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 📦 Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install pico-ioc
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🚀 Quick Start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from pico_ioc import component, init
|
|
38
|
+
|
|
39
|
+
@component
|
|
40
|
+
class AppConfig:
|
|
41
|
+
def get_db_url(self):
|
|
42
|
+
return "postgresql://user:pass@host/db"
|
|
43
|
+
|
|
44
|
+
@component
|
|
45
|
+
class DatabaseService:
|
|
46
|
+
def __init__(self, config: AppConfig):
|
|
47
|
+
self._cs = config.get_db_url()
|
|
48
|
+
def get_data(self):
|
|
49
|
+
return f"Data from {self._cs}"
|
|
50
|
+
|
|
51
|
+
container = init(__name__) # blueprint runs here (eager + fail-fast)
|
|
52
|
+
db = container.get(DatabaseService)
|
|
53
|
+
print(db.get_data())
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 🧩 Custom Component Keys
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from pico_ioc import component, init
|
|
62
|
+
|
|
63
|
+
@component(name="config") # custom key
|
|
64
|
+
class AppConfig:
|
|
65
|
+
db_url = "postgresql://user:pass@localhost/db"
|
|
66
|
+
|
|
67
|
+
@component
|
|
68
|
+
class Repository:
|
|
69
|
+
def __init__(self, config: "config"): # resolve by NAME
|
|
70
|
+
self.url = config.db_url
|
|
71
|
+
|
|
72
|
+
container = init(__name__)
|
|
73
|
+
print(container.get("config").db_url)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 🏭 Factories and `@provides`
|
|
79
|
+
|
|
80
|
+
* Default is **eager** (`lazy=False`). Eager bindings are constructed at the end of `init()`.
|
|
81
|
+
* Use `lazy=True` for on-first-use creation via `ComponentProxy`.
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from pico_ioc import factory_component, provides, init
|
|
85
|
+
|
|
86
|
+
COUNTER = {"value": 0}
|
|
87
|
+
|
|
88
|
+
@factory_component
|
|
89
|
+
class ServicesFactory:
|
|
90
|
+
@provides(key="heavy_service", lazy=True)
|
|
91
|
+
def heavy(self):
|
|
92
|
+
COUNTER["value"] += 1
|
|
93
|
+
return {"payload": "hello"}
|
|
94
|
+
|
|
95
|
+
container = init(__name__)
|
|
96
|
+
svc = container.get("heavy_service") # not created yet
|
|
97
|
+
print(COUNTER["value"]) # 0
|
|
98
|
+
print(svc["payload"]) # triggers creation
|
|
99
|
+
print(COUNTER["value"]) # 1
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 🧠 Dependency Resolution Order
|
|
105
|
+
|
|
106
|
+
1. parameter **name**
|
|
107
|
+
2. exact **type annotation**
|
|
108
|
+
3. **MRO fallback** (walk base classes)
|
|
109
|
+
4. `str(name)`
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## ⚡ Eager vs. Lazy (Blueprint Behavior)
|
|
114
|
+
|
|
115
|
+
At the end of `init()`, Pico-IoC performs a **blueprint**:
|
|
116
|
+
|
|
117
|
+
- **Eager** (`lazy=False`, default): instantiated immediately; failures stop startup.
|
|
118
|
+
- **Lazy** (`lazy=True`): returns a `ComponentProxy`; instantiated on first real use.
|
|
119
|
+
|
|
120
|
+
**Lifecycle:**
|
|
121
|
+
|
|
122
|
+
┌───────────────────────┐
|
|
123
|
+
│ init() │
|
|
124
|
+
└───────────────────────┘
|
|
125
|
+
│
|
|
126
|
+
▼
|
|
127
|
+
┌───────────────────────┐
|
|
128
|
+
│ Scan & bind deps │
|
|
129
|
+
└───────────────────────┘
|
|
130
|
+
│
|
|
131
|
+
▼
|
|
132
|
+
┌─────────────────────────────┐
|
|
133
|
+
│ Blueprint instantiates all │
|
|
134
|
+
│ non-lazy (eager) beans │
|
|
135
|
+
└─────────────────────────────┘
|
|
136
|
+
│
|
|
137
|
+
┌───────────────────────┐
|
|
138
|
+
│ Container ready │
|
|
139
|
+
└───────────────────────┘
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
**Best practice:** keep eager+fail-fast for production parity with Spring; use lazy only for heavy/optional deps or to support negative tests.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 🔄 Migration Guide (v0.2.1 → v0.3.0)
|
|
147
|
+
|
|
148
|
+
* **Defaults changed:** `@component` and `@provides` now default to `lazy=False` (eager).
|
|
149
|
+
* **Proxy renamed:** `LazyProxy` → `ComponentProxy` (only relevant if referenced directly).
|
|
150
|
+
* **Tests/fixtures:** components intentionally missing deps should be marked `@component(lazy=True)` (to avoid failing `init()`), or excluded from the scan.
|
|
151
|
+
|
|
152
|
+
Example fix for an intentional failure case:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
@component(lazy=True)
|
|
156
|
+
class MissingDep:
|
|
157
|
+
def __init__(self, missing):
|
|
158
|
+
self.missing = missing
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🛠 API Reference
|
|
164
|
+
|
|
165
|
+
### `init(root, *, exclude=None, auto_exclude_caller=True) -> PicoContainer`
|
|
166
|
+
|
|
167
|
+
Scan and bind components in `root` (str module name or module).
|
|
168
|
+
Skips the calling module if `auto_exclude_caller=True`.
|
|
169
|
+
Runs blueprint (instantiate all `lazy=False` bindings).
|
|
170
|
+
|
|
171
|
+
### `@component(cls=None, *, name=None, lazy=False)`
|
|
172
|
+
|
|
173
|
+
Register a class as a component.
|
|
174
|
+
Use `name` for a custom key.
|
|
175
|
+
Set `lazy=True` to defer creation.
|
|
176
|
+
|
|
177
|
+
### `@factory_component`
|
|
178
|
+
|
|
179
|
+
Mark a class as a component factory (its methods can `@provides` bindings).
|
|
180
|
+
|
|
181
|
+
### `@provides(key, *, lazy=False)`
|
|
182
|
+
|
|
183
|
+
Declare that a factory method provides a component under `key`.
|
|
184
|
+
Set `lazy=True` for deferred creation (`ComponentProxy`).
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 🧪 Testing
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pip install tox
|
|
192
|
+
tox -e py311
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Tip: for “missing dependency” tests, mark those components as `lazy=True` so `init()` remains fail-fast for real components while your test still asserts failure on resolution.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## ❓ FAQ
|
|
200
|
+
|
|
201
|
+
**Q: Can I make the container lenient at startup?**
|
|
202
|
+
A: By design it’s strict. Prefer `lazy=True` on specific bindings or exclude problem modules from the scan.
|
|
203
|
+
|
|
204
|
+
**Q: Thread safety?**
|
|
205
|
+
A: Container uses `ContextVar` to guard re-entrancy during scanning. Singletons are created once per container; typical usage is in single-threaded app startup, then read-mostly.
|
|
206
|
+
|
|
207
|
+
**Q: Frameworks?**
|
|
208
|
+
A: Framework-agnostic. Works with Flask, FastAPI, CLIs, scripts, etc.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 📜 License
|
|
213
|
+
|
|
214
|
+
MIT — see [LICENSE](https://opensource.org/licenses/MIT)
|
|
215
|
+
|
|
216
|
+
|