pico-ioc 0.5.2__py3-none-any.whl → 1.0.0__py3-none-any.whl

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.
@@ -1,278 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: pico-ioc
3
- Version: 0.5.2
4
- Summary: A minimalist, zero-dependency Inversion of Control (IoC) container for Python.
5
- Author-email: David Perez Cabrera <dperezcabrera@gmail.com>
6
- License: MIT License
7
-
8
- Copyright (c) 2025 David Pérez Cabrera
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
-
28
- Project-URL: Homepage, https://github.com/dperezcabrera/pico-ioc
29
- Project-URL: Repository, https://github.com/dperezcabrera/pico-ioc
30
- Project-URL: Issue Tracker, https://github.com/dperezcabrera/pico-ioc/issues
31
- Keywords: ioc,di,dependency injection,inversion of control,decorator
32
- Classifier: Development Status :: 4 - Beta
33
- Classifier: Programming Language :: Python :: 3
34
- Classifier: Programming Language :: Python :: 3 :: Only
35
- Classifier: Programming Language :: Python :: 3.8
36
- Classifier: Programming Language :: Python :: 3.9
37
- Classifier: Programming Language :: Python :: 3.10
38
- Classifier: Programming Language :: Python :: 3.11
39
- Classifier: Programming Language :: Python :: 3.12
40
- Classifier: Programming Language :: Python :: 3.13
41
- Classifier: License :: OSI Approved :: MIT License
42
- Classifier: Operating System :: OS Independent
43
- Requires-Python: >=3.8
44
- Description-Content-Type: text/markdown
45
- License-File: LICENSE
46
- Dynamic: license-file
47
-
48
- # 📦 Pico-IoC: A Minimalist IoC Container for Python
49
-
50
- [![PyPI](https://img.shields.io/pypi/v/pico-ioc.svg)](https://pypi.org/project/pico-ioc/)
51
- [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
52
- ![CI (tox matrix)](https://github.com/dperezcabrera/pico-ioc/actions/workflows/ci.yml/badge.svg)
53
- [![codecov](https://codecov.io/gh/dperezcabrera/pico-ioc/branch/main/graph/badge.svg)](https://codecov.io/gh/dperezcabrera/pico-ioc)
54
- [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-ioc&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-ioc)
55
- [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-ioc&metric=duplicated_lines_density)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-ioc)
56
- [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=dperezcabrera_pico-ioc&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=dperezcabrera_pico-ioc)
57
-
58
- **Pico-IoC** is a tiny, zero-dependency, decorator-based Inversion of Control container for Python.
59
- Build loosely-coupled, testable apps without manual wiring. Inspired by the Spring ecosystem.
60
-
61
- ---
62
-
63
- ## ✨ Key Features
64
-
65
- * **Zero dependencies** — pure Python.
66
- * **Decorator API** — `@component`, `@factory_component`, `@provides`.
67
- * **Auto discovery** — scans a package and registers components.
68
- * **Eager by default, fail-fast** — non-lazy bindings are instantiated immediately after `init()`. Missing deps fail startup.
69
- * **Opt-in lazy** — set `lazy=True` to defer creation (wrapped in `ComponentProxy`).
70
- * **Factories** — encapsulate complex creation logic.
71
- * **Smart resolution order** — **parameter name** takes precedence over **type annotation**, then **MRO fallback**, then **string(name)**.
72
- * **Re-entrancy guard** — prevents `get()` during scanning.
73
- * **Auto-exclude caller** — `init()` skips the calling module to avoid double scanning.
74
-
75
- ---
76
-
77
- ## 📦 Installation
78
-
79
- ```bash
80
- pip install pico-ioc
81
- ````
82
-
83
- ---
84
-
85
- ## 🚀 Quick Start
86
-
87
- ```python
88
- from pico_ioc import component, init
89
-
90
- @component
91
- class AppConfig:
92
- def get_db_url(self):
93
- return "postgresql://user:pass@host/db"
94
-
95
- @component
96
- class DatabaseService:
97
- def __init__(self, config: AppConfig):
98
- self._cs = config.get_db_url()
99
- def get_data(self):
100
- return f"Data from {self._cs}"
101
-
102
- container = init(__name__) # blueprint runs here (eager + fail-fast)
103
- db = container.get(DatabaseService)
104
- print(db.get_data())
105
- ```
106
-
107
- ---
108
-
109
- ## 🧩 Custom Component Keys
110
-
111
- ```python
112
- from pico_ioc import component, init
113
-
114
- @component(name="config") # custom key
115
- class AppConfig:
116
- db_url = "postgresql://user:pass@localhost/db"
117
-
118
- @component
119
- class Repository:
120
- def __init__(self, config: "config"): # resolve by NAME
121
- self.url = config.db_url
122
-
123
- container = init(__name__)
124
- print(container.get("config").db_url)
125
- ```
126
-
127
- ---
128
-
129
- ## 🏭 Factories and `@provides`
130
-
131
- * Default is **eager** (`lazy=False`). Eager bindings are constructed at the end of `init()`.
132
- * Use `lazy=True` for on-first-use creation via `ComponentProxy`.
133
-
134
- ```python
135
- from pico_ioc import factory_component, provides, init
136
-
137
- COUNTER = {"value": 0}
138
-
139
- @factory_component
140
- class ServicesFactory:
141
- @provides(key="heavy_service", lazy=True)
142
- def heavy(self):
143
- COUNTER["value"] += 1
144
- return {"payload": "hello"}
145
-
146
- container = init(__name__)
147
- svc = container.get("heavy_service") # not created yet
148
- print(COUNTER["value"]) # 0
149
- print(svc["payload"]) # triggers creation
150
- print(COUNTER["value"]) # 1
151
- ```
152
-
153
- ---
154
-
155
- ## 🧠 Dependency Resolution Order (Updated in v0.5.0)
156
-
157
- Starting with **v0.5.0**, Pico-IoC enforces **name-first resolution**:
158
-
159
- 1. **Parameter name** (highest priority)
160
- 2. **Exact type annotation**
161
- 3. **MRO fallback** (walk base classes)
162
- 4. **String(name)**
163
-
164
- This means that if a dependency could match both by name and type, **the name match wins**.
165
-
166
- Example:
167
-
168
- ```python
169
- from pico_ioc import component, factory_component, provides, init
170
-
171
- class BaseType: ...
172
- class Impl(BaseType): ...
173
-
174
- @component(name="inject_by_name")
175
- class InjectByName:
176
- def __init__(self):
177
- self.value = "by-name"
178
-
179
- @factory_component
180
- class NameVsTypeFactory:
181
- @provides("choose", lazy=True)
182
- def make(self, inject_by_name, hint: BaseType = None):
183
- return inject_by_name.value
184
-
185
- container = init(__name__)
186
- assert container.get("choose") == "by-name"
187
- ```
188
-
189
- ---
190
-
191
- ## ⚡ Eager vs. Lazy (Blueprint Behavior)
192
-
193
- At the end of `init()`, Pico-IoC performs a **blueprint**:
194
-
195
- * **Eager** (`lazy=False`, default): instantiated immediately; failures stop startup.
196
- * **Lazy** (`lazy=True`): returns a `ComponentProxy`; instantiated on first real use.
197
-
198
- **Lifecycle:**
199
-
200
- ```
201
- ┌───────────────────────┐
202
- │ init() │
203
- └───────────────────────┘
204
-
205
-
206
- ┌───────────────────────┐
207
- │ Scan & bind deps │
208
- └───────────────────────┘
209
-
210
-
211
- ┌─────────────────────────────┐
212
- │ Blueprint instantiates all │
213
- │ non-lazy (eager) beans │
214
- └─────────────────────────────┘
215
-
216
- ┌───────────────────────┐
217
- │ Container ready │
218
- └───────────────────────┘
219
- ```
220
-
221
- ---
222
-
223
- ## 🛠 API Reference
224
-
225
- ### `init(root, *, exclude=None, auto_exclude_caller=True) -> PicoContainer`
226
-
227
- Scan and bind components in `root` (str module name or module).
228
- Skips the calling module if `auto_exclude_caller=True`.
229
- Runs blueprint (instantiate all `lazy=False` bindings).
230
-
231
- ### `@component(cls=None, *, name=None, lazy=False)`
232
-
233
- Register a class as a component.
234
- Use `name` for a custom key.
235
- Set `lazy=True` to defer creation.
236
-
237
- ### `@factory_component`
238
-
239
- Mark a class as a component factory (its methods can `@provides` bindings).
240
-
241
- ### `@provides(key, *, lazy=False)`
242
-
243
- Declare that a factory method provides a component under `key`.
244
- Set `lazy=True` for deferred creation (`ComponentProxy`).
245
-
246
- ---
247
-
248
- ## 🧪 Testing
249
-
250
- ```bash
251
- pip install tox
252
- tox
253
- ```
254
-
255
- **New in v0.5.0:**
256
- Additional tests verify:
257
-
258
- * Name vs. type precedence.
259
- * Mixed binding key resolution in factories.
260
- * Eager vs. lazy instantiation edge cases.
261
-
262
- ---
263
-
264
- ## 🔌 Extensibility: Plugins, Binder, and Lifecycle Hooks
265
-
266
- From `v0.4.0` onward, Pico-IoC can be cleanly extended without patching the core.
267
-
268
- *(plugin API docs unchanged from before)*
269
-
270
- ---
271
-
272
- ## 📜 License
273
-
274
- MIT — see [LICENSE](https://opensource.org/licenses/MIT)
275
-
276
- ```
277
-
278
-
@@ -1,7 +0,0 @@
1
- pico_ioc/__init__.py,sha256=zWSJSAIgpZ_bXNi_6s88Lmql181ECyIy_Yh7hc5SOd8,16487
2
- pico_ioc/_version.py,sha256=pIxUWQG2brcif6SJXtn4CcMr6f5oY-6lwZ_FJEilJwQ,22
3
- pico_ioc-0.5.2.dist-info/licenses/LICENSE,sha256=N1_nOvHTM6BobYnOTNXiQkroDqCEi6EzfGBv8lWtyZ0,1077
4
- pico_ioc-0.5.2.dist-info/METADATA,sha256=jl1Y3pGbCz-PjZv7Cvmjy1sE7utZhL8ZZIcAmLW-uCk,9431
5
- pico_ioc-0.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
- pico_ioc-0.5.2.dist-info/top_level.txt,sha256=_7_RLu616z_dtRw16impXn4Mw8IXe2J4BeX5912m5dQ,9
7
- pico_ioc-0.5.2.dist-info/RECORD,,