pico-ioc 1.0.0__py3-none-any.whl → 1.1.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.
- pico_ioc/_version.py +1 -1
- pico_ioc/api.py +23 -11
- pico_ioc/container.py +3 -0
- {pico_ioc-1.0.0.dist-info → pico_ioc-1.1.0.dist-info}/METADATA +22 -1
- {pico_ioc-1.0.0.dist-info → pico_ioc-1.1.0.dist-info}/RECORD +8 -8
- {pico_ioc-1.0.0.dist-info → pico_ioc-1.1.0.dist-info}/WHEEL +0 -0
- {pico_ioc-1.0.0.dist-info → pico_ioc-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {pico_ioc-1.0.0.dist-info → pico_ioc-1.1.0.dist-info}/top_level.txt +0 -0
pico_ioc/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '1.
|
|
1
|
+
__version__ = '1.1.0'
|
pico_ioc/api.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import inspect
|
|
4
4
|
import logging
|
|
5
5
|
from contextlib import contextmanager
|
|
6
|
-
from typing import Callable, Optional, Tuple
|
|
6
|
+
from typing import Callable, Optional, Tuple, Any, Dict # ⬅️ Any, Dict
|
|
7
7
|
|
|
8
8
|
from .container import PicoContainer, Binder
|
|
9
9
|
from .plugins import PicoPlugin
|
|
@@ -24,14 +24,14 @@ def init(
|
|
|
24
24
|
auto_exclude_caller: bool = True,
|
|
25
25
|
plugins: Tuple[PicoPlugin, ...] = (),
|
|
26
26
|
reuse: bool = True,
|
|
27
|
+
overrides: Optional[Dict[Any, Any]] = None, # ⬅️ NUEVO
|
|
27
28
|
) -> PicoContainer:
|
|
28
|
-
|
|
29
|
-
Initialize and configure a PicoContainer by scanning a root package.
|
|
30
|
-
"""
|
|
29
|
+
|
|
31
30
|
root_name = root_package if isinstance(root_package, str) else getattr(root_package, "__name__", None)
|
|
32
31
|
|
|
33
|
-
# Reuse only if the existing container was built for the same root
|
|
34
32
|
if reuse and _state._container and _state._root_name == root_name:
|
|
33
|
+
if overrides:
|
|
34
|
+
_apply_overrides(_state._container, overrides)
|
|
35
35
|
return _state._container
|
|
36
36
|
|
|
37
37
|
combined_exclude = _build_exclude(exclude, auto_exclude_caller, root_name=root_name)
|
|
@@ -48,6 +48,9 @@ def init(
|
|
|
48
48
|
plugins=plugins,
|
|
49
49
|
)
|
|
50
50
|
|
|
51
|
+
if overrides:
|
|
52
|
+
_apply_overrides(container, overrides)
|
|
53
|
+
|
|
51
54
|
_run_hooks(plugins, "after_bind", container, binder)
|
|
52
55
|
_run_hooks(plugins, "before_eager", container, binder)
|
|
53
56
|
|
|
@@ -57,22 +60,32 @@ def init(
|
|
|
57
60
|
|
|
58
61
|
logging.info("Container configured and ready.")
|
|
59
62
|
_state._container = container
|
|
60
|
-
_state._root_name = root_name
|
|
63
|
+
_state._root_name = root_name
|
|
61
64
|
return container
|
|
62
65
|
|
|
63
66
|
|
|
64
67
|
# -------------------- helpers --------------------
|
|
65
68
|
|
|
69
|
+
def _apply_overrides(container: PicoContainer, overrides: Dict[Any, Any]) -> None:
|
|
70
|
+
for key, val in overrides.items():
|
|
71
|
+
lazy = False
|
|
72
|
+
if isinstance(val, tuple) and len(val) == 2 and callable(val[0]) and isinstance(val[1], bool):
|
|
73
|
+
provider = val[0]
|
|
74
|
+
lazy = val[1]
|
|
75
|
+
elif callable(val):
|
|
76
|
+
provider = val
|
|
77
|
+
else:
|
|
78
|
+
def provider(v=val):
|
|
79
|
+
return v
|
|
80
|
+
container.bind(key, provider, lazy=lazy)
|
|
81
|
+
|
|
82
|
+
|
|
66
83
|
def _build_exclude(
|
|
67
84
|
exclude: Optional[Callable[[str], bool]],
|
|
68
85
|
auto_exclude_caller: bool,
|
|
69
86
|
*,
|
|
70
87
|
root_name: Optional[str] = None,
|
|
71
88
|
) -> Optional[Callable[[str], bool]]:
|
|
72
|
-
"""
|
|
73
|
-
Compose the exclude predicate. When auto_exclude_caller=True, exclude only
|
|
74
|
-
the exact calling module, but never exclude modules under the root being scanned.
|
|
75
|
-
"""
|
|
76
89
|
if not auto_exclude_caller:
|
|
77
90
|
return exclude
|
|
78
91
|
|
|
@@ -91,7 +104,6 @@ def _build_exclude(
|
|
|
91
104
|
|
|
92
105
|
|
|
93
106
|
def _get_caller_module_name() -> Optional[str]:
|
|
94
|
-
"""Return the module name that called `init`."""
|
|
95
107
|
try:
|
|
96
108
|
f = inspect.currentframe()
|
|
97
109
|
# frame -> _get_caller_module_name -> _build_exclude -> init
|
pico_ioc/container.py
CHANGED
|
@@ -28,6 +28,9 @@ class PicoContainer:
|
|
|
28
28
|
self._singletons: Dict[Any, Any] = {}
|
|
29
29
|
|
|
30
30
|
def bind(self, key: Any, provider, *, lazy: bool):
|
|
31
|
+
# 🔧 rebind must evict any cached singleton for this key
|
|
32
|
+
self._singletons.pop(key, None)
|
|
33
|
+
|
|
31
34
|
meta = {"factory": provider, "lazy": bool(lazy)}
|
|
32
35
|
try:
|
|
33
36
|
q = getattr(key, QUALIFIERS_KEY, ())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pico-ioc
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: A minimalist, zero-dependency Inversion of Control (IoC) container for Python.
|
|
5
5
|
Author-email: David Perez Cabrera <dperezcabrera@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -72,6 +72,7 @@ It helps you build loosely-coupled, testable apps without manual wiring. Inspire
|
|
|
72
72
|
- **Plugins** — lifecycle hooks (`before_scan`, `after_ready`).
|
|
73
73
|
- **Public API helper** — auto-export decorated symbols in `__init__.py`.
|
|
74
74
|
- **Thread/async safe** — isolation via `ContextVar`.
|
|
75
|
+
- **Overrides for testing** — inject mocks/fakes directly via `init(overrides={...})`.
|
|
75
76
|
|
|
76
77
|
---
|
|
77
78
|
|
|
@@ -117,7 +118,21 @@ print(svc.run())
|
|
|
117
118
|
```
|
|
118
119
|
fetching from sqlite:///demo.db
|
|
119
120
|
```
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### Quick overrides for testing
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from pico_ioc import init
|
|
127
|
+
import myapp
|
|
120
128
|
|
|
129
|
+
fake = {"repo": "fake-data"}
|
|
130
|
+
c = init(myapp, overrides={
|
|
131
|
+
"fast_model": fake, # constant instance
|
|
132
|
+
"user_service": lambda: {"id": 1}, # provider
|
|
133
|
+
})
|
|
134
|
+
assert c.get("fast_model") == {"repo": "fake-data"}
|
|
135
|
+
```
|
|
121
136
|
---
|
|
122
137
|
|
|
123
138
|
## 📖 Documentation
|
|
@@ -137,6 +152,12 @@ tox
|
|
|
137
152
|
|
|
138
153
|
---
|
|
139
154
|
|
|
155
|
+
## 📜 Changelog
|
|
156
|
+
|
|
157
|
+
See [CHANGELOG.md](./CHANGELOG.md) for version history.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
140
161
|
## 📜 License
|
|
141
162
|
|
|
142
163
|
MIT — see [LICENSE](https://opensource.org/licenses/MIT)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
pico_ioc/__init__.py,sha256=7EyifZ02LFfhkAR6zzAaQJvByyMI2_-qNrw49gPoJkA,633
|
|
2
2
|
pico_ioc/_state.py,sha256=KHNtdPrv1s-uynfot2IsNkWotBPyORPCcM2xe9qMMPo,286
|
|
3
|
-
pico_ioc/_version.py,sha256=
|
|
4
|
-
pico_ioc/api.py,sha256=
|
|
5
|
-
pico_ioc/container.py,sha256=
|
|
3
|
+
pico_ioc/_version.py,sha256=b6-WiVk0Li5MaV2rBnHYl104TsouINojSWKqHDas0js,22
|
|
4
|
+
pico_ioc/api.py,sha256=pInjKJ1oi8bM4N0u4T3XLFa2qmYiHpQ7omcdXFFkGmE,3928
|
|
5
|
+
pico_ioc/container.py,sha256=oyCCeiPFVx7qw51IR9_ReuccInnpYMNuYhKxOKsioYE,5193
|
|
6
6
|
pico_ioc/decorators.py,sha256=gNPxLFNEdFUFYlxILKjU76XyoPohediK0DNiv-RpK3I,1902
|
|
7
7
|
pico_ioc/plugins.py,sha256=JbI-28VLGJaik7ysXi3L-YGTGxhqwJH4W5QYuWSruDE,589
|
|
8
8
|
pico_ioc/proxy.py,sha256=-e3Z9z7Bc_2wxswwUJI_s8AfvCTps8f8RWUJ9RuEp7E,4606
|
|
@@ -10,8 +10,8 @@ pico_ioc/public_api.py,sha256=E3sArCoI1xxkIw7xQBvLYAWcIoVJjcq1s0kH-0qIVDE,2383
|
|
|
10
10
|
pico_ioc/resolver.py,sha256=PN5uq2dFEStAzzTEl0n4AEyC-k7TowqCu7-uwIDDgEk,3897
|
|
11
11
|
pico_ioc/scanner.py,sha256=-iOj_qX15IBFmOAFQlP_1rIkBfamGzdqYdvIPOvq7sY,7709
|
|
12
12
|
pico_ioc/typing_utils.py,sha256=JQ4bkR60pKxFs3f8JlEz41ruKDsWj-SmkKv3DLJriec,950
|
|
13
|
-
pico_ioc-1.
|
|
14
|
-
pico_ioc-1.
|
|
15
|
-
pico_ioc-1.
|
|
16
|
-
pico_ioc-1.
|
|
17
|
-
pico_ioc-1.
|
|
13
|
+
pico_ioc-1.1.0.dist-info/licenses/LICENSE,sha256=N1_nOvHTM6BobYnOTNXiQkroDqCEi6EzfGBv8lWtyZ0,1077
|
|
14
|
+
pico_ioc-1.1.0.dist-info/METADATA,sha256=9tZ6dAnCgwLxD2GinaNb3U0FsCTPHTmicJxk9YsFY18,5920
|
|
15
|
+
pico_ioc-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
16
|
+
pico_ioc-1.1.0.dist-info/top_level.txt,sha256=_7_RLu616z_dtRw16impXn4Mw8IXe2J4BeX5912m5dQ,9
|
|
17
|
+
pico_ioc-1.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|