pico-ioc 1.3.0__py3-none-any.whl → 1.4.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/__init__.py +13 -0
- pico_ioc/_state.py +60 -25
- pico_ioc/_version.py +1 -1
- pico_ioc/api.py +36 -55
- pico_ioc/builder.py +93 -41
- pico_ioc/config.py +332 -0
- pico_ioc/container.py +30 -11
- pico_ioc/decorators.py +30 -6
- pico_ioc/interceptors.py +13 -7
- pico_ioc/policy.py +102 -189
- pico_ioc/proxy.py +30 -18
- pico_ioc/resolver.py +28 -25
- pico_ioc/scanner.py +21 -21
- pico_ioc/scope.py +46 -0
- {pico_ioc-1.3.0.dist-info → pico_ioc-1.4.0.dist-info}/METADATA +7 -1
- pico_ioc-1.4.0.dist-info/RECORD +22 -0
- pico_ioc-1.3.0.dist-info/RECORD +0 -20
- {pico_ioc-1.3.0.dist-info → pico_ioc-1.4.0.dist-info}/WHEEL +0 -0
- {pico_ioc-1.3.0.dist-info → pico_ioc-1.4.0.dist-info}/licenses/LICENSE +0 -0
- {pico_ioc-1.3.0.dist-info → pico_ioc-1.4.0.dist-info}/top_level.txt +0 -0
pico_ioc/resolver.py
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
# pico_ioc/resolver.py
|
|
2
|
-
|
|
1
|
+
# src/pico_ioc/resolver.py
|
|
3
2
|
from __future__ import annotations
|
|
3
|
+
|
|
4
4
|
import inspect
|
|
5
|
-
from typing import Any, Annotated, get_args, get_origin, get_type_hints
|
|
5
|
+
from typing import Any, Annotated, Callable, get_args, get_origin, get_type_hints
|
|
6
6
|
from contextvars import ContextVar
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
_path: ContextVar[list[tuple[str, str]]] = ContextVar("pico_resolve_path", default=[])
|
|
10
10
|
|
|
11
|
+
|
|
11
12
|
def _get_hints(obj, owner_cls=None) -> dict:
|
|
12
|
-
"""type hints with include_extras=True
|
|
13
|
+
"""Return type hints with include_extras=True, using correct globals/locals."""
|
|
13
14
|
mod = inspect.getmodule(obj)
|
|
14
15
|
g = getattr(mod, "__dict__", {})
|
|
15
16
|
l = vars(owner_cls) if owner_cls is not None else None
|
|
@@ -17,15 +18,14 @@ def _get_hints(obj, owner_cls=None) -> dict:
|
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
def _is_collection_hint(tp) -> bool:
|
|
20
|
-
"""True if tp is a list[...] or tuple[...]."""
|
|
21
21
|
origin = get_origin(tp) or tp
|
|
22
22
|
return origin in (list, tuple)
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _base_and_qualifiers_from_hint(tp):
|
|
26
26
|
"""
|
|
27
|
-
Extract (base, qualifiers, container_kind) from a
|
|
28
|
-
Supports list[T]
|
|
27
|
+
Extract (base, qualifiers, container_kind) from a type hint.
|
|
28
|
+
Supports list[T], tuple[T], Annotated[T, "qual1", ...].
|
|
29
29
|
"""
|
|
30
30
|
origin = get_origin(tp) or tp
|
|
31
31
|
args = get_args(tp) or ()
|
|
@@ -48,12 +48,13 @@ class Resolver:
|
|
|
48
48
|
self.c = container
|
|
49
49
|
self._prefer_name_first = bool(prefer_name_first)
|
|
50
50
|
|
|
51
|
+
# --- core resolution ---
|
|
51
52
|
|
|
52
53
|
def _resolve_dependencies_for_callable(self, fn: Callable, owner_cls: Any = None) -> dict:
|
|
53
54
|
sig = inspect.signature(fn)
|
|
54
55
|
hints = _get_hints(fn, owner_cls=owner_cls)
|
|
55
56
|
kwargs = {}
|
|
56
|
-
|
|
57
|
+
|
|
57
58
|
path_owner = getattr(owner_cls, "__name__", getattr(fn, "__qualname__", "callable"))
|
|
58
59
|
if fn.__name__ == "__init__" and owner_cls:
|
|
59
60
|
path_owner = f"{path_owner}.__init__"
|
|
@@ -61,23 +62,18 @@ class Resolver:
|
|
|
61
62
|
for name, param in sig.parameters.items():
|
|
62
63
|
if param.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD) or name == "self":
|
|
63
64
|
continue
|
|
64
|
-
|
|
65
|
+
|
|
65
66
|
ann = hints.get(name, param.annotation)
|
|
66
67
|
st = _path.get()
|
|
67
68
|
_path.set(st + [(path_owner, name)])
|
|
68
69
|
try:
|
|
69
|
-
|
|
70
|
-
kwargs[name] = value
|
|
70
|
+
kwargs[name] = self._resolve_param(name, ann)
|
|
71
71
|
except NameError as e:
|
|
72
72
|
if param.default is not inspect.Parameter.empty:
|
|
73
73
|
_path.set(st)
|
|
74
74
|
continue
|
|
75
|
-
|
|
76
|
-
# If the error is already formatted with a chain, re-raise to preserve the full context.
|
|
77
75
|
if "(required by" in str(e):
|
|
78
76
|
raise
|
|
79
|
-
|
|
80
|
-
# Otherwise, this is a fresh error; add the full chain for the first time.
|
|
81
77
|
chain = " -> ".join(f"{owner}.{param}" for owner, param in _path.get())
|
|
82
78
|
raise NameError(f"{e} (required by {chain})") from e
|
|
83
79
|
finally:
|
|
@@ -87,43 +83,50 @@ class Resolver:
|
|
|
87
83
|
return kwargs
|
|
88
84
|
|
|
89
85
|
def create_instance(self, cls: type) -> Any:
|
|
90
|
-
"""
|
|
91
|
-
|
|
92
|
-
return cls(**
|
|
86
|
+
"""Instantiate a class by resolving its __init__ dependencies."""
|
|
87
|
+
ctor_kwargs = self._resolve_dependencies_for_callable(cls.__init__, owner_cls=cls)
|
|
88
|
+
return cls(**ctor_kwargs)
|
|
93
89
|
|
|
94
90
|
def kwargs_for_callable(self, fn: Callable, *, owner_cls: Any = None) -> dict:
|
|
95
|
-
"""
|
|
91
|
+
"""Resolve all keyword arguments for any callable."""
|
|
96
92
|
return self._resolve_dependencies_for_callable(fn, owner_cls=owner_cls)
|
|
97
93
|
|
|
94
|
+
# --- param resolution ---
|
|
98
95
|
|
|
99
96
|
def _notify_resolve(self, key, ann, quals=()):
|
|
100
97
|
for ci in getattr(self.c, "_container_interceptors", ()):
|
|
101
|
-
try:
|
|
102
|
-
|
|
98
|
+
try:
|
|
99
|
+
ci.on_resolve(key, ann, tuple(quals) if quals else ())
|
|
100
|
+
except Exception:
|
|
101
|
+
pass
|
|
103
102
|
|
|
104
103
|
def _resolve_param(self, name: str, ann: Any):
|
|
105
|
-
#
|
|
104
|
+
# collections
|
|
106
105
|
if _is_collection_hint(ann):
|
|
107
|
-
base, quals,
|
|
106
|
+
base, quals, kind = _base_and_qualifiers_from_hint(ann)
|
|
108
107
|
self._notify_resolve(base, ann, quals)
|
|
109
108
|
items = self.c._resolve_all_for_base(base, qualifiers=quals)
|
|
110
|
-
return list(items) if
|
|
109
|
+
return list(items) if kind is list else tuple(items)
|
|
111
110
|
|
|
112
|
-
#
|
|
111
|
+
# precedence
|
|
113
112
|
if self._prefer_name_first and self.c.has(name):
|
|
114
113
|
self._notify_resolve(name, ann, ())
|
|
115
114
|
return self.c.get(name)
|
|
115
|
+
|
|
116
116
|
if ann is not inspect._empty and self.c.has(ann):
|
|
117
117
|
self._notify_resolve(ann, ann, ())
|
|
118
118
|
return self.c.get(ann)
|
|
119
|
+
|
|
119
120
|
if ann is not inspect._empty and isinstance(ann, type):
|
|
120
121
|
for base in ann.__mro__[1:]:
|
|
121
122
|
if self.c.has(base):
|
|
122
123
|
self._notify_resolve(base, ann, ())
|
|
123
124
|
return self.c.get(base)
|
|
125
|
+
|
|
124
126
|
if self.c.has(name):
|
|
125
127
|
self._notify_resolve(name, ann, ())
|
|
126
128
|
return self.c.get(name)
|
|
127
129
|
|
|
128
130
|
missing = ann if ann is not inspect._empty else name
|
|
129
131
|
raise NameError(f"No provider found for key {missing!r}")
|
|
132
|
+
|
pico_ioc/scanner.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
# pico_ioc/scanner.py
|
|
1
|
+
# src/pico_ioc/scanner.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
2
4
|
import importlib
|
|
3
5
|
import inspect
|
|
4
6
|
import logging
|
|
@@ -6,7 +8,7 @@ import pkgutil
|
|
|
6
8
|
from types import ModuleType
|
|
7
9
|
from typing import Any, Callable, Optional, Tuple, List, Iterable
|
|
8
10
|
|
|
9
|
-
from .plugins import run_plugin_hook
|
|
11
|
+
from .plugins import run_plugin_hook, PicoPlugin
|
|
10
12
|
from .container import PicoContainer, Binder
|
|
11
13
|
from .decorators import (
|
|
12
14
|
COMPONENT_FLAG,
|
|
@@ -21,9 +23,9 @@ from .decorators import (
|
|
|
21
23
|
)
|
|
22
24
|
from .proxy import ComponentProxy
|
|
23
25
|
from .resolver import Resolver
|
|
24
|
-
from .plugins import PicoPlugin
|
|
25
26
|
from . import _state
|
|
26
27
|
from .utils import _provider_from_class, _provider_from_callable
|
|
28
|
+
from .config import is_config_component, build_component_instance, ConfigRegistry
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
def scan_and_configure(
|
|
@@ -35,12 +37,12 @@ def scan_and_configure(
|
|
|
35
37
|
) -> tuple[int, int, list[tuple[Any, dict]]]:
|
|
36
38
|
"""
|
|
37
39
|
Scan a package, bind components/factories, and collect interceptor declarations.
|
|
38
|
-
Returns: (component_count, factory_count, interceptor_decls)
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
Returns: (component_count, factory_count, interceptor_decls)
|
|
42
|
+
- interceptor_decls entries:
|
|
43
|
+
(cls, meta) for @interceptor class
|
|
44
|
+
(fn, meta) for @interceptor function
|
|
45
|
+
((owner_cls, fn), meta) for @interceptor methods
|
|
44
46
|
"""
|
|
45
47
|
package = _as_module(package_or_name)
|
|
46
48
|
logging.info("Scanning in '%s'...", getattr(package, "__name__", repr(package)))
|
|
@@ -65,7 +67,7 @@ def scan_and_configure(
|
|
|
65
67
|
return len(comp_classes), len(factory_classes), interceptor_decls
|
|
66
68
|
|
|
67
69
|
|
|
68
|
-
# --------------------
|
|
70
|
+
# -------------------- helpers --------------------
|
|
69
71
|
|
|
70
72
|
def _as_module(package_or_name: Any) -> ModuleType:
|
|
71
73
|
if isinstance(package_or_name, str):
|
|
@@ -98,37 +100,30 @@ def _collect_decorated(
|
|
|
98
100
|
interceptors: List[tuple[Any, dict]] = []
|
|
99
101
|
|
|
100
102
|
def _collect_from_class(cls: type):
|
|
101
|
-
# Class decorators
|
|
102
103
|
if getattr(cls, COMPONENT_FLAG, False):
|
|
103
104
|
comps.append(cls)
|
|
104
105
|
elif getattr(cls, FACTORY_FLAG, False):
|
|
105
106
|
facts.append(cls)
|
|
106
107
|
|
|
107
|
-
# Class-level interceptor (decorated class itself)
|
|
108
108
|
meta_class = getattr(cls, INTERCEPTOR_META, None)
|
|
109
109
|
if meta_class:
|
|
110
110
|
interceptors.append((cls, dict(meta_class)))
|
|
111
111
|
|
|
112
|
-
# Method-level interceptors
|
|
113
112
|
for _nm, fn in inspect.getmembers(cls, predicate=inspect.isfunction):
|
|
114
113
|
meta_m = getattr(fn, INTERCEPTOR_META, None)
|
|
115
114
|
if meta_m:
|
|
116
|
-
# Preserve the owner to allow proper binding (self) later
|
|
117
115
|
interceptors.append(((cls, fn), dict(meta_m)))
|
|
118
116
|
|
|
119
117
|
def _visit_module(module: ModuleType):
|
|
120
|
-
# Classes
|
|
121
118
|
for _name, obj in inspect.getmembers(module, inspect.isclass):
|
|
122
119
|
run_plugin_hook(plugins, "visit_class", module, obj, binder)
|
|
123
120
|
_collect_from_class(obj)
|
|
124
121
|
|
|
125
|
-
# Module-level functions that declare interceptors
|
|
126
122
|
for _name, fn in inspect.getmembers(module, predicate=inspect.isfunction):
|
|
127
123
|
meta = getattr(fn, INTERCEPTOR_META, None)
|
|
128
124
|
if meta:
|
|
129
125
|
interceptors.append((fn, dict(meta)))
|
|
130
126
|
|
|
131
|
-
# Walk submodules
|
|
132
127
|
for mod_name in _iter_package_modules(package):
|
|
133
128
|
if exclude and exclude(mod_name):
|
|
134
129
|
logging.info("Skipping module %s (excluded)", mod_name)
|
|
@@ -140,12 +135,12 @@ def _collect_decorated(
|
|
|
140
135
|
continue
|
|
141
136
|
_visit_module(module)
|
|
142
137
|
|
|
143
|
-
# Also visit the root module itself (in case it's a single-file module)
|
|
144
138
|
if not hasattr(package, "__path__"):
|
|
145
139
|
_visit_module(package)
|
|
146
140
|
|
|
147
141
|
return comps, facts, interceptors
|
|
148
142
|
|
|
143
|
+
|
|
149
144
|
def _register_component_classes(
|
|
150
145
|
*,
|
|
151
146
|
classes: List[type],
|
|
@@ -156,7 +151,15 @@ def _register_component_classes(
|
|
|
156
151
|
key = getattr(cls, COMPONENT_KEY, cls)
|
|
157
152
|
is_lazy = bool(getattr(cls, COMPONENT_LAZY, False))
|
|
158
153
|
tags = tuple(getattr(cls, COMPONENT_TAGS, ()))
|
|
159
|
-
|
|
154
|
+
if is_config_component(cls):
|
|
155
|
+
registry: ConfigRegistry | None = getattr(container, "_config_registry", None)
|
|
156
|
+
def _prov(_c=cls, _reg=registry):
|
|
157
|
+
if _reg is None:
|
|
158
|
+
raise RuntimeError(f"No config registry found to build {_c.__name__}")
|
|
159
|
+
return build_component_instance(_c, _reg)
|
|
160
|
+
provider = (lambda p=_prov: ComponentProxy(p)) if is_lazy else _prov
|
|
161
|
+
else:
|
|
162
|
+
provider = _provider_from_class(cls, resolver=resolver, lazy=is_lazy)
|
|
160
163
|
container.bind(key, provider, lazy=is_lazy, tags=tags)
|
|
161
164
|
|
|
162
165
|
|
|
@@ -168,7 +171,6 @@ def _register_factory_classes(
|
|
|
168
171
|
) -> None:
|
|
169
172
|
for fcls in factory_classes:
|
|
170
173
|
try:
|
|
171
|
-
# Prevent accidental container access recursion while constructing factories
|
|
172
174
|
tok_res = _state._resolving.set(True)
|
|
173
175
|
try:
|
|
174
176
|
finst = resolver.create_instance(fcls)
|
|
@@ -186,12 +188,10 @@ def _register_factory_classes(
|
|
|
186
188
|
is_lazy = bool(getattr(func, PROVIDES_LAZY, False))
|
|
187
189
|
tags = tuple(getattr(func, PROVIDES_TAGS, ()))
|
|
188
190
|
|
|
189
|
-
# bind the method to the concrete factory instance
|
|
190
191
|
bound = getattr(finst, attr_name, func.__get__(finst, fcls))
|
|
191
192
|
prov = _provider_from_callable(bound, owner_cls=fcls, resolver=resolver, lazy=is_lazy)
|
|
192
193
|
|
|
193
194
|
if isinstance(provided_key, type):
|
|
194
|
-
# Mark for aliasing policy pipeline and ensure uniqueness of the provider key
|
|
195
195
|
try:
|
|
196
196
|
setattr(prov, "_pico_alias_for", provided_key)
|
|
197
197
|
except Exception:
|
pico_ioc/scope.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from .container import PicoContainer
|
|
6
|
+
|
|
7
|
+
class ScopedContainer(PicoContainer):
|
|
8
|
+
def __init__(self, built_container: PicoContainer, base: Optional[PicoContainer], strict: bool):
|
|
9
|
+
super().__init__(providers=getattr(built_container, "_providers", {}).copy())
|
|
10
|
+
|
|
11
|
+
self._active_profiles = getattr(built_container, "_active_profiles", ())
|
|
12
|
+
|
|
13
|
+
base_method_its = getattr(base, "_method_interceptors", ()) if base else ()
|
|
14
|
+
base_container_its = getattr(base, "_container_interceptors", ()) if base else ()
|
|
15
|
+
|
|
16
|
+
self._method_interceptors = base_method_its
|
|
17
|
+
self._container_interceptors = base_container_its
|
|
18
|
+
self._seen_interceptor_types = {type(it) for it in (base_method_its + base_container_its)}
|
|
19
|
+
|
|
20
|
+
for it in getattr(built_container, "_method_interceptors", ()):
|
|
21
|
+
self.add_method_interceptor(it)
|
|
22
|
+
for it in getattr(built_container, "_container_interceptors", ()):
|
|
23
|
+
self.add_container_interceptor(it)
|
|
24
|
+
|
|
25
|
+
self._base = base
|
|
26
|
+
self._strict = strict
|
|
27
|
+
|
|
28
|
+
if base:
|
|
29
|
+
self._singletons.update(getattr(base, "_singletons", {}))
|
|
30
|
+
|
|
31
|
+
def __enter__(self): return self
|
|
32
|
+
def __exit__(self, exc_type, exc, tb): return False
|
|
33
|
+
|
|
34
|
+
def has(self, key: Any) -> bool:
|
|
35
|
+
if super().has(key): return True
|
|
36
|
+
if not self._strict and self._base is not None:
|
|
37
|
+
return self._base.has(key)
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
def get(self, key: Any):
|
|
41
|
+
try:
|
|
42
|
+
return super().get(key)
|
|
43
|
+
except NameError as e:
|
|
44
|
+
if not self._strict and self._base is not None and self._base.has(key):
|
|
45
|
+
return self._base.get(key)
|
|
46
|
+
raise e
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pico-ioc
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.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
|
|
@@ -221,6 +221,12 @@ tox
|
|
|
221
221
|
|
|
222
222
|
---
|
|
223
223
|
|
|
224
|
+
## 📜 Overview
|
|
225
|
+
|
|
226
|
+
See [OVERVIEW.md](.llm/OVERVIEW.md) Just need a quick summary?
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
224
230
|
## 📜 Changelog
|
|
225
231
|
|
|
226
232
|
See [CHANGELOG.md](./CHANGELOG.md) for version history.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
pico_ioc/__init__.py,sha256=s_9v-pMM5X7r5vhbzaOmQQEHBLOmZCV7o6QNtRcfMAU,1282
|
|
2
|
+
pico_ioc/_state.py,sha256=C98XQZIfKy98j8fzR730eUCoqSnCkRkxUS4bH7mp73c,2154
|
|
3
|
+
pico_ioc/_version.py,sha256=EyMGX1ADFzN6XVXHWbJUtKPONYKeFkvWoKIFPDDB2I8,22
|
|
4
|
+
pico_ioc/api.py,sha256=cc9c3db6_dIfeobP_VvFRpNV9qNIsIPbUct5X9mmW9w,8348
|
|
5
|
+
pico_ioc/builder.py,sha256=ZvIpOaAzBpByw-u5V52GM5cJAMH_E_5FMDLlgyqd-g4,11379
|
|
6
|
+
pico_ioc/config.py,sha256=J3k7_2vRB2HCpikzeMzT4Ut9COFM4kcydkwZorncqSk,12317
|
|
7
|
+
pico_ioc/container.py,sha256=V9X0qvNPZYU80C65X3Dqifek6RWt9kgEwG0CkX1Hpow,6461
|
|
8
|
+
pico_ioc/decorators.py,sha256=Jyq7PhSM3uFVfBEaCq6x_mFV9V3B5fTEK4o3I6ZvG5A,4492
|
|
9
|
+
pico_ioc/interceptors.py,sha256=rBdpI7ca5L30N-zR7LKroCIc5FgfNb9M5P7OEGw-TtY,1955
|
|
10
|
+
pico_ioc/plugins.py,sha256=GP7WEMshggQ-FEjiShkcuLrSMxfueUnhbY9I8PcIyPU,1039
|
|
11
|
+
pico_ioc/policy.py,sha256=p7maTHNfU-zoaz3j7CY4P3ry-bYfaGxAOklcTAuF6dY,8648
|
|
12
|
+
pico_ioc/proxy.py,sha256=VJA-QaO8yvejcHmX5mlXMHfyuyXFxD7cazONSzBGrf0,6308
|
|
13
|
+
pico_ioc/public_api.py,sha256=E3sArCoI1xxkIw7xQBvLYAWcIoVJjcq1s0kH-0qIVDE,2383
|
|
14
|
+
pico_ioc/resolver.py,sha256=clIS9wwhOKzIwzBQFXxCrmPX2gM2X2eVyS8P_VEeyDw,4798
|
|
15
|
+
pico_ioc/scanner.py,sha256=TmDLkklO-e2LBoVducQD4-uuZKFDg_dMwgwO9vM8-pU,7129
|
|
16
|
+
pico_ioc/scope.py,sha256=5oRCir1Dqu8Jlgl_R-q900my1u6_7zq5VUbq8ahV280,1754
|
|
17
|
+
pico_ioc/utils.py,sha256=OyhOKnyepwGQ_uQKlQLt-fymEV1bQ6hCq4Me7h3dfco,1002
|
|
18
|
+
pico_ioc-1.4.0.dist-info/licenses/LICENSE,sha256=N1_nOvHTM6BobYnOTNXiQkroDqCEi6EzfGBv8lWtyZ0,1077
|
|
19
|
+
pico_ioc-1.4.0.dist-info/METADATA,sha256=DdvaybzEQOnC-HD563NJZqMDL7zwY3SnEpLGwjPxVzU,10346
|
|
20
|
+
pico_ioc-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
21
|
+
pico_ioc-1.4.0.dist-info/top_level.txt,sha256=_7_RLu616z_dtRw16impXn4Mw8IXe2J4BeX5912m5dQ,9
|
|
22
|
+
pico_ioc-1.4.0.dist-info/RECORD,,
|
pico_ioc-1.3.0.dist-info/RECORD
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
pico_ioc/__init__.py,sha256=Vl0nnRou3BZY1QSUOSyZ8-PFIFrz979DAzhXp0KYvIg,1014
|
|
2
|
-
pico_ioc/_state.py,sha256=XG3Q8NsRN-Di5MrWn6kLzJXg25PXp2_qAzfgytNoP-s,1021
|
|
3
|
-
pico_ioc/_version.py,sha256=zi_LaUT_OsChAtsPXbOeRpQkCohSsOyeXfavQPM0GoE,22
|
|
4
|
-
pico_ioc/api.py,sha256=PbR9_VX3ipxgv7-vKq1TyjKC75RqyDr65QUCG4i7eeI,9172
|
|
5
|
-
pico_ioc/builder.py,sha256=QPn1yC3JQYkjV08XpCAIFs95Bi0VQG5NZnSXKx4IgsI,10730
|
|
6
|
-
pico_ioc/container.py,sha256=YCrjAhChHtDcPBg1Zz0PnMbY-6x6V313nA1liPNaUaM,6306
|
|
7
|
-
pico_ioc/decorators.py,sha256=jhJxpaR9wCeBsNm1W0ziTCF3C0LGhu866-9x4IJ9-4U,3581
|
|
8
|
-
pico_ioc/interceptors.py,sha256=-ZH-AG4h_6vUgTJGbP8YESlODhOEkdC6r82GHTRrKxk,1978
|
|
9
|
-
pico_ioc/plugins.py,sha256=GP7WEMshggQ-FEjiShkcuLrSMxfueUnhbY9I8PcIyPU,1039
|
|
10
|
-
pico_ioc/policy.py,sha256=XQs8Nr7aTq0xbNPGaeFiBgJCI65r5rXK4yQdhhQuLjM,12054
|
|
11
|
-
pico_ioc/proxy.py,sha256=ZQ0g5QT32QV_v72N9oUWtQRnTh5An66GPtvaF1HtNp8,6187
|
|
12
|
-
pico_ioc/public_api.py,sha256=E3sArCoI1xxkIw7xQBvLYAWcIoVJjcq1s0kH-0qIVDE,2383
|
|
13
|
-
pico_ioc/resolver.py,sha256=qCzyjsfq59b_XEa5LNAgWzPniqoJYxyG-mXn2fzqFsk,5063
|
|
14
|
-
pico_ioc/scanner.py,sha256=VjIW6e2nsYuI1pm38RX8yIGs7SUrvuKHPN5vgTss3h4,7257
|
|
15
|
-
pico_ioc/utils.py,sha256=OyhOKnyepwGQ_uQKlQLt-fymEV1bQ6hCq4Me7h3dfco,1002
|
|
16
|
-
pico_ioc-1.3.0.dist-info/licenses/LICENSE,sha256=N1_nOvHTM6BobYnOTNXiQkroDqCEi6EzfGBv8lWtyZ0,1077
|
|
17
|
-
pico_ioc-1.3.0.dist-info/METADATA,sha256=GRIv4XBIAY8vFFXv0BVFyT4lVqryoUEQU9qF6jOlftc,10259
|
|
18
|
-
pico_ioc-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
19
|
-
pico_ioc-1.3.0.dist-info/top_level.txt,sha256=_7_RLu616z_dtRw16impXn4Mw8IXe2J4BeX5912m5dQ,9
|
|
20
|
-
pico_ioc-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|