omlish 0.0.0.dev462__py3-none-any.whl → 0.0.0.dev464__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.

Potentially problematic release.


This version of omlish might be problematic. Click here for more details.

omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev462'
2
- __revision__ = '5e5ee1d71115ec07b8f9627222c9f5d6d4016e5a'
1
+ __version__ = '0.0.0.dev464'
2
+ __revision__ = '8f9a53b4670200336b1878510977fc9165f866c2'
3
3
 
4
4
 
5
5
  #
@@ -41,6 +41,7 @@ def LRU(cache: 'Cache') -> None: # noqa
41
41
  cache._kill(cache._root.lru_next) # type: ignore # noqa
42
42
 
43
43
 
44
+ # aka FIFO
44
45
  def LRI(cache: 'Cache') -> None: # noqa
45
46
  cache._kill(cache._root.ins_next) # type: ignore # noqa
46
47
 
omlish/inject/__init__.py CHANGED
@@ -19,11 +19,30 @@ from .. import lang as _lang # noqa
19
19
  with _lang.auto_proxy_init(globals()):
20
20
  ##
21
21
 
22
+ from .helpers.constfn import ( # noqa
23
+ ConstFn,
24
+ )
25
+
26
+ from .helpers.id import ( # noqa
27
+ Id,
28
+ )
29
+
30
+ from .helpers.multis import ( # noqa
31
+ bind_map_entry_const,
32
+ bind_set_entry_const,
33
+
34
+ ItemsBinderHelper,
35
+ items_binder_helper,
36
+ )
37
+
38
+ from .helpers.wrappers import ( # noqa
39
+ WrapperBinderHelper,
40
+ wrapper_binder_helper,
41
+ )
42
+
22
43
  from .binder import ( # noqa
23
44
  bind,
24
45
  bind_as_fn,
25
- bind_map_entry_const,
26
- bind_set_entry_const,
27
46
  )
28
47
 
29
48
  from .bindings import ( # noqa
@@ -36,9 +55,10 @@ with _lang.auto_proxy_init(globals()):
36
55
 
37
56
  from .elements import ( # noqa
38
57
  Element,
39
- Elemental,
40
58
  Elements,
59
+ Elemental,
41
60
  as_elements,
61
+ iter_elements,
42
62
  )
43
63
 
44
64
  from .errors import ( # noqa
@@ -91,15 +111,19 @@ with _lang.auto_proxy_init(globals()):
91
111
  )
92
112
 
93
113
  from .multis import ( # noqa
94
- MapBinding,
95
- MapProvider,
114
+ is_set_multi_key,
96
115
  SetBinding,
97
116
  SetProvider,
98
- MapBinder,
117
+
118
+ is_map_multi_key,
119
+ MapBinding,
120
+ MapProvider,
121
+
99
122
  SetBinder,
123
+ set_binder,
100
124
 
101
- MapBinder as map_binder, # noqa
102
- SetBinder as set_binder, # noqa
125
+ MapBinder,
126
+ map_binder,
103
127
  )
104
128
 
105
129
 
@@ -116,10 +140,10 @@ with _lang.auto_proxy_init(globals()):
116
140
 
117
141
  from .privates import ( # noqa
118
142
  Expose,
143
+ expose,
144
+
119
145
  Private,
120
146
  private,
121
-
122
- Expose as expose, # noqa
123
147
  )
124
148
 
125
149
  from .providers import ( # noqa
@@ -153,16 +177,8 @@ with _lang.auto_proxy_init(globals()):
153
177
  create_injector,
154
178
  )
155
179
 
156
- from .tags import ( # noqa
157
- Id,
158
- )
159
-
160
180
  from .types import ( # noqa
161
181
  Scope,
162
182
  Tag,
163
183
  Unscoped,
164
184
  )
165
-
166
- from .utils import ( # noqa
167
- ConstFn,
168
- )
omlish/inject/binder.py CHANGED
@@ -11,13 +11,8 @@ from .bindings import Binding
11
11
  from .eagers import Eager
12
12
  from .elements import Element
13
13
  from .elements import Elements
14
- from .elements import as_elements
15
14
  from .keys import Key
16
15
  from .keys import as_key
17
- from .multis import MapBinding
18
- from .multis import SetBinding
19
- from .multis import is_map_multi_key
20
- from .multis import is_set_multi_key
21
16
  from .privates import Expose
22
17
  from .providers import AsyncFnProvider
23
18
  from .providers import ConstProvider
@@ -27,7 +22,6 @@ from .providers import LinkProvider
27
22
  from .providers import Provider
28
23
  from .scopes import SCOPE_ALIASES
29
24
  from .scopes import Singleton
30
- from .tags import Id
31
25
  from .types import Scope
32
26
  from .types import Unscoped
33
27
 
@@ -84,6 +78,7 @@ def bind(
84
78
  *,
85
79
  tag: ta.Any = None,
86
80
 
81
+ to_provider: Provider | None = None,
87
82
  to_async_fn: ta.Any = None,
88
83
  to_fn: ta.Any = None,
89
84
  to_ctor: ta.Any = None,
@@ -104,6 +99,7 @@ def bind(
104
99
  ##
105
100
 
106
101
  has_to = (
102
+ to_provider is not None or
107
103
  to_async_fn is not None or
108
104
  to_fn is not None or
109
105
  to_ctor is not None or
@@ -140,6 +136,8 @@ def bind(
140
136
  ##
141
137
 
142
138
  providers: list[Provider] = []
139
+ if to_provider is not None:
140
+ providers.append(to_provider)
143
141
  if to_async_fn is not None:
144
142
  providers.append(AsyncFnProvider(to_async_fn))
145
143
  if to_fn is not None:
@@ -191,45 +189,3 @@ def bind(
191
189
  return elements[0]
192
190
  else:
193
191
  return Elements(frozenset(elements))
194
-
195
-
196
- ##
197
-
198
-
199
- def bind_set_entry_const(
200
- multi_key: ta.Any,
201
- obj: ta.Any,
202
- *,
203
- tag: ta.Any | None = None,
204
- ) -> Elements:
205
- multi_key = as_key(multi_key)
206
- check.arg(is_set_multi_key(multi_key))
207
-
208
- if tag is None:
209
- tag = Id(id(obj), tag=multi_key.tag)
210
- obj_key: Key = Key(type(obj), tag=tag)
211
-
212
- return as_elements(
213
- bind(obj_key, to_const=obj),
214
- SetBinding(multi_key, obj_key),
215
- )
216
-
217
-
218
- def bind_map_entry_const(
219
- multi_key: ta.Any,
220
- map_key: ta.Any,
221
- obj: ta.Any,
222
- *,
223
- tag: ta.Any | None = None,
224
- ) -> Elements:
225
- multi_key = as_key(multi_key)
226
- check.arg(is_map_multi_key(multi_key))
227
-
228
- if tag is None:
229
- tag = Id(id(obj), tag=multi_key.tag)
230
- obj_key: Key = Key(type(obj), tag=tag)
231
-
232
- return as_elements(
233
- bind(obj_key, to_const=obj),
234
- MapBinding(multi_key, map_key, obj_key),
235
- )
omlish/inject/elements.py CHANGED
@@ -64,3 +64,13 @@ def as_elements(*args: Elemental) -> Elements:
64
64
  es if es else None,
65
65
  cs if cs else None,
66
66
  )
67
+
68
+
69
+ def iter_elements(*args: Elemental) -> ta.Iterator[Element]:
70
+ for a in args:
71
+ if isinstance(a, Element):
72
+ yield a
73
+ elif isinstance(a, (Elements, ElementGenerator)):
74
+ yield from a
75
+ else:
76
+ raise TypeError(a)
File without changes
@@ -1,8 +1,8 @@
1
1
  import typing as ta
2
2
 
3
- from .. import dataclasses as dc
4
- from .. import lang
5
- from .impl.origins import HasOriginsImpl
3
+ from ... import dataclasses as dc
4
+ from ... import lang
5
+ from ..impl.origins import HasOriginsImpl
6
6
 
7
7
 
8
8
  T = ta.TypeVar('T')
@@ -1,7 +1,7 @@
1
1
  import typing as ta
2
2
 
3
- from .. import dataclasses as dc
4
- from .types import Tag
3
+ from ... import dataclasses as dc
4
+ from ..types import Tag
5
5
 
6
6
 
7
7
  ##
@@ -0,0 +1,143 @@
1
+ import typing as ta
2
+
3
+ from ... import cached
4
+ from ... import check
5
+ from ... import dataclasses as dc
6
+ from ... import lang
7
+ from ... import reflect as rfl
8
+ from ..binder import bind
9
+ from ..elements import Elements
10
+ from ..elements import as_elements
11
+ from ..inspect import KwargsTarget
12
+ from ..keys import Key
13
+ from ..keys import as_key
14
+ from ..multis import MapBinding
15
+ from ..multis import SetBinder
16
+ from ..multis import SetBinding
17
+ from ..multis import is_map_multi_key
18
+ from ..multis import is_set_multi_key
19
+ from ..providers import FnProvider
20
+ from .id import Id
21
+
22
+
23
+ ItemT = ta.TypeVar('ItemT')
24
+
25
+
26
+ ##
27
+
28
+
29
+ def bind_set_entry_const(
30
+ multi_key: ta.Any,
31
+ obj: ta.Any,
32
+ *,
33
+ tag: ta.Any | None = None,
34
+ ) -> Elements:
35
+ multi_key = as_key(multi_key)
36
+ check.arg(is_set_multi_key(multi_key))
37
+
38
+ if tag is None:
39
+ tag = Id(id(obj), tag=multi_key.tag)
40
+ obj_key: Key = Key(type(obj), tag=tag)
41
+
42
+ return as_elements(
43
+ bind(obj_key, to_const=obj),
44
+ SetBinding(multi_key, obj_key),
45
+ )
46
+
47
+
48
+ def bind_map_entry_const(
49
+ multi_key: ta.Any,
50
+ map_key: ta.Any,
51
+ obj: ta.Any,
52
+ *,
53
+ tag: ta.Any | None = None,
54
+ ) -> Elements:
55
+ multi_key = as_key(multi_key)
56
+ check.arg(is_map_multi_key(multi_key))
57
+
58
+ if tag is None:
59
+ tag = Id(id(obj), tag=multi_key.tag)
60
+ obj_key: Key = Key(type(obj), tag=tag)
61
+
62
+ return as_elements(
63
+ bind(obj_key, to_const=obj),
64
+ MapBinding(multi_key, map_key, obj_key),
65
+ )
66
+
67
+
68
+ ##
69
+
70
+
71
+ @ta.final
72
+ class ItemsBinderHelper(ta.Generic[ItemT]):
73
+ def __init__(self, items_cls: ta.Any) -> None:
74
+ self._items_cls = items_cls
75
+
76
+ @cached.property
77
+ def _item_rty(self) -> rfl.Type:
78
+ rty = check.isinstance(rfl.type_(rfl.get_orig_class(self)), rfl.Generic)
79
+ check.is_(rty.cls, self.__class__)
80
+ return check.single(rty.args)
81
+
82
+ @dc.dataclass(frozen=True, eq=False)
83
+ class _ItemsBox:
84
+ vs: ta.Sequence
85
+
86
+ @cached.property
87
+ def _items_box(self) -> type[_ItemsBox]:
88
+ if isinstance(item_rty := self._item_rty, type):
89
+ sfx = item_rty.__qualname__
90
+ else:
91
+ sfx = str(item_rty).replace("'", '')
92
+
93
+ return lang.new_type( # noqa
94
+ f'{ItemsBinderHelper._ItemsBox.__qualname__}${sfx}@{id(self):x}',
95
+ (ItemsBinderHelper._ItemsBox,),
96
+ {},
97
+ )
98
+
99
+ @cached.property
100
+ def _set_key(self) -> Key:
101
+ return as_key(ta.AbstractSet[self._item_rty]) # type: ignore
102
+
103
+ def bind_item_consts(self, *items: ItemT) -> Elements:
104
+ return as_elements(
105
+ bind_set_entry_const(self._set_key, self._items_box(items)),
106
+ )
107
+
108
+ @dc.dataclass(frozen=True, eq=False)
109
+ @dc.extra_class_params(repr_id=True)
110
+ class _ItemTag:
111
+ pass
112
+
113
+ def bind_item(self, **kwargs: ta.Any) -> Elements:
114
+ tag = ItemsBinderHelper._ItemTag()
115
+ item_key: Key = Key(ta.Any, tag=tag)
116
+ items_box_key: Key = Key(self._items_box, tag=tag)
117
+ return as_elements(
118
+ bind(item_key, **kwargs),
119
+ bind(
120
+ items_box_key,
121
+ to_provider=FnProvider(KwargsTarget.of(
122
+ lambda v: self._items_box([v]),
123
+ v=item_key,
124
+ )),
125
+ ),
126
+ SetBinding(self._set_key, items_box_key),
127
+ )
128
+
129
+ def bind_items_provider(self, **kwargs: ta.Any) -> Elements:
130
+ return as_elements(
131
+ SetBinder[self._item_rty](), # type: ignore
132
+ bind(
133
+ self._items_cls,
134
+ to_provider=FnProvider(KwargsTarget.of(
135
+ lambda s: self._items_cls([v for i in s for v in i.vs]),
136
+ s=self._set_key,
137
+ )),
138
+ **kwargs,
139
+ ),
140
+ )
141
+
142
+
143
+ items_binder_helper = ItemsBinderHelper
@@ -0,0 +1,54 @@
1
+ import typing as ta
2
+
3
+ from ... import cached
4
+ from ... import dataclasses as dc
5
+ from ..binder import bind
6
+ from ..elements import Elemental
7
+ from ..keys import Key
8
+ from ..keys import as_key
9
+ from ..privates import private
10
+
11
+
12
+ ##
13
+
14
+
15
+ @ta.final
16
+ class WrapperBinderHelper:
17
+ def __init__(self, key: ta.Any) -> None:
18
+ self._key = as_key(key)
19
+ self._root = WrapperBinderHelper._Root()
20
+ self._top = WrapperBinderHelper._Level(self._root, 0)
21
+
22
+ @dc.dataclass(frozen=True, eq=False)
23
+ @dc.extra_class_params(repr_id=True)
24
+ class _Root:
25
+ pass
26
+
27
+ @dc.dataclass(frozen=True)
28
+ class _Level:
29
+ root: 'WrapperBinderHelper._Root'
30
+ level: int
31
+
32
+ def next(self) -> 'WrapperBinderHelper._Level':
33
+ return WrapperBinderHelper._Level(self.root, self.level + 1)
34
+
35
+ @cached.property
36
+ def key(self) -> Key:
37
+ return Key(ta.Any, tag=self)
38
+
39
+ @property
40
+ def top(self) -> Key:
41
+ return self._top.key
42
+
43
+ def push_bind(self, **kwargs: ta.Any) -> Elemental:
44
+ prv = self._top
45
+ nxt = prv.next()
46
+ out = private(
47
+ *([bind(self._key, to_key=prv.key)] if prv.level else []),
48
+ bind(nxt.key, **kwargs, expose=True),
49
+ )
50
+ self._top = nxt
51
+ return out
52
+
53
+
54
+ wrapper_binder_helper = WrapperBinderHelper
@@ -63,6 +63,23 @@ ElementT = ta.TypeVar('ElementT', bound=Element)
63
63
  ##
64
64
 
65
65
 
66
+ _SIMPLE_KEYED_ELEMENT_TYPES: tuple[type[Element], ...] = (
67
+ Binding,
68
+ Eager,
69
+ Expose,
70
+ )
71
+
72
+ _SIMPLE_NON_KEYED_ELEMENT_TYPES: tuple[type[Element], ...] = (
73
+ ProvisionListenerBinding,
74
+ )
75
+
76
+ _NON_BINDING_ELEMENT_TYPES: tuple[type[Element], ...] = (
77
+ Eager,
78
+ Expose,
79
+ ProvisionListenerBinding,
80
+ )
81
+
82
+
66
83
  class ElementCollection(lang.Final):
67
84
  def __init__(self, es: Elements) -> None:
68
85
  super().__init__()
@@ -96,28 +113,28 @@ class ElementCollection(lang.Final):
96
113
  out.setdefault(k, []).extend(e)
97
114
 
98
115
  for e in es:
99
- if isinstance(e, ScopeBinding):
116
+ if isinstance(e, _SIMPLE_KEYED_ELEMENT_TYPES):
117
+ add(e.key, e) # type: ignore[attr-defined] # noqa
118
+
119
+ elif isinstance(e, _SIMPLE_NON_KEYED_ELEMENT_TYPES):
120
+ add(None, e)
121
+
122
+ elif isinstance(e, (SetBinding, MapBinding)):
123
+ add(e.multi_key, e)
124
+
125
+ elif isinstance(e, ScopeBinding):
100
126
  add(None, e)
101
127
  sci = make_scope_impl(e.scope)
102
128
  if (sae := sci.auto_elements()) is not None:
103
129
  self._build_raw_element_multimap(sae, out)
104
130
 
105
- elif isinstance(e, (Binding, Eager, Expose)):
106
- add(e.key, e)
107
-
108
131
  elif isinstance(e, Private):
109
132
  pi = self._get_private_info(e)
110
133
  self._build_raw_element_multimap(pi.owner_elements(), out)
111
134
 
112
- elif isinstance(e, (SetBinding, MapBinding)):
113
- add(e.multi_key, e)
114
-
115
- elif isinstance(e, ProvisionListenerBinding):
116
- add(None, e)
117
-
118
135
  elif isinstance(e, Overrides):
119
- ovr = self._build_raw_element_multimap(e.ovr)
120
136
  src = self._build_raw_element_multimap(e.src)
137
+ ovr = self._build_raw_element_multimap(e.ovr)
121
138
  for k, b in src.items(): # FIXME: merge None keys?
122
139
  try:
123
140
  bs = ovr[k]
@@ -166,9 +183,8 @@ class ElementCollection(lang.Final):
166
183
 
167
184
  es_by_ty = col.multi_map_by(type, es)
168
185
 
169
- es_by_ty.pop(Eager, None)
170
- es_by_ty.pop(Expose, None)
171
- es_by_ty.pop(ProvisionListenerBinding, None)
186
+ for nb_ty in _NON_BINDING_ELEMENT_TYPES:
187
+ es_by_ty.pop(nb_ty, None)
172
188
 
173
189
  if (bs := es_by_ty.pop(Binding, None)):
174
190
  b = self._get_single_binding(k, bs) # type: ignore
@@ -176,7 +192,6 @@ class ElementCollection(lang.Final):
176
192
  p: ProviderImpl
177
193
  if isinstance(b.provider, (SetProvider, MapProvider)):
178
194
  p = make_multi_provider_impl(b.provider, es_by_ty)
179
-
180
195
  else:
181
196
  p = make_provider_impl(b.provider)
182
197
 
@@ -12,6 +12,8 @@ TODO:
12
12
  - injection listeners
13
13
  - unions - raise on ambiguous - usecase: sql.AsyncEngineLike
14
14
  - multiple live request scopes on single injector - use private injectors?
15
+ - more listeners - UnboundKeyListener
16
+ - lazy parent listener chain cache thing
15
17
  """
16
18
  import contextlib
17
19
  import functools
@@ -55,6 +57,7 @@ DEFAULT_SCOPES: list[Scope] = [
55
57
  ]
56
58
 
57
59
 
60
+ @ta.final
58
61
  class AsyncInjectorImpl(AsyncInjector, lang.Final):
59
62
  def __init__(
60
63
  self,
@@ -83,7 +86,7 @@ class AsyncInjectorImpl(AsyncInjector, lang.Final):
83
86
  )
84
87
  )
85
88
 
86
- self._cs: weakref.WeakSet[AsyncInjectorImpl] | None = None
89
+ self._cs: weakref.WeakSet[AsyncInjectorImpl] | None = None # noqa
87
90
  self._root: AsyncInjectorImpl = p._root if p is not None else self # noqa
88
91
 
89
92
  self.__cur_req: AsyncInjectorImpl._Request | None = None
@@ -76,6 +76,9 @@ def build_kwargs_target(
76
76
  skip_kwargs: ta.Iterable[str] | None = None,
77
77
  raw_optional: bool = False,
78
78
  ) -> KwargsTarget:
79
+ if isinstance(obj, KwargsTarget):
80
+ return obj
81
+
79
82
  sig = signature(obj)
80
83
  tags = _TAGS.get(obj)
81
84
 
@@ -1,5 +1,6 @@
1
1
  import typing as ta
2
2
 
3
+ from ... import check
3
4
  from ... import dataclasses as dc
4
5
  from ... import lang
5
6
  from ..elements import Element
@@ -58,6 +59,7 @@ class MapProviderImpl(ProviderImpl, lang.Final):
58
59
  def make_multi_provider_impl(p: Provider, es_by_ty: ta.MutableMapping[type, list[Element]]) -> ProviderImpl:
59
60
  if isinstance(p, SetProvider):
60
61
  sbs: ta.Iterable[SetBinding] = es_by_ty.pop(SetBinding, ()) # type: ignore
62
+ check.empty(es_by_ty)
61
63
  return SetProviderImpl([
62
64
  LinkProviderImpl(LinkProvider(sb.dst))
63
65
  for sb in sbs
@@ -65,6 +67,7 @@ def make_multi_provider_impl(p: Provider, es_by_ty: ta.MutableMapping[type, list
65
67
 
66
68
  elif isinstance(p, MapProvider):
67
69
  mbs: ta.Iterable[MapBinding] = es_by_ty.pop(MapBinding, ()) # type: ignore
70
+ check.empty(es_by_ty)
68
71
  return MapProviderImpl([
69
72
  MapProviderImpl.Entry(
70
73
  mb.map_key,
omlish/inject/inspect.py CHANGED
@@ -2,6 +2,7 @@ import typing as ta
2
2
 
3
3
  from .. import lang
4
4
  from .keys import Key
5
+ from .keys import as_key
5
6
 
6
7
 
7
8
  if ta.TYPE_CHECKING:
@@ -21,11 +22,45 @@ class Kwarg(ta.NamedTuple):
21
22
  key: Key
22
23
  has_default: bool
23
24
 
25
+ @classmethod
26
+ def of(
27
+ cls,
28
+ name: str,
29
+ key: Key,
30
+ *,
31
+ has_default: bool = False,
32
+ ) -> 'Kwarg':
33
+ return cls(
34
+ name,
35
+ key,
36
+ has_default,
37
+ )
38
+
24
39
 
25
40
  class KwargsTarget(ta.NamedTuple):
26
41
  obj: ta.Any
27
42
  kwargs: ta.Sequence[Kwarg]
28
43
 
44
+ @classmethod
45
+ def of(
46
+ cls,
47
+ obj: ta.Any,
48
+ *kws: Kwarg,
49
+ **kwargs: tuple[Key, bool] | Key | ta.Any,
50
+ ) -> 'KwargsTarget':
51
+ kw_kwargs: list[Kwarg] = []
52
+ for n, v in kwargs.items():
53
+ if isinstance(v, tuple):
54
+ kw_k, kw_hd = v
55
+ kw_kwargs.append(Kwarg.of(n, kw_k, has_default=kw_hd))
56
+ else:
57
+ kw_kwargs.append(Kwarg.of(n, as_key(v)))
58
+
59
+ return cls(
60
+ obj,
61
+ [*kws, *kw_kwargs],
62
+ )
63
+
29
64
 
30
65
  def tag(obj: T, **kwargs: ta.Any) -> T:
31
66
  return _inspect.tag(obj, **kwargs)
omlish/inject/multis.py CHANGED
@@ -1,5 +1,7 @@
1
1
  """
2
2
  TODO:
3
+ - DynamicSetBinding / DynamicMapBinding ? provider of set[T] / map[K, V] ?
4
+ - doable not guicey - too much dynamism
3
5
  - scopes
4
6
  """
5
7
  import collections.abc
@@ -94,6 +96,9 @@ class SetBinder(ElementGenerator, ta.Generic[T]):
94
96
  yield from self._sbs
95
97
 
96
98
 
99
+ set_binder = SetBinder
100
+
101
+
97
102
  #
98
103
 
99
104
 
@@ -123,3 +128,6 @@ class MapBinder(ElementGenerator, ta.Generic[K, V]):
123
128
  def __iter__(self) -> ta.Iterator[Element]:
124
129
  yield self._map_provider_binding
125
130
  yield from self._mbs
131
+
132
+
133
+ map_binder = MapBinder
@@ -14,9 +14,9 @@ from .elements import as_elements
14
14
  @dc.dataclass(frozen=True)
15
15
  @dc.extra_class_params(cache_hash=True)
16
16
  class Overrides(Element, lang.Final):
17
- ovr: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
18
17
  src: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
18
+ ovr: Elements = dc.xfield(coerce=check.of_isinstance(Elements))
19
19
 
20
20
 
21
- def override(ovr: ta.Any, *a: ta.Any) -> Element:
22
- return Overrides(as_elements(ovr), as_elements(*a))
21
+ def override(src: ta.Any, *ovr: ta.Any) -> Element:
22
+ return Overrides(as_elements(src), as_elements(*ovr))
omlish/inject/privates.py CHANGED
@@ -18,6 +18,12 @@ class Expose(Element, lang.Final):
18
18
  key: Key = dc.xfield(coerce=as_key)
19
19
 
20
20
 
21
+ expose = Expose
22
+
23
+
24
+ #
25
+
26
+
21
27
  @dc.dataclass(frozen=True)
22
28
  @dc.extra_class_params(cache_hash=True)
23
29
  class Private(Element, lang.Final):
@@ -3,6 +3,7 @@ import typing as ta
3
3
  from .. import check
4
4
  from .. import dataclasses as dc
5
5
  from .. import lang
6
+ from .inspect import KwargsTarget
6
7
  from .keys import Key
7
8
 
8
9
 
@@ -20,13 +21,13 @@ class Provider(lang.Abstract):
20
21
  @dc.dataclass(frozen=True)
21
22
  @dc.extra_class_params(cache_hash=True)
22
23
  class AsyncFnProvider(Provider):
23
- fn: ta.Any = dc.xfield(validate=callable)
24
+ fn: ta.Any = dc.xfield(validate=lambda v: callable(v) or isinstance(v, KwargsTarget))
24
25
 
25
26
 
26
27
  @dc.dataclass(frozen=True)
27
28
  @dc.extra_class_params(cache_hash=True)
28
29
  class FnProvider(Provider):
29
- fn: ta.Any = dc.xfield(validate=callable)
30
+ fn: ta.Any = dc.xfield(validate=lambda v: callable(v) or isinstance(v, KwargsTarget))
30
31
 
31
32
 
32
33
  @dc.dataclass(frozen=True)
omlish/lang/recursion.py CHANGED
@@ -13,7 +13,6 @@ P = ta.ParamSpec('P')
13
13
 
14
14
 
15
15
  _LOCK = threading.RLock()
16
-
17
16
  _LOCAL: threading.local
18
17
 
19
18
 
omlish/lite/typing.py CHANGED
@@ -12,6 +12,12 @@ A2 = ta.TypeVar('A2')
12
12
 
13
13
  ##
14
14
  # A workaround for typing deficiencies (like `Argument 2 to NewType(...) must be subclassable`).
15
+ #
16
+ # Note that this problem doesn't happen at runtime - it happens in mypy:
17
+ #
18
+ # mypy <(echo "import typing as ta; MyCallback = ta.NewType('MyCallback', ta.Callable[[], None])")
19
+ # /dev/fd/11:1:22: error: Argument 2 to NewType(...) must be subclassable (got "Callable[[], None]") [valid-newtype]
20
+ #
15
21
 
16
22
 
17
23
  @dc.dataclass(frozen=True)
omlish/reflect/types.py CHANGED
@@ -9,6 +9,7 @@ give it some guiding North Star to make all of its decisions for it, and to add
9
9
  meet, join, solve, ...), but it's quite a bit of work and not a priority at the moment.
10
10
 
11
11
  TODO:
12
+ - !!! refactor like a GuardFn - no check_only, return a closure to continue computation !!!
12
13
  - !! cache this shit !!
13
14
  - especially generic_mro shit
14
15
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev462
3
+ Version: 0.0.0.dev464
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.omlish-manifests.json,sha256=FLw7xkPiSXuImZgqSP8BwrEib2R1doSzUPLUkc-QUIA,8410
2
- omlish/__about__.py,sha256=-V3o03Hr1h9gnXTUCGAuhYuAtvBiOS6R2iHHoB5MrB8,3613
2
+ omlish/__about__.py,sha256=WyDJQ2x949KN_uTbi46dCg9PAT7MHo8ImNATkJ1mqb0,3613
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=ZNIMl1kwg3qdei4DiUrJPQe5M81S1e76N-GuNSwLBAE,8683
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -82,7 +82,7 @@ omlish/collections/unmodifiable.py,sha256=0ZkA_0paWlkgaU6OupFdSV0yFP--7XoI3lqhs3
82
82
  omlish/collections/utils.py,sha256=JYBYoConWxApqJLOjXR6GuQI76G0KQDjg6kkXrTofUw,4063
83
83
  omlish/collections/cache/__init__.py,sha256=D1gO71VcwxFTZP9gAc9isHfg_TEdalwhsJcgGLvS9hg,233
84
84
  omlish/collections/cache/descriptor.py,sha256=5SOsKNxnhisJY22l7tujMOI6MGGr6TERzgsfjvGXOyA,5013
85
- omlish/collections/cache/impl.py,sha256=6rOg7zgEn8I5GPjz1RdImB1TdbHZv6EKdv2QAUcUGug,14783
85
+ omlish/collections/cache/impl.py,sha256=Xw8V-koWqtWn9Q0qROxM33-ziUSebhWZv-fzYzkjDfQ,14794
86
86
  omlish/collections/cache/types.py,sha256=uND_qOk8bVVmdhrOhjx9QHYqs2jq53NThEqQAl3Nepw,690
87
87
  omlish/collections/kv/__init__.py,sha256=qPuE8bmbyOkT_qVGH5owSp0SbC9xI_p_LS0tP7S7QSw,751
88
88
  omlish/collections/kv/base.py,sha256=lbE5kj2rNgee8dQOlD7v5oTAn5BcgE3IYRpA11N31Dw,1077
@@ -340,36 +340,39 @@ omlish/http/coro/server/fdio.py,sha256=wd4ShtoX0Ag2xf9PiiQcZR1XLmqHukb_anp0TipNG
340
340
  omlish/http/coro/server/server.py,sha256=pB-QV70koRtFwmKmyjnriZDJtErhE6dNqTVvF7s4BVg,18433
341
341
  omlish/http/coro/server/simple.py,sha256=j1RZ3niKrgGM2qFnjdYWn_eniZzay5j49Ca4L3u8vO4,3296
342
342
  omlish/http/coro/server/sockets.py,sha256=kFZYbcTGYftvm7zpOhkZGtyX2qYdem-Gk018GVBOzeg,2285
343
- omlish/inject/__init__.py,sha256=8ik0yhn0LCdDr2UMACBeatENs76yprB8pDXUNllXRWg,2954
344
- omlish/inject/binder.py,sha256=7-Lhf39FuwtpAA57ljJ_h8fIUNCpcd10E6CJiR4Cdxc,5303
343
+ omlish/inject/__init__.py,sha256=oiHZj4WSEyTAeCk6upegNO6EwezhrNf3gvoHXZ3B1jU,3204
344
+ omlish/inject/binder.py,sha256=ET0BC-tCYVhlQK5-7KKwgRGcFFkzscPgY107TnFu7oQ,4361
345
345
  omlish/inject/bindings.py,sha256=PlvOnUREjvc6F8nOJdzl1k9SAf80icRB4qWFqDop87M,536
346
346
  omlish/inject/eagers.py,sha256=JBY7PcjXt-Rg9scQ1ol9xpcoTLXkXC_Ie9uwTWdzUkA,340
347
- omlish/inject/elements.py,sha256=y4luEO_-eOlVnLcUDiNGSyMXee4pusl46ZGr0JFhbcY,1405
347
+ omlish/inject/elements.py,sha256=I6_Jdqk265T7KegrChVTRnYrhXFE80tCr7nMxqV9xkE,1670
348
348
  omlish/inject/errors.py,sha256=_wkN2tF55gQzmMOMKJC_9jYHBZzaBiCDcyqI9Sf2UZs,626
349
349
  omlish/inject/injector.py,sha256=Lw8RLPdJYCHx2zYckttcZnAXBg_UYHe6KAeBilpz-SY,1177
350
- omlish/inject/inspect.py,sha256=Uq4KMloGWF_YS2mgZbrx-JXhZQnYHHKJSr68i9yoBVc,597
350
+ omlish/inject/inspect.py,sha256=d1IOpgPV1UCUm0uqLRa8PW-jGdfrhzaV1qLitANfCDY,1420
351
351
  omlish/inject/keys.py,sha256=7jnI2cw7cvLlzZAfe5SC50O3oPOpOB6iGZGTigyfQvs,682
352
352
  omlish/inject/listeners.py,sha256=bav7-uzfpajFAmH_snM0PW2oCfMavmhbE6R4-gjOmJ8,620
353
353
  omlish/inject/lite.py,sha256=AFOCj_SznDCPjkiVSKdFXL2hH1q2o4kaDnzkxRWDpsI,2615
354
354
  omlish/inject/managed.py,sha256=jaZiiLqHHhL5aHtryou7M15QgHvZ8rSIHveG7ka9sAw,3087
355
355
  omlish/inject/maysync.py,sha256=I_gV1efDgqi-A-wJVHAmeswzIxAI0WW_U416E7LnSBs,491
356
- omlish/inject/multis.py,sha256=Dn63jE8P5ahSKc1IDBdzzx6ByBCgVOth5t4frG9m4UA,3336
356
+ omlish/inject/multis.py,sha256=NNiHConMRmKVqs-FNrSQWIQtXVgTy2cQR59R1p_55kQ,3504
357
357
  omlish/inject/origins.py,sha256=-qXa18rIIkNwBdTrvASRDjgPYnoY6n6OPC222jJDrXg,551
358
- omlish/inject/overrides.py,sha256=ybEcq9cDf6kvqu5mqnwi6Evj0MFjKNeE3r0oUlGw5E4,546
359
- omlish/inject/privates.py,sha256=CyE-hvQ-F_uyCzcwfdiYVtfm9IF1WZvMDOYilFyZmWk,658
360
- omlish/inject/providers.py,sha256=Usvi0YgjS5jrAqQFhzeU2artxRSTM4zIoz72lac1PEA,931
358
+ omlish/inject/overrides.py,sha256=3fMHSfX4Xym2NBHP5_vTZTq2Q47SfGhoC5WnTdYOLx0,550
359
+ omlish/inject/privates.py,sha256=46ODWz3PQh6GyH2Rqd-Y7Ye1WBGr9RjSbZ4U12zAolY,680
360
+ omlish/inject/providers.py,sha256=OroBtCBvd0YqfdkLsQLGKmL3cbPngUWFfHqQYo4rYGo,1053
361
361
  omlish/inject/scopes.py,sha256=9atVF24QEn073kvoCw_4yLrkdIEzSAqqI0cSXAg4G1A,2722
362
362
  omlish/inject/sync.py,sha256=ovVoMY7X9hxe1xverBEec4la3j_041HKjNSlarGsfuA,1051
363
- omlish/inject/tags.py,sha256=gRDLa-WdZc9DC7KwwmoIPAi8g_qdGpRWuMT7HCd7CL0,433
364
363
  omlish/inject/types.py,sha256=Z-ZEdgtCpHBNrbxxKaMVvfeD7hYXdL4rC7A9_VGxZ6g,256
365
- omlish/inject/utils.py,sha256=Gc2qq45KgkyqDt03WSvOEZBCiuqQ6ESwplx5ZRBcY5M,413
364
+ omlish/inject/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
365
+ omlish/inject/helpers/constfn.py,sha256=Q7yfaGtxEb3L9izvwWSHh8udvR111qOtUYItw6OiyXo,416
366
+ omlish/inject/helpers/id.py,sha256=F1RYU03q4evteO6O3NDjwHZtPgd7MUK-qwsQAH1X-P0,435
367
+ omlish/inject/helpers/multis.py,sha256=4V85CdxxuYANAEn44IQbXHDYjPbBQ9jLrEP5XpzV2bI,3807
368
+ omlish/inject/helpers/wrappers.py,sha256=f3mulTNuItvmXnn7E4JHk9UESjsf-ponvlDfIpAHbk4,1319
366
369
  omlish/inject/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
367
370
  omlish/inject/impl/bindings.py,sha256=xSvUcoDz8NH-aNHPwBPEZsFg73K2WcF_A63npVbGt_k,420
368
- omlish/inject/impl/elements.py,sha256=BZweNf8lbG_tO5X_A8-yM2ukIwtHHVMR6nsxai95EOA,5948
369
- omlish/inject/impl/injector.py,sha256=0e8Il9ObzWMDBJDLQk9RRBkK83mk-nIRlKU_LtmQfLI,8266
370
- omlish/inject/impl/inspect.py,sha256=HLhz5DfP9dwvbIYnwqsfR9ADjCoWs9q4Gh7J4BpImf4,3135
371
+ omlish/inject/impl/elements.py,sha256=qR06KaAjZMaQgdMBE6_tdrT7cWP1Ft0CFq71bnyp224,6265
372
+ omlish/inject/impl/injector.py,sha256=tcPyq_747L12G3CT_rA9KU4l_gWlesX0uCDv3GJOZGY,8366
373
+ omlish/inject/impl/inspect.py,sha256=UcCaQEhQfRINrY9Phz9UYKCuAg7HnZTqBJ2i-6j_O1A,3193
371
374
  omlish/inject/impl/maysync.py,sha256=7GWjrvJStOx85BCvk8IJAmmkoGkChFAAi2h7j2pe6Qs,1207
372
- omlish/inject/impl/multis.py,sha256=fa31UdkBYdAulfYdrkU1klDZicuQRyaBDbG28kaw8SI,2092
375
+ omlish/inject/impl/multis.py,sha256=5aKXnmSocwqu7y6WicvYX1-QGTz9iHubxRq9j0enlgk,2174
373
376
  omlish/inject/impl/origins.py,sha256=dgGdkoMN6I4DZrWjlpZYijeFsrF6Up1WPq_QSAgTtuQ,1676
374
377
  omlish/inject/impl/privates.py,sha256=uxMAl0MOPu-MeLd-q1DySu7J5FcdRVL1B0XgC4dnB6I,2667
375
378
  omlish/inject/impl/providers.py,sha256=qqPUF9qZZ-CGTTc7ZPskjexM2aK8xdY0gLPMshB5VKw,2127
@@ -433,7 +436,7 @@ omlish/lang/objects.py,sha256=JMOZU5I6sK4rJm04898dOJkvef-lDIh5O3k6tlLbBJw,4616
433
436
  omlish/lang/outcomes.py,sha256=rCyjWjElNheJ-sQhauxfERT98IZ0mrUoaSI9nMpJZTg,8751
434
437
  omlish/lang/overrides.py,sha256=IBzK6ljfLX6TLgIyKTSjhqTLcuKRkQNVtEOnBLS4nuA,2095
435
438
  omlish/lang/params.py,sha256=sfbNoGrKCsAtubFufj_uh_WKshIgA8fqJ4PmLH1PH00,6639
436
- omlish/lang/recursion.py,sha256=1VfSqzKO-8Is3t9LKw0W4jwPfE0aBS70EUlbUxAx4eE,1900
439
+ omlish/lang/recursion.py,sha256=tfCCe4poGcyV56Wj7j9NBjm7akp828mBZegJpm-i9SU,1899
437
440
  omlish/lang/resolving.py,sha256=nMosn-rcYjI8t6b35oICDyPw6t6-HvWj5jMdkfn1jfA,1612
438
441
  omlish/lang/resources.py,sha256=awfh33Uxkd9Ho-5Z3d9CPWQE3gjktV0XWM6XbdG0ejA,2845
439
442
  omlish/lang/sequences.py,sha256=OJ5hdgjvgzOgsb0Bg8vGrwPyef4gkRPp-Bz21sc9_iE,3185
@@ -493,7 +496,7 @@ omlish/lite/strings.py,sha256=rapGrc2BrIDstAEJov3pG_30PimOIR7IFVYioyTi-MM,1831
493
496
  omlish/lite/timeouts.py,sha256=OLU9iju2pkk3niM20aPnmA6AqabFmW8zeLDu6WsuaxA,5008
494
497
  omlish/lite/timing.py,sha256=KTlEa5PyT6BXf8AwGVWUNtoVgRx9zwSUrBQnkpygK78,262
495
498
  omlish/lite/types.py,sha256=QM9whf55r7TmmQBRApIWSlyVKsl1p_jcut_YheyZMFY,146
496
- omlish/lite/typing.py,sha256=m2CyJTz2OVOCPRvp-0UuEx7oleZgXqs3rYXijE0bTsA,1280
499
+ omlish/lite/typing.py,sha256=RZBto50cqbeZrLbFtSPMmxc0gR-dnRsH02Yx4t4xosQ,1580
497
500
  omlish/lite/wrappers.py,sha256=d00Ls2kFHuogKd5wEBaU65VNCN10YXIZtiwu1mbMpmA,530
498
501
  omlish/logs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
499
502
  omlish/logs/_amalg.py,sha256=XTfwEPyxNLHgDq3rEDa5WnotoyFIxvvcAKeqOFZxBY8,204
@@ -628,7 +631,7 @@ omlish/reflect/__init__.py,sha256=omD3VLFQtYTwPxrTH6gLATQIax9sTGGKc-7ps96-q0g,12
628
631
  omlish/reflect/inspect.py,sha256=dUrVz8VfAdLVFtFpW416DxzVC17D80cvFb_g2Odzgq8,1823
629
632
  omlish/reflect/ops.py,sha256=4mGvFMw5D6XGbhDhdCqZ1dZsiqezUTenDv63FIDohpY,3029
630
633
  omlish/reflect/subst.py,sha256=_lfNS2m2UiJgqARQtmGLTGo7CrSm9OMvVzt6GWOEX6M,4590
631
- omlish/reflect/types.py,sha256=4Plo_1cHIk8-68lu8_c_SUEohy19exTNDsgvuVbOJ5A,16066
634
+ omlish/reflect/types.py,sha256=iKLnOhOfbssFp7J4TNFif6as4SyNVFRYlCv7zLQH4iU,16159
632
635
  omlish/secrets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
633
636
  omlish/secrets/all.py,sha256=qBxUFIqxCExADL71taNH_W6FYT9QvOrdcaMeUUPO3aw,298
634
637
  omlish/secrets/crypto.py,sha256=q0Hca5oMwvh39r0hrupN_ewxhlllbdDgAgVoloYFmDg,3714
@@ -828,9 +831,9 @@ omlish/typedvalues/marshal.py,sha256=2xqX6JllhtGpmeYkU7C-qzgU__0x-vd6CzYbAsocQlc
828
831
  omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
829
832
  omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
830
833
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
831
- omlish-0.0.0.dev462.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
832
- omlish-0.0.0.dev462.dist-info/METADATA,sha256=cz6Ceh1xL9eOzPJiUFmjYRw1SA220Ujydbg5IBx-ufs,19003
833
- omlish-0.0.0.dev462.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
834
- omlish-0.0.0.dev462.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
835
- omlish-0.0.0.dev462.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
836
- omlish-0.0.0.dev462.dist-info/RECORD,,
834
+ omlish-0.0.0.dev464.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
835
+ omlish-0.0.0.dev464.dist-info/METADATA,sha256=D4GGbbDDetXUn2WacG-QrL6r_ZRprtERgAiGJYpR45k,19003
836
+ omlish-0.0.0.dev464.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
837
+ omlish-0.0.0.dev464.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
838
+ omlish-0.0.0.dev464.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
839
+ omlish-0.0.0.dev464.dist-info/RECORD,,