omlish 0.0.0.dev128__py3-none-any.whl → 0.0.0.dev129__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev128'
2
- __revision__ = '032185683e360475ef780c77bea913c965cebcc6'
1
+ __version__ = '0.0.0.dev129'
2
+ __revision__ = '997d6cc6f7e56919cf06a3d284f3d64e3383fc81'
3
3
 
4
4
 
5
5
  #
omlish/lite/check.py CHANGED
@@ -57,6 +57,30 @@ def check_not_equal(l: T, r: T) -> T:
57
57
  return l
58
58
 
59
59
 
60
+ def check_is(l: T, r: T) -> T:
61
+ if l is not r:
62
+ raise ValueError(l, r)
63
+ return l
64
+
65
+
66
+ def check_is_not(l: T, r: ta.Any) -> T:
67
+ if l is r:
68
+ raise ValueError(l, r)
69
+ return l
70
+
71
+
72
+ def check_in(v: T, c: ta.Container[T]) -> T:
73
+ if v not in c:
74
+ raise ValueError(v, c)
75
+ return v
76
+
77
+
78
+ def check_not_in(v: T, c: ta.Container[T]) -> T:
79
+ if v in c:
80
+ raise ValueError(v, c)
81
+ return v
82
+
83
+
60
84
  def check_single(vs: ta.Iterable[T]) -> T:
61
85
  [v] = vs
62
86
  return v
omlish/lite/inject.py CHANGED
@@ -1,5 +1,11 @@
1
1
  # ruff: noqa: UP006 UP007
2
+ """
3
+ TODO:
4
+ - recursion detection
5
+ - bind empty array
6
+ """
2
7
  import abc
8
+ import contextlib
3
9
  import dataclasses as dc
4
10
  import functools
5
11
  import inspect
@@ -7,7 +13,9 @@ import types
7
13
  import typing as ta
8
14
  import weakref
9
15
 
16
+ from .check import check_in
10
17
  from .check import check_isinstance
18
+ from .check import check_not_in
11
19
  from .check import check_not_isinstance
12
20
  from .check import check_not_none
13
21
  from .maybes import Maybe
@@ -124,7 +132,7 @@ class InjectorError(Exception):
124
132
  pass
125
133
 
126
134
 
127
- @dc.dataclass(frozen=True)
135
+ @dc.dataclass()
128
136
  class InjectorKeyError(InjectorError):
129
137
  key: InjectorKey
130
138
 
@@ -132,16 +140,18 @@ class InjectorKeyError(InjectorError):
132
140
  name: ta.Optional[str] = None
133
141
 
134
142
 
135
- @dc.dataclass(frozen=True)
136
143
  class UnboundInjectorKeyError(InjectorKeyError):
137
144
  pass
138
145
 
139
146
 
140
- @dc.dataclass(frozen=True)
141
147
  class DuplicateInjectorKeyError(InjectorKeyError):
142
148
  pass
143
149
 
144
150
 
151
+ class CyclicDependencyInjectorKeyError(InjectorKeyError):
152
+ pass
153
+
154
+
145
155
  ###
146
156
  # keys
147
157
 
@@ -475,22 +485,65 @@ class _Injector(Injector):
475
485
  if _INJECTOR_INJECTOR_KEY in self._pfm:
476
486
  raise DuplicateInjectorKeyError(_INJECTOR_INJECTOR_KEY)
477
487
 
488
+ self.__cur_req: ta.Optional[_Injector._Request] = None
489
+
490
+ class _Request:
491
+ def __init__(self, injector: '_Injector') -> None:
492
+ super().__init__()
493
+ self._injector = injector
494
+ self._provisions: ta.Dict[InjectorKey, Maybe] = {}
495
+ self._seen_keys: ta.Set[InjectorKey] = set()
496
+
497
+ def handle_key(self, key: InjectorKey) -> Maybe[Maybe]:
498
+ try:
499
+ return Maybe.just(self._provisions[key])
500
+ except KeyError:
501
+ pass
502
+ if key in self._seen_keys:
503
+ raise CyclicDependencyInjectorKeyError(key)
504
+ self._seen_keys.add(key)
505
+ return Maybe.empty()
506
+
507
+ def handle_provision(self, key: InjectorKey, mv: Maybe) -> Maybe:
508
+ check_in(key, self._seen_keys)
509
+ check_not_in(key, self._provisions)
510
+ self._provisions[key] = mv
511
+ return mv
512
+
513
+ @contextlib.contextmanager
514
+ def _current_request(self) -> ta.Generator[_Request, None, None]:
515
+ if (cr := self.__cur_req) is not None:
516
+ yield cr
517
+ return
518
+
519
+ cr = self._Request(self)
520
+ try:
521
+ self.__cur_req = cr
522
+ yield cr
523
+ finally:
524
+ self.__cur_req = None
525
+
478
526
  def try_provide(self, key: ta.Any) -> Maybe[ta.Any]:
479
527
  key = as_injector_key(key)
480
528
 
481
- if key == _INJECTOR_INJECTOR_KEY:
482
- return Maybe.just(self)
529
+ cr: _Injector._Request
530
+ with self._current_request() as cr:
531
+ if (rv := cr.handle_key(key)).present:
532
+ return rv.must()
533
+
534
+ if key == _INJECTOR_INJECTOR_KEY:
535
+ return cr.handle_provision(key, Maybe.just(self))
483
536
 
484
- fn = self._pfm.get(key)
485
- if fn is not None:
486
- return Maybe.just(fn(self))
537
+ fn = self._pfm.get(key)
538
+ if fn is not None:
539
+ return cr.handle_provision(key, Maybe.just(fn(self)))
487
540
 
488
- if self._p is not None:
489
- pv = self._p.try_provide(key)
490
- if pv is not None:
491
- return Maybe.empty()
541
+ if self._p is not None:
542
+ pv = self._p.try_provide(key)
543
+ if pv is not None:
544
+ return cr.handle_provision(key, Maybe.empty())
492
545
 
493
- return Maybe.empty()
546
+ return cr.handle_provision(key, Maybe.empty())
494
547
 
495
548
  def provide(self, key: ta.Any) -> ta.Any:
496
549
  v = self.try_provide(key)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev128
3
+ Version: 0.0.0.dev129
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
1
  omlish/.manifests.json,sha256=CxGnj-UiRPlZgmgWoovDWrOnqpSEmBy_kqA7cdfSA3w,1431
2
- omlish/__about__.py,sha256=9lZ5XVEOu3HBl1htFmArMTPb8o6NmnVqnhMIpjv5mhc,3379
2
+ omlish/__about__.py,sha256=I7cXPq7JaH6uExuC7ADYlMyuYjPdRhADj2biay0wUN8,3379
3
3
  omlish/__init__.py,sha256=SsyiITTuK0v74XpKV8dqNaCmjOlan1JZKrHQv5rWKPA,253
4
4
  omlish/argparse.py,sha256=cqKGAqcxuxv_s62z0gq29L9KAvg_3-_rFvXKjVpRJjo,8126
5
5
  omlish/c3.py,sha256=ubu7lHwss5V4UznbejAI0qXhXahrU01MysuHOZI9C4U,8116
@@ -300,10 +300,10 @@ omlish/lifecycles/states.py,sha256=zqMOU2ZU-MDNnWuwauM3_anIAiXM8LoBDElDEraptFg,1
300
300
  omlish/lifecycles/transitions.py,sha256=qQtFby-h4VzbvgaUqT2NnbNumlcOx9FVVADP9t83xj4,1939
301
301
  omlish/lite/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
302
302
  omlish/lite/cached.py,sha256=Fs-ljXVJmHBjAaHc-JuJXMEV4MNSX5c_KHZIM3AEaIw,694
303
- omlish/lite/check.py,sha256=1mo1GK78Ro5-IC_jUrmNabmt--hz_9v1y5h28K2cqUY,1102
303
+ omlish/lite/check.py,sha256=VDCx-7OqtN7EBcAAHhlYoNyRdo8UMyUDu9K44shMkIo,1519
304
304
  omlish/lite/contextmanagers.py,sha256=_jfNdpYvxkbKwyjQLbK-o69W89GoEuUfl_NrCosE9lU,1308
305
305
  omlish/lite/docker.py,sha256=3IVZZtIm7-UdB2SwArmN_MosTva1_KifyYp3YWjODbE,337
306
- omlish/lite/inject.py,sha256=NTZl6VXhYDILPMm1zBx-CbqF7Vkpxv9w1JVKqmmUp5w,20407
306
+ omlish/lite/inject.py,sha256=QXIEL920axG66kbt-fsLQDVy8kHcBT-2AHgc7qiCkKc,22108
307
307
  omlish/lite/io.py,sha256=lcpI1cS_Kn90tvYMg8ZWkSlYloS4RFqXCk-rKyclhdg,3148
308
308
  omlish/lite/journald.py,sha256=f5Y2Q6-6O3iK_7MoGiwZwoQEOcP7LfkxxQNUR9tMjJM,3882
309
309
  omlish/lite/json.py,sha256=7-02Ny4fq-6YAu5ynvqoijhuYXWpLmfCI19GUeZnb1c,740
@@ -482,9 +482,9 @@ omlish/text/glyphsplit.py,sha256=Ug-dPRO7x-OrNNr8g1y6DotSZ2KH0S-VcOmUobwa4B0,329
482
482
  omlish/text/indent.py,sha256=6Jj6TFY9unaPa4xPzrnZemJ-fHsV53IamP93XGjSUHs,1274
483
483
  omlish/text/parts.py,sha256=7vPF1aTZdvLVYJ4EwBZVzRSy8XB3YqPd7JwEnNGGAOo,6495
484
484
  omlish/text/random.py,sha256=jNWpqiaKjKyTdMXC-pWAsSC10AAP-cmRRPVhm59ZWLk,194
485
- omlish-0.0.0.dev128.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
486
- omlish-0.0.0.dev128.dist-info/METADATA,sha256=lgogkc74fPcQs_ct8BCBruFkyE5sDH9QPyrnz90DRQE,4173
487
- omlish-0.0.0.dev128.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
488
- omlish-0.0.0.dev128.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
489
- omlish-0.0.0.dev128.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
490
- omlish-0.0.0.dev128.dist-info/RECORD,,
485
+ omlish-0.0.0.dev129.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
486
+ omlish-0.0.0.dev129.dist-info/METADATA,sha256=lebYC_UeiQKZPCZWcsShqqR6HJUpAcDQ7U4Bk941WF8,4173
487
+ omlish-0.0.0.dev129.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
488
+ omlish-0.0.0.dev129.dist-info/entry_points.txt,sha256=Lt84WvRZJskWCAS7xnQGZIeVWksprtUHj0llrvVmod8,35
489
+ omlish-0.0.0.dev129.dist-info/top_level.txt,sha256=pePsKdLu7DvtUiecdYXJ78iO80uDNmBlqe-8hOzOmfs,7
490
+ omlish-0.0.0.dev129.dist-info/RECORD,,