omlish 0.0.0.dev407__py3-none-any.whl → 0.0.0.dev409__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.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev407'
2
- __revision__ = '069daca807ba62f298b1fef1de82247d29c345c0'
1
+ __version__ = '0.0.0.dev409'
2
+ __revision__ = '9ee675d7bba914e838f5f8ce55dc0af32638a52c'
3
3
 
4
4
 
5
5
  #
omlish/inject/lite.py ADDED
@@ -0,0 +1,112 @@
1
+ """
2
+ TODO:
3
+ - explicit blacklisted key element - blacklist lite Injector
4
+ """
5
+ import dataclasses as dc
6
+ import typing as ta
7
+
8
+ from .. import check
9
+ from .. import reflect as rfl
10
+ from ..lite import inject as lij
11
+ from .bindings import Binding
12
+ from .elements import Elements
13
+ from .keys import Key
14
+ from .providers import ConstProvider
15
+ from .providers import CtorProvider
16
+ from .providers import FnProvider
17
+ from .providers import LinkProvider
18
+ from .providers import Provider
19
+ from .scopes import Singleton
20
+ from .types import Scope
21
+ from .types import Unscoped
22
+
23
+
24
+ ##
25
+
26
+
27
+ @dc.dataclass(frozen=True)
28
+ class BoxedLiteProvider:
29
+ p: Provider
30
+ sc: Scope | None = None
31
+
32
+
33
+ ##
34
+
35
+
36
+ @ta.overload
37
+ def convert_from_lite(o: lij.InjectorBindings) -> Elements:
38
+ ...
39
+
40
+
41
+ @ta.overload
42
+ def convert_from_lite(o: lij.InjectorKey) -> Key:
43
+ ...
44
+
45
+
46
+ @ta.overload
47
+ def convert_from_lite(o: lij.InjectorBinding) -> Binding:
48
+ ...
49
+
50
+
51
+ @ta.overload
52
+ def convert_from_lite(o: lij.InjectorProvider) -> BoxedLiteProvider:
53
+ ...
54
+
55
+
56
+ def convert_from_lite(o):
57
+ if isinstance(o, lij.InjectorBindings):
58
+ return Elements([
59
+ convert_from_lite(c)
60
+ for c in o.bindings()
61
+ ])
62
+
63
+ elif isinstance(o, lij.InjectorKey):
64
+ check.not_equal(o.cls_, lij.InjectorKeyCls)
65
+ check.arg(not o.array)
66
+ return Key(rfl.type_(o.cls_), tag=o.tag)
67
+
68
+ elif isinstance(o, lij.InjectorBinding):
69
+ blp = convert_from_lite(o.provider)
70
+ return Binding(
71
+ convert_from_lite(o.key),
72
+ blp.p,
73
+ blp.sc if blp.sc is not None else Unscoped(),
74
+ )
75
+
76
+ elif isinstance(o, lij.InjectorProvider):
77
+ if isinstance(o, lij.FnInjectorProvider):
78
+ return BoxedLiteProvider(FnProvider(
79
+ o.fn,
80
+ ))
81
+
82
+ elif isinstance(o, lij.CtorInjectorProvider):
83
+ return BoxedLiteProvider(CtorProvider(
84
+ o.cls_,
85
+ ))
86
+
87
+ elif isinstance(o, lij.ConstInjectorProvider):
88
+ return BoxedLiteProvider(ConstProvider(
89
+ o.v,
90
+ ))
91
+
92
+ elif isinstance(o, lij.SingletonInjectorProvider):
93
+ blp = convert_from_lite(o.p)
94
+ check.none(blp.sc)
95
+ return dc.replace(
96
+ blp,
97
+ sc=Singleton(),
98
+ )
99
+
100
+ elif isinstance(o, lij.LinkInjectorProvider):
101
+ return BoxedLiteProvider(LinkProvider(
102
+ convert_from_lite(o.k),
103
+ ))
104
+
105
+ elif isinstance(o, lij.ScopedInjectorProvider):
106
+ raise NotImplementedError
107
+
108
+ else:
109
+ raise TypeError(o)
110
+
111
+ else:
112
+ raise TypeError(o)
omlish/lang/__init__.py CHANGED
@@ -237,7 +237,7 @@ from .imports.proxyinit import ( # noqa
237
237
  auto_proxy_init,
238
238
  )
239
239
 
240
- from .imports.resolution import ( # noqa
240
+ from .imports.resolving import ( # noqa
241
241
  can_import,
242
242
  get_real_module_name,
243
243
  resolve_import_name,
@@ -1,6 +1,6 @@
1
1
  import sys
2
2
 
3
- from .resolution import resolve_import_name
3
+ from .resolving import resolve_import_name
4
4
 
5
5
 
6
6
  ##
@@ -62,5 +62,5 @@ def proxy_import(
62
62
  return getattr(omod, att)
63
63
 
64
64
  lmod = types.ModuleType(name)
65
- lmod.__getattr__ = __getattr__ # type: ignore
65
+ lmod.__getattr__ = __getattr__ # type: ignore[method-assign]
66
66
  return lmod
@@ -1,10 +1,3 @@
1
- """
2
- TODO:
3
- - auto_proxy_init can capture `import as` by scanning globals for sentinels
4
- - replaces _AutoProxyInitCapture._attrs dict outright
5
- - should raise on unbound or shadowed import - was probably imported for side-effects but will never get
6
- proxy imported
7
- """
8
1
  import builtins
9
2
  import contextlib
10
3
  import functools
@@ -18,12 +11,11 @@ from ..lazyglobals import LazyGlobals
18
11
  ##
19
12
 
20
13
 
21
- class NamePackage(ta.NamedTuple):
22
- name: str
23
- package: str
24
-
25
-
26
14
  class _ProxyInit:
15
+ class NamePackage(ta.NamedTuple):
16
+ name: str
17
+ package: str
18
+
27
19
  class _Import(ta.NamedTuple):
28
20
  pkg: str
29
21
  attr: str | None
@@ -48,26 +40,16 @@ class _ProxyInit:
48
40
  def add(
49
41
  self,
50
42
  package: str,
51
- attrs: ta.Iterable[str | tuple[str, str]] | None = None,
43
+ attrs: ta.Iterable[tuple[str | None, str]],
52
44
  ) -> None:
53
- if isinstance(attrs, str):
54
- raise TypeError(attrs)
55
-
56
- if attrs is None:
57
- whole_attr = package.split('.')[-1]
45
+ for imp_attr, as_attr in attrs:
46
+ if imp_attr is None:
47
+ self._imps_by_attr[as_attr] = self._Import(package, None)
48
+ self._lazy_globals.set_fn(as_attr, functools.partial(self.get, as_attr))
58
49
 
59
- self._imps_by_attr[whole_attr] = self._Import(package, None)
60
- self._lazy_globals.set_fn(whole_attr, functools.partial(self.get, whole_attr))
61
-
62
- else:
63
- for attr in attrs:
64
- if isinstance(attr, tuple):
65
- imp_attr, attr = attr
66
- else:
67
- imp_attr = attr
68
-
69
- self._imps_by_attr[attr] = self._Import(package, imp_attr)
70
- self._lazy_globals.set_fn(attr, functools.partial(self.get, attr))
50
+ else:
51
+ self._imps_by_attr[as_attr] = self._Import(package, imp_attr)
52
+ self._lazy_globals.set_fn(as_attr, functools.partial(self.get, as_attr))
71
53
 
72
54
  def _import_module(self, name: str) -> ta.Any:
73
55
  return importlib.import_module(name, package=self._name_package.package)
@@ -98,12 +80,38 @@ class _ProxyInit:
98
80
  def proxy_init(
99
81
  init_globals: ta.MutableMapping[str, ta.Any],
100
82
  package: str,
101
- attrs: ta.Iterable[str | tuple[str, str]] | None = None,
83
+ attrs: ta.Iterable[str | tuple[str | None, str | None] | None] | None = None,
102
84
  ) -> None:
103
85
  if isinstance(attrs, str):
104
86
  raise TypeError(attrs)
105
87
 
106
- init_name_package = NamePackage(
88
+ if attrs is None:
89
+ attrs = [None]
90
+
91
+ whole_attr = package.split('.')[-1]
92
+ al: list[tuple[str | None, str]] = []
93
+ for attr in attrs:
94
+ if attr is None:
95
+ al.append((None, whole_attr))
96
+
97
+ elif isinstance(attr, str):
98
+ al.append((attr, attr))
99
+
100
+ elif isinstance(attr, tuple):
101
+ imp_attr, as_attr = attr
102
+ if as_attr is None:
103
+ if imp_attr is None:
104
+ as_attr = whole_attr
105
+ else:
106
+ as_attr = imp_attr
107
+ al.append((imp_attr, as_attr))
108
+
109
+ else:
110
+ raise TypeError(attr)
111
+
112
+ #
113
+
114
+ init_name_package = _ProxyInit.NamePackage(
107
115
  init_globals['__name__'],
108
116
  init_globals['__package__'],
109
117
  )
@@ -123,7 +131,7 @@ def proxy_init(
123
131
  if pi.name_package != init_name_package:
124
132
  raise Exception(f'Wrong init name: {pi.name_package=} != {init_name_package=}')
125
133
 
126
- pi.add(package, attrs)
134
+ pi.add(package, al)
127
135
 
128
136
 
129
137
  ##
@@ -166,6 +174,15 @@ class AutoProxyInitErrors:
166
174
  class UnproxiedImportForbiddenError(ImportError):
167
175
  pass
168
176
 
177
+ class UnreferencedImportsError(AutoProxyInitError):
178
+ def __init__(self, unreferenced: ta.Mapping[str, ta.Sequence[str | None]]) -> None:
179
+ super().__init__()
180
+
181
+ self.unreferenced = unreferenced
182
+
183
+ def __repr__(self) -> str:
184
+ return f'{self.__class__.__qualname__}(unreferenced={self.unreferenced!r})'
185
+
169
186
 
170
187
  class _AutoProxyInitCapture:
171
188
  class ModuleSpec(ta.NamedTuple):
@@ -178,8 +195,22 @@ class _AutoProxyInitCapture:
178
195
  def __repr__(self) -> str:
179
196
  return repr(str(self))
180
197
 
198
+ def __init__(self) -> None:
199
+ super().__init__()
200
+
201
+ self._modules_by_spec: dict[_AutoProxyInitCapture.ModuleSpec, _AutoProxyInitCapture._Module] = {}
202
+ self._modules_by_module_obj: dict[types.ModuleType, _AutoProxyInitCapture._Module] = {}
203
+
204
+ self._attrs: dict[_AutoProxyInitCapture._ModuleAttr, tuple[_AutoProxyInitCapture._Module, str]] = {}
205
+
206
+ #
207
+
181
208
  class _ModuleAttr:
182
- def __init__(self, module: '_AutoProxyInitCapture._Module', name: str) -> None:
209
+ def __init__(
210
+ self,
211
+ module: '_AutoProxyInitCapture._Module',
212
+ name: str,
213
+ ) -> None:
183
214
  super().__init__()
184
215
 
185
216
  self.__module = module
@@ -189,24 +220,62 @@ class _AutoProxyInitCapture:
189
220
  return f'<{self.__class__.__name__}: {f"{self.__module.spec}:{self.__name}"!r}>'
190
221
 
191
222
  class _Module:
192
- def __init__(self, spec: '_AutoProxyInitCapture.ModuleSpec') -> None:
223
+ def __init__(
224
+ self,
225
+ spec: '_AutoProxyInitCapture.ModuleSpec',
226
+ *,
227
+ getattr_handler: ta.Callable[['_AutoProxyInitCapture._Module', str], ta.Any] | None = None,
228
+ ) -> None:
193
229
  super().__init__()
194
230
 
195
231
  self.spec = spec
196
232
 
197
- self.module = types.ModuleType(f'<{self.__class__.__qualname__}: {spec!r}>')
233
+ self.module_obj = types.ModuleType(f'<{self.__class__.__qualname__}: {spec!r}>')
234
+ if getattr_handler is not None:
235
+ self.module_obj.__getattr__ = functools.partial(getattr_handler, self) # type: ignore[method-assign] # noqa
236
+ self.initial_module_dict = dict(self.module_obj.__dict__)
198
237
 
199
- self.attrs: dict[str, _AutoProxyInitCapture._ModuleAttr] = {}
238
+ self.contents: dict[str, _AutoProxyInitCapture._ModuleAttr | types.ModuleType] = {}
200
239
  self.imported_whole = False
201
240
 
202
241
  def __repr__(self) -> str:
203
242
  return f'{self.__class__.__name__}({self.spec!r})'
204
243
 
205
- def __init__(self) -> None:
206
- super().__init__()
244
+ def _get_or_make_module(self, spec: ModuleSpec) -> _Module:
245
+ try:
246
+ return self._modules_by_spec[spec]
247
+ except KeyError:
248
+ pass
207
249
 
208
- self._modules: dict[_AutoProxyInitCapture.ModuleSpec, _AutoProxyInitCapture._Module] = {}
209
- self._attrs: dict[str, _AutoProxyInitCapture._ModuleAttr | _AutoProxyInitCapture._Module] = {}
250
+ module = self._Module(
251
+ spec,
252
+ getattr_handler=self._handle_module_getattr,
253
+ )
254
+ self._modules_by_spec[spec] = module
255
+ self._modules_by_module_obj[module.module_obj] = module
256
+ return module
257
+
258
+ def _handle_module_getattr(self, module: _Module, attr: str) -> ta.Any:
259
+ if attr in module.contents:
260
+ raise AutoProxyInitErrors.AttrError(str(module.spec), attr)
261
+
262
+ v: _AutoProxyInitCapture._ModuleAttr | types.ModuleType
263
+ if not module.spec.name:
264
+ if not module.spec.level:
265
+ raise AutoProxyInitError
266
+ cs = _AutoProxyInitCapture.ModuleSpec(attr, module.spec.level)
267
+ cm = self._get_or_make_module(cs)
268
+ cm.imported_whole = True
269
+ v = cm.module_obj
270
+
271
+ else:
272
+ ma = _AutoProxyInitCapture._ModuleAttr(module, attr)
273
+ self._attrs[ma] = (module, attr)
274
+ v = ma
275
+
276
+ module.contents[attr] = v
277
+ setattr(module.module_obj, attr, v)
278
+ return v
210
279
 
211
280
  def _handle_import(
212
281
  self,
@@ -218,23 +287,6 @@ class _AutoProxyInitCapture:
218
287
  if module.spec.level or not module.spec.name:
219
288
  raise AutoProxyInitError
220
289
 
221
- attr = module.spec.name
222
-
223
- try:
224
- xma: ta.Any = self._attrs[attr]
225
- except KeyError:
226
- pass
227
-
228
- else:
229
- if (
230
- xma is not self._attrs.get(attr) or
231
- not module.imported_whole
232
- ):
233
- raise AutoProxyInitErrors.AttrError(str(module.spec), attr)
234
-
235
- return
236
-
237
- self._attrs[attr] = module
238
290
  module.imported_whole = True
239
291
 
240
292
  else:
@@ -242,27 +294,23 @@ class _AutoProxyInitCapture:
242
294
  if attr == '*':
243
295
  raise AutoProxyInitErrors.ImportStarForbiddenError(str(module.spec), from_list)
244
296
 
245
- try:
246
- xma = getattr(module.module, attr)
247
- except AttributeError:
248
- pass
249
-
297
+ x = getattr(module.module_obj, attr)
298
+
299
+ bad = False
300
+ if x is not module.contents.get(attr):
301
+ bad = True
302
+ if isinstance(x, _AutoProxyInitCapture._ModuleAttr):
303
+ if self._attrs[x] != (module, attr):
304
+ bad = True
305
+ elif isinstance(x, types.ModuleType):
306
+ if x not in self._modules_by_module_obj:
307
+ bad = True
250
308
  else:
251
- if (
252
- xma is not module.attrs.get(attr) or
253
- xma is not self._attrs.get(attr)
254
- ):
255
- raise AutoProxyInitErrors.AttrError(str(module.spec), attr)
256
-
257
- continue
258
-
259
- if attr in self._attrs:
309
+ bad = True
310
+ if bad:
260
311
  raise AutoProxyInitErrors.AttrError(str(module.spec), attr)
261
312
 
262
- ma = _AutoProxyInitCapture._ModuleAttr(module, attr)
263
- self._attrs[attr] = ma
264
- module.attrs[attr] = ma
265
- setattr(module.module, attr, ma)
313
+ #
266
314
 
267
315
  _MOD_SELF_ATTR: ta.ClassVar[str] = '__auto_proxy_init_capture__'
268
316
 
@@ -281,18 +329,14 @@ class _AutoProxyInitCapture:
281
329
  return None
282
330
 
283
331
  spec = _AutoProxyInitCapture.ModuleSpec(name, level)
284
- try:
285
- module = self._modules[spec]
286
- except KeyError:
287
- module = self._Module(spec)
288
- self._modules[spec] = module
332
+ module = self._get_or_make_module(spec)
289
333
 
290
334
  self._handle_import(
291
335
  module,
292
336
  from_list=from_list,
293
337
  )
294
338
 
295
- return module.module
339
+ return module.module_obj
296
340
 
297
341
  @contextlib.contextmanager
298
342
  def hook_context(
@@ -353,54 +397,103 @@ class _AutoProxyInitCapture:
353
397
  del init_globals[self._MOD_SELF_ATTR]
354
398
  builtins.__import__ = old_import
355
399
 
356
- def verify_globals(
400
+ #
401
+
402
+ def verify_state(
357
403
  self,
358
404
  init_globals: ta.MutableMapping[str, ta.Any], # noqa
359
405
  ) -> None:
360
- for attr, obj in self._attrs.items():
361
- try:
362
- xo = init_globals[attr]
363
- except KeyError:
364
- raise AutoProxyInitErrors.AttrError(None, attr) from None
406
+ for m in self._modules_by_spec.values():
407
+ for a, o in m.module_obj.__dict__.items():
408
+ try:
409
+ i = m.initial_module_dict[a]
365
410
 
366
- if isinstance(obj, _AutoProxyInitCapture._ModuleAttr):
367
- if xo is not obj:
368
- raise AutoProxyInitErrors.AttrError(None, attr) from None
411
+ except KeyError:
412
+ if o is not m.contents[a]:
413
+ raise AutoProxyInitErrors.AttrError(str(m.spec), a) from None
369
414
 
370
- elif isinstance(obj, _AutoProxyInitCapture._Module):
371
- if xo is not obj.module:
372
- raise AutoProxyInitErrors.AttrError(None, attr) from None
415
+ else:
416
+ if o != i:
417
+ raise AutoProxyInitErrors.AttrError(str(m.spec), a)
373
418
 
374
- else:
375
- raise TypeError(obj)
376
-
377
- @property
378
- def all_attrs(self) -> ta.AbstractSet[str]:
379
- return self._attrs.keys()
419
+ #
380
420
 
381
421
  class ProxyInit(ta.NamedTuple):
382
422
  package: str
383
- attrs: ta.Sequence[str] | None
423
+ attrs: ta.Sequence[tuple[str | None, str]]
384
424
 
385
- def build_proxy_inits(self) -> list[ProxyInit]:
386
- lst: list[_AutoProxyInitCapture.ProxyInit] = []
425
+ class BuiltProxyInits(ta.NamedTuple):
426
+ proxy_inits: ta.Sequence['_AutoProxyInitCapture.ProxyInit']
427
+ unreferenced: ta.Mapping[str, ta.Sequence[str | None]] | None
387
428
 
388
- for module in self._modules.values():
389
- if module.imported_whole:
390
- lst.append(_AutoProxyInitCapture.ProxyInit(str(module.spec), None))
429
+ def build_proxy_inits(
430
+ self,
431
+ init_globals: ta.MutableMapping[str, ta.Any], # noqa
432
+ *,
433
+ collect_unreferenced: bool = False,
434
+ ) -> BuiltProxyInits:
435
+ dct: dict[_AutoProxyInitCapture._Module, list[tuple[str | None, str]]] = {}
391
436
 
392
- if module.attrs:
393
- if not module.spec.name:
394
- for attr in module.attrs:
395
- if not module.spec.level:
396
- raise AutoProxyInitError
437
+ rem_whole_mods: set[_AutoProxyInitCapture._Module] = set()
438
+ rem_mod_attrs: set[_AutoProxyInitCapture._ModuleAttr] = set()
439
+ if collect_unreferenced:
440
+ rem_whole_mods.update([m for m in self._modules_by_spec.values() if m.imported_whole])
441
+ rem_mod_attrs.update(self._attrs)
397
442
 
398
- lst.append(_AutoProxyInitCapture.ProxyInit('.' * module.spec.level + attr, None))
443
+ for attr, obj in init_globals.items():
444
+ if isinstance(obj, _AutoProxyInitCapture._ModuleAttr):
445
+ try:
446
+ m, a = self._attrs[obj]
447
+ except KeyError:
448
+ raise AutoProxyInitErrors.AttrError(None, attr) from None
449
+ dct.setdefault(m, []).append((a, attr))
450
+ rem_mod_attrs.discard(obj)
399
451
 
400
- else:
401
- lst.append(_AutoProxyInitCapture.ProxyInit(str(module.spec), list(module.attrs)))
452
+ elif isinstance(obj, _AutoProxyInitCapture._Module):
453
+ raise AutoProxyInitErrors.AttrError(None, attr) from None
402
454
 
403
- return lst
455
+ elif isinstance(obj, types.ModuleType):
456
+ try:
457
+ m = self._modules_by_module_obj[obj]
458
+ except KeyError:
459
+ continue
460
+ if not m.imported_whole:
461
+ raise RuntimeError(f'AutoProxyInit module {m.spec!r} not imported_whole')
462
+ dct.setdefault(m, []).append((None, attr))
463
+ rem_whole_mods.discard(m)
464
+
465
+ lst: list[_AutoProxyInitCapture.ProxyInit] = []
466
+ for m, ts in dct.items():
467
+ if not m.spec.name:
468
+ if not m.spec.level:
469
+ raise AutoProxyInitError
470
+ for imp_attr, as_attr in ts:
471
+ if not imp_attr:
472
+ raise RuntimeError
473
+ lst.append(_AutoProxyInitCapture.ProxyInit(
474
+ '.' * m.spec.level + imp_attr,
475
+ [(None, as_attr)],
476
+ ))
477
+
478
+ else:
479
+ lst.append(_AutoProxyInitCapture.ProxyInit(
480
+ str(m.spec),
481
+ ts,
482
+ ))
483
+
484
+ unreferenced: dict[str, list[str | None]] | None = None
485
+ if collect_unreferenced and (rem_whole_mods or rem_mod_attrs):
486
+ unreferenced = {}
487
+ for m in rem_whole_mods:
488
+ unreferenced.setdefault(str(m.spec), []).append(None)
489
+ for ma in rem_mod_attrs:
490
+ m, a = self._attrs[ma]
491
+ unreferenced.setdefault(str(m.spec), []).append(a)
492
+
493
+ return _AutoProxyInitCapture.BuiltProxyInits(
494
+ lst,
495
+ unreferenced,
496
+ )
404
497
 
405
498
 
406
499
  @contextlib.contextmanager
@@ -409,6 +502,9 @@ def auto_proxy_init(
409
502
  *,
410
503
  disable: bool = False,
411
504
  eager: bool = False,
505
+
506
+ unreferenced_callback: ta.Callable[[ta.Mapping[str, ta.Sequence[str | None]]], None] | None = None,
507
+ raise_unreferenced: bool = False,
412
508
  ) -> ta.Iterator[None]:
413
509
  """
414
510
  This is a bit extreme - use sparingly. It relies on an interpreter-global import lock, but much of the ecosystem
@@ -425,14 +521,23 @@ def auto_proxy_init(
425
521
  with cap.hook_context(init_globals):
426
522
  yield
427
523
 
428
- cap.verify_globals(init_globals)
524
+ cap.verify_state(init_globals)
429
525
 
430
- pis = cap.build_proxy_inits()
526
+ blt = cap.build_proxy_inits(
527
+ init_globals,
528
+ collect_unreferenced=unreferenced_callback is not None or raise_unreferenced,
529
+ )
431
530
 
432
- for attr in cap.all_attrs:
433
- del init_globals[attr]
531
+ if blt.unreferenced:
532
+ if unreferenced_callback:
533
+ unreferenced_callback(blt.unreferenced)
534
+ if raise_unreferenced:
535
+ raise AutoProxyInitErrors.UnreferencedImportsError(blt.unreferenced)
536
+
537
+ for pi in blt.proxy_inits:
538
+ for _, a in pi.attrs:
539
+ del init_globals[a]
434
540
 
435
- for pi in pis:
436
541
  proxy_init(
437
542
  init_globals,
438
543
  pi.package,
@@ -441,5 +546,7 @@ def auto_proxy_init(
441
546
 
442
547
  if eager:
443
548
  lg = LazyGlobals.install(init_globals)
444
- for attr in cap.all_attrs:
445
- lg.get(attr)
549
+
550
+ for pi in blt.proxy_inits:
551
+ for _, a in pi.attrs:
552
+ lg.get(a)
omlish/lite/inject.py CHANGED
@@ -19,6 +19,7 @@ from .reflect import is_optional_alias
19
19
  T = ta.TypeVar('T')
20
20
  U = ta.TypeVar('U')
21
21
 
22
+
22
23
  InjectorKeyCls = ta.Union[type, ta.NewType]
23
24
 
24
25
  InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
@@ -209,6 +209,7 @@ class ManifestLoader:
209
209
  @classmethod
210
210
  def _discover_packages_uncached(cls) -> ta.Sequence[str]:
211
211
  from importlib import metadata as importlib_metadata # noqa
212
+
212
213
  return [
213
214
  ep.value
214
215
  for ep in importlib_metadata.entry_points(group=cls.ENTRY_POINT_GROUP)
@@ -262,35 +263,31 @@ class ManifestLoader:
262
263
 
263
264
  ##
264
265
 
265
- _detected_packages: ta.Set[str]
266
-
267
- def _do_initialize(self) -> None:
268
- self._detected_packages = set()
266
+ def _detect_packages_uncached(self) -> ta.AbstractSet[str]:
267
+ ret: ta.Set[str] = set()
269
268
 
270
269
  for r in self._config.package_scan_root_dirs or []:
271
- self._detected_packages.update(self._scan_package_root_dir_locked(r))
270
+ ret.update(self._scan_package_root_dir_locked(r))
272
271
 
273
272
  if self._config.discover_packages:
274
- self._detected_packages.update(dps := self.discover_packages())
273
+ ret.update(dps := self.discover_packages())
275
274
  if not dps:
276
275
  for r in self._config.discover_packages_fallback_scan_root_dirs or []:
277
- self._detected_packages.update(self._scan_package_root_dir_locked(r))
276
+ ret.update(self._scan_package_root_dir_locked(r))
278
277
 
279
- _has_initialized = False
278
+ return ret
280
279
 
281
- def _initialize_locked(self) -> None:
282
- if not self._has_initialized:
283
- self._do_initialize()
284
- self._has_initialized = True
280
+ _detected_packages: ta.Optional[ta.AbstractSet[str]] = None
285
281
 
286
- def has_initialized(self) -> bool:
287
- with self._lock:
288
- return self._has_initialized
282
+ def _detect_packages_locked(self) -> ta.AbstractSet[str]:
283
+ if self._detected_packages is None:
284
+ self._detected_packages = self._detect_packages_uncached()
289
285
 
290
- def initialize(self) -> None:
291
- if not self._has_initialized:
292
- with self._lock:
293
- self._initialize_locked()
286
+ return self._detected_packages
287
+
288
+ def detect_packages(self) -> ta.AbstractSet[str]:
289
+ with self._lock:
290
+ return self._detect_packages_locked()
294
291
 
295
292
  ##
296
293
 
@@ -429,6 +426,7 @@ class ManifestLoader:
429
426
  return f.read()
430
427
 
431
428
  from importlib import resources as importlib_resources # noqa
429
+
432
430
  t = importlib_resources.files(package_name).joinpath(file_name)
433
431
  if not t.is_file():
434
432
  return None
@@ -497,7 +495,7 @@ class ManifestLoader:
497
495
 
498
496
  ##
499
497
 
500
- def _load_initialized(
498
+ def _load_locked(
501
499
  self,
502
500
  *,
503
501
  packages: ta.Optional[ta.Collection[str]] = None,
@@ -511,7 +509,7 @@ class ManifestLoader:
511
509
  class_keys = {self.get_class_key(cls) for cls in classes}
512
510
 
513
511
  if packages is None:
514
- packages = self._detected_packages
512
+ packages = self._detect_packages_locked()
515
513
 
516
514
  lst: ta.List[ManifestLoader.LoadedManifest] = []
517
515
  for pn in packages:
@@ -527,18 +525,6 @@ class ManifestLoader:
527
525
 
528
526
  return lst
529
527
 
530
- def _load_locked(
531
- self,
532
- *,
533
- packages: ta.Optional[ta.Collection[str]] = None,
534
- classes: ta.Optional[ta.Collection[type]] = None,
535
- ) -> ta.Sequence[LoadedManifest]:
536
- self._initialize_locked()
537
- return self._load_initialized(
538
- packages=packages,
539
- classes=classes,
540
- )
541
-
542
528
  def load(
543
529
  self,
544
530
  *,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev407
3
+ Version: 0.0.0.dev409
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License-Expression: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=FLw7xkPiSXuImZgqSP8BwrEib2R1doSzUPLUkc-QUIA,8410
2
- omlish/__about__.py,sha256=O8Q9qajIb2jh65cp6pHJd0NZKoPAJTNlKXkbL_Ozf_4,3601
2
+ omlish/__about__.py,sha256=4QkSZDk0KGwNDUXL28RW4dosDTkKwvPxAM7iBzddM4g,3601
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/c3.py,sha256=rer-TPOFDU6fYq_AWio_AmA-ckZ8JDY5shIzQ_yXfzA,8414
5
5
  omlish/cached.py,sha256=MLap_p0rdGoDIMVhXVHm1tsbcWobJF0OanoodV03Ju8,542
@@ -370,6 +370,7 @@ omlish/inject/injector.py,sha256=fyvaRoJXo_oibx1_IiGkncP9oXnZSKtDm7-ULNKRXHE,107
370
370
  omlish/inject/inspect.py,sha256=Uq4KMloGWF_YS2mgZbrx-JXhZQnYHHKJSr68i9yoBVc,597
371
371
  omlish/inject/keys.py,sha256=7jnI2cw7cvLlzZAfe5SC50O3oPOpOB6iGZGTigyfQvs,682
372
372
  omlish/inject/listeners.py,sha256=Ffaun2fVWAgAwKgLdgziJynG_jhAWaaPEsy-2I2Cmpw,599
373
+ omlish/inject/lite.py,sha256=AFOCj_SznDCPjkiVSKdFXL2hH1q2o4kaDnzkxRWDpsI,2615
373
374
  omlish/inject/managed.py,sha256=-9aBm1vRPOjNz4kgOmpt8S2T55s727t9RiggFBH8maU,2096
374
375
  omlish/inject/multis.py,sha256=Dn63jE8P5ahSKc1IDBdzzx6ByBCgVOth5t4frG9m4UA,3336
375
376
  omlish/inject/origins.py,sha256=-qXa18rIIkNwBdTrvASRDjgPYnoY6n6OPC222jJDrXg,551
@@ -425,7 +426,7 @@ omlish/iterators/iterators.py,sha256=RxW35yQ5ed8vBQ22IqpDXFx-i5JiLQdp7-pkMZXhJJ8
425
426
  omlish/iterators/recipes.py,sha256=wOwOZg-zWG9Zc3wcAxJFSe2rtavVBYwZOfG09qYEx_4,472
426
427
  omlish/iterators/tools.py,sha256=M16LXrJhMdsz5ea2qH0vws30ZvhQuQSCVFSLpRf_gTg,2096
427
428
  omlish/iterators/unique.py,sha256=BSE-eanva8byFCJi09Nt2zzTsVr8LnTqY1PIInGYRs0,1396
428
- omlish/lang/__init__.py,sha256=le8N_Hj6ahtWnG6-gGEo53CK270rDA9wuhh6rUDS9ws,7232
429
+ omlish/lang/__init__.py,sha256=7Xe1YcE2PPgx-NI-V9VTsvUl4qZD0RPANxuDv9ddRXg,7231
429
430
  omlish/lang/attrs.py,sha256=zFiVuGVOq88x45464T_LxDa-ZEq_RD9zJLq2zeVEBDc,5105
430
431
  omlish/lang/casing.py,sha256=cFUlbDdXLhwnWwcYx4qnM5c4zGX7hIRUfcjiZbxUD28,4636
431
432
  omlish/lang/clsdct.py,sha256=HAGIvBSbCefzRjXriwYSBLO7QHKRv2UsE78jixOb-fA,1828
@@ -463,10 +464,10 @@ omlish/lang/classes/restrict.py,sha256=CUyvLpMYiQwTjpzo5sdG_lQxdeEIq2z2xSVNrsI9K
463
464
  omlish/lang/classes/simple.py,sha256=9blmJdi4c15zyIEbNVjkA0ZTSImQbv4g0p2Il6knWAc,2539
464
465
  omlish/lang/classes/virtual.py,sha256=z0MYQD9Q5MkX8DzF325wDB4J9XoYbsB09jZ1omC62To,3366
465
466
  omlish/lang/imports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
466
- omlish/lang/imports/conditional.py,sha256=qxHYlE_xuwPJb6F9K8upagHxuYL0APPLWRVo5079Ipg,1007
467
- omlish/lang/imports/lazy.py,sha256=gDv7ffrGsPEAHZ9a1Myt7Uf-4vqWErhCd1DaS7SQL0c,1464
468
- omlish/lang/imports/proxyinit.py,sha256=prcQSZYdXSvZLsWZClNSOhIJVHNMuO8nD9NTtG-fFv4,12636
469
- omlish/lang/imports/resolution.py,sha256=DeRarn35Fryg5JhVhy8wbiC9lvr58AnllI9B_reswUE,2085
467
+ omlish/lang/imports/conditional.py,sha256=R-E47QD95mMonPImWlrde3rnJrFKCCkYz71c94W05sc,1006
468
+ omlish/lang/imports/lazy.py,sha256=Fhtb5tSAttff6G2pZdF8bh__GZlqJWHaMKtA8KubuX4,1479
469
+ omlish/lang/imports/proxyinit.py,sha256=ALpV9LahE8SQl6jNO92Mk4PcaQPce9Cv53K8AwnH5fQ,16749
470
+ omlish/lang/imports/resolving.py,sha256=DeRarn35Fryg5JhVhy8wbiC9lvr58AnllI9B_reswUE,2085
470
471
  omlish/lang/imports/traversal.py,sha256=pbFQIa880NGjSfcLsno2vE_G41_CLwDHb-7gWg2J3BI,2855
471
472
  omlish/lifecycles/__init__.py,sha256=1FjYceXs-4fc-S-C9zFYmc2axHs4znnQHcJVHdY7a6E,578
472
473
  omlish/lifecycles/abstract.py,sha256=c9UY7oxzYZ_neh5DPE4yv5HfuDv7B4Mj_9Zo-B8KDSs,1114
@@ -484,7 +485,7 @@ omlish/lite/configs.py,sha256=4-1uVxo-aNV7vMKa7PVNhM610eejG1WepB42-Dw2xQI,914
484
485
  omlish/lite/contextmanagers.py,sha256=QEqVxUtmr9aJJ_03A-YC4vVUy8jkiIDCYIGIOlXvn8U,5827
485
486
  omlish/lite/dataclasses.py,sha256=aRSCZz1jN_UI-CWJhN0SJeKxa-79vXNUZ6YOMgG31SE,3610
486
487
  omlish/lite/imports.py,sha256=GyEDKL-WuHtdOKIL-cc8aFd0-bHwZFDEjAB52ItabX0,1341
487
- omlish/lite/inject.py,sha256=WC5uazLkxAF5QB2dq6qgrhKXkRwkANqO2oGD0G6C_k8,29021
488
+ omlish/lite/inject.py,sha256=SJt0KjvzMz3vBswYhVbiA0cQqxzZO7HmsGvdtjkwgg4,29022
488
489
  omlish/lite/json.py,sha256=m0Ce9eqUZG23-H7-oOp8n1sf4fzno5vtK4AK_4Vc-Mg,706
489
490
  omlish/lite/logs.py,sha256=CWFG0NKGhqNeEgryF5atN2gkPYbUdTINEw_s1phbINM,51
490
491
  omlish/lite/marshal.py,sha256=K_wnZwfC8cftGILyE3RlmzQEYuZOfzkMLKey41zuwtM,20296
@@ -519,7 +520,7 @@ omlish/logs/utils.py,sha256=OkFWf1exmWImmT7BaSiIC7c0Fk9tAis-PRqo8H4ny3c,398
519
520
  omlish/manifests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
520
521
  omlish/manifests/base.py,sha256=Dt44a3qppWaxkoi3naFFMetxbxw14qnz2naTKK93GNU,915
521
522
  omlish/manifests/globals.py,sha256=kVqQ-fT4kc7xWzLHoI731GviitFPv2v2yqw-p7t7Exs,2628
522
- omlish/manifests/loading.py,sha256=guLx-3y4rqQ2YIgTtqlpCk59inePtcEUE19JrWDzleM,17639
523
+ omlish/manifests/loading.py,sha256=Br1OyI23pis_FfYju9xoacms608lzB1Zh_IqdVw_7vg,17201
523
524
  omlish/manifests/static.py,sha256=9BaPBLkuzxHmg5A-5k9BjjBFINCdmFOIu06dMFgCfz4,497
524
525
  omlish/manifests/types.py,sha256=NeOGuIVrcbqjCDbQ3MnCxxHAgHnw0CkWJsBzo230PWE,453
525
526
  omlish/marshal/.dataclasses.json,sha256=wXWUy_IR8AolAa2RQnqn_mo2QnmVcvUJmayIykdVl0I,22
@@ -908,9 +909,9 @@ omlish/typedvalues/marshal.py,sha256=AtBz7Jq-BfW8vwM7HSxSpR85JAXmxK2T0xDblmm1HI0
908
909
  omlish/typedvalues/of_.py,sha256=UXkxSj504WI2UrFlqdZJbu2hyDwBhL7XVrc2qdR02GQ,1309
909
910
  omlish/typedvalues/reflect.py,sha256=PAvKW6T4cW7u--iX80w3HWwZUS3SmIZ2_lQjT65uAyk,1026
910
911
  omlish/typedvalues/values.py,sha256=ym46I-q2QJ_6l4UlERqv3yj87R-kp8nCKMRph0xQ3UA,1307
911
- omlish-0.0.0.dev407.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
912
- omlish-0.0.0.dev407.dist-info/METADATA,sha256=zAQhPHsAgpSKxDHdzuCl9iDtCb-tRFEYeRuMln15HoE,18881
913
- omlish-0.0.0.dev407.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
914
- omlish-0.0.0.dev407.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
915
- omlish-0.0.0.dev407.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
916
- omlish-0.0.0.dev407.dist-info/RECORD,,
912
+ omlish-0.0.0.dev409.dist-info/licenses/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
913
+ omlish-0.0.0.dev409.dist-info/METADATA,sha256=fCzoIaINPTeVtCOvdUmzuUWQqKIGW40xgEmeKO4bIxg,18881
914
+ omlish-0.0.0.dev409.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
915
+ omlish-0.0.0.dev409.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
916
+ omlish-0.0.0.dev409.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
917
+ omlish-0.0.0.dev409.dist-info/RECORD,,
File without changes