ominfra 0.0.0.dev177__py3-none-any.whl → 0.0.0.dev178__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- ominfra/manage/deploy/commands.py +4 -3
- ominfra/manage/deploy/deploy.py +1 -51
- ominfra/manage/deploy/driver.py +71 -0
- ominfra/manage/deploy/inject.py +29 -0
- ominfra/scripts/manage.py +280 -43
- ominfra/scripts/supervisor.py +205 -11
- {ominfra-0.0.0.dev177.dist-info → ominfra-0.0.0.dev178.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev177.dist-info → ominfra-0.0.0.dev178.dist-info}/RECORD +12 -11
- {ominfra-0.0.0.dev177.dist-info → ominfra-0.0.0.dev178.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev177.dist-info → ominfra-0.0.0.dev178.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev177.dist-info → ominfra-0.0.0.dev178.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev177.dist-info → ominfra-0.0.0.dev178.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,7 @@ from omlish.lite.logs import log
|
|
5
5
|
|
6
6
|
from ..commands.base import Command
|
7
7
|
from ..commands.base import CommandExecutor
|
8
|
-
from .
|
8
|
+
from .driver import DeployDriverFactory
|
9
9
|
from .specs import DeploySpec
|
10
10
|
|
11
11
|
|
@@ -23,11 +23,12 @@ class DeployCommand(Command['DeployCommand.Output']):
|
|
23
23
|
|
24
24
|
@dc.dataclass(frozen=True)
|
25
25
|
class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
|
26
|
-
|
26
|
+
_driver_factory: DeployDriverFactory
|
27
27
|
|
28
28
|
async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
|
29
29
|
log.info('Deploying! %r', cmd.spec)
|
30
30
|
|
31
|
-
|
31
|
+
with self._driver_factory(cmd.spec) as driver:
|
32
|
+
await driver.drive_deploy()
|
32
33
|
|
33
34
|
return DeployCommand.Output()
|
ominfra/manage/deploy/deploy.py
CHANGED
@@ -1,18 +1,10 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
import datetime
|
3
|
-
import os.path
|
4
3
|
import typing as ta
|
5
4
|
|
6
|
-
from omlish.lite.check import check
|
7
5
|
from omlish.lite.typing import Func0
|
8
6
|
|
9
|
-
from .apps import DeployAppManager
|
10
|
-
from .paths.manager import DeployPathsManager
|
11
|
-
from .specs import DeploySpec
|
12
|
-
from .tags import DeployAppRev
|
13
|
-
from .tags import DeployTagMap
|
14
7
|
from .tags import DeployTime
|
15
|
-
from .types import DeployHome
|
16
8
|
|
17
9
|
|
18
10
|
DEPLOY_TAG_DATETIME_FMT = '%Y%m%dT%H%M%SZ'
|
@@ -25,16 +17,11 @@ class DeployManager:
|
|
25
17
|
def __init__(
|
26
18
|
self,
|
27
19
|
*,
|
28
|
-
apps: DeployAppManager,
|
29
|
-
paths: DeployPathsManager,
|
30
20
|
|
31
21
|
utc_clock: ta.Optional[DeployManagerUtcClock] = None,
|
32
22
|
):
|
33
23
|
super().__init__()
|
34
24
|
|
35
|
-
self._apps = apps
|
36
|
-
self._paths = paths
|
37
|
-
|
38
25
|
self._utc_clock = utc_clock
|
39
26
|
|
40
27
|
def _utc_now(self) -> datetime.datetime:
|
@@ -43,42 +30,5 @@ class DeployManager:
|
|
43
30
|
else:
|
44
31
|
return datetime.datetime.now(tz=datetime.timezone.utc) # noqa
|
45
32
|
|
46
|
-
def
|
33
|
+
def make_deploy_time(self) -> DeployTime:
|
47
34
|
return DeployTime(self._utc_now().strftime(DEPLOY_TAG_DATETIME_FMT))
|
48
|
-
|
49
|
-
async def run_deploy(
|
50
|
-
self,
|
51
|
-
spec: DeploySpec,
|
52
|
-
) -> None:
|
53
|
-
self._paths.validate_deploy_paths()
|
54
|
-
|
55
|
-
#
|
56
|
-
|
57
|
-
hs = check.non_empty_str(spec.home)
|
58
|
-
hs = os.path.expanduser(hs)
|
59
|
-
hs = os.path.realpath(hs)
|
60
|
-
hs = os.path.abspath(hs)
|
61
|
-
|
62
|
-
home = DeployHome(hs)
|
63
|
-
|
64
|
-
#
|
65
|
-
|
66
|
-
deploy_tags = DeployTagMap(
|
67
|
-
self._make_deploy_time(),
|
68
|
-
spec.key(),
|
69
|
-
)
|
70
|
-
|
71
|
-
#
|
72
|
-
|
73
|
-
for app in spec.apps:
|
74
|
-
app_tags = deploy_tags.add(
|
75
|
-
app.app,
|
76
|
-
app.key(),
|
77
|
-
DeployAppRev(app.git.rev),
|
78
|
-
)
|
79
|
-
|
80
|
-
await self._apps.prepare_app(
|
81
|
-
app,
|
82
|
-
home,
|
83
|
-
app_tags,
|
84
|
-
)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
import os.path
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
from omlish.lite.check import check
|
6
|
+
from omlish.lite.typing import Func1
|
7
|
+
|
8
|
+
from .apps import DeployAppManager
|
9
|
+
from .deploy import DeployManager
|
10
|
+
from .paths.manager import DeployPathsManager
|
11
|
+
from .specs import DeploySpec
|
12
|
+
from .tags import DeployAppRev
|
13
|
+
from .tags import DeployTagMap
|
14
|
+
from .types import DeployHome
|
15
|
+
|
16
|
+
|
17
|
+
class DeployDriverFactory(Func1[DeploySpec, ta.ContextManager['DeployDriver']]):
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
class DeployDriver:
|
22
|
+
def __init__(
|
23
|
+
self,
|
24
|
+
*,
|
25
|
+
spec: DeploySpec,
|
26
|
+
|
27
|
+
deploys: DeployManager,
|
28
|
+
paths: DeployPathsManager,
|
29
|
+
apps: DeployAppManager,
|
30
|
+
) -> None:
|
31
|
+
super().__init__()
|
32
|
+
|
33
|
+
self._spec = spec
|
34
|
+
|
35
|
+
self._deploys = deploys
|
36
|
+
self._paths = paths
|
37
|
+
self._apps = apps
|
38
|
+
|
39
|
+
async def drive_deploy(self) -> None:
|
40
|
+
self._paths.validate_deploy_paths()
|
41
|
+
|
42
|
+
#
|
43
|
+
|
44
|
+
hs = check.non_empty_str(self._spec.home)
|
45
|
+
hs = os.path.expanduser(hs)
|
46
|
+
hs = os.path.realpath(hs)
|
47
|
+
hs = os.path.abspath(hs)
|
48
|
+
|
49
|
+
home = DeployHome(hs)
|
50
|
+
|
51
|
+
#
|
52
|
+
|
53
|
+
deploy_tags = DeployTagMap(
|
54
|
+
self._deploys.make_deploy_time(),
|
55
|
+
self._spec.key(),
|
56
|
+
)
|
57
|
+
|
58
|
+
#
|
59
|
+
|
60
|
+
for app in self._spec.apps:
|
61
|
+
app_tags = deploy_tags.add(
|
62
|
+
app.app,
|
63
|
+
app.key(),
|
64
|
+
DeployAppRev(app.git.rev),
|
65
|
+
)
|
66
|
+
|
67
|
+
await self._apps.prepare_app(
|
68
|
+
app,
|
69
|
+
home,
|
70
|
+
app_tags,
|
71
|
+
)
|
ominfra/manage/deploy/inject.py
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
|
+
import contextlib
|
2
3
|
import typing as ta
|
3
4
|
|
5
|
+
from omlish.lite.inject import ContextvarInjectorScope
|
6
|
+
from omlish.lite.inject import Injector
|
4
7
|
from omlish.lite.inject import InjectorBindingOrBindings
|
5
8
|
from omlish.lite.inject import InjectorBindings
|
6
9
|
from omlish.lite.inject import inj
|
@@ -12,16 +15,23 @@ from .commands import DeployCommandExecutor
|
|
12
15
|
from .conf import DeployConfManager
|
13
16
|
from .config import DeployConfig
|
14
17
|
from .deploy import DeployManager
|
18
|
+
from .driver import DeployDriver
|
19
|
+
from .driver import DeployDriverFactory
|
15
20
|
from .git import DeployGitManager
|
16
21
|
from .interp import InterpCommand
|
17
22
|
from .interp import InterpCommandExecutor
|
18
23
|
from .paths.inject import bind_deploy_paths
|
19
24
|
from .paths.owners import DeployPathOwner
|
25
|
+
from .specs import DeploySpec
|
20
26
|
from .tmp import DeployHomeAtomics
|
21
27
|
from .tmp import DeployTmpManager
|
22
28
|
from .venvs import DeployVenvManager
|
23
29
|
|
24
30
|
|
31
|
+
class DeployInjectorScope(ContextvarInjectorScope):
|
32
|
+
pass
|
33
|
+
|
34
|
+
|
25
35
|
def bind_deploy(
|
26
36
|
*,
|
27
37
|
deploy_config: DeployConfig,
|
@@ -65,6 +75,25 @@ def bind_deploy(
|
|
65
75
|
|
66
76
|
#
|
67
77
|
|
78
|
+
def provide_deploy_driver_factory(injector: Injector, sc: DeployInjectorScope) -> DeployDriverFactory:
|
79
|
+
@contextlib.contextmanager
|
80
|
+
def factory(spec: DeploySpec) -> ta.Iterator[DeployDriver]:
|
81
|
+
with sc.enter({
|
82
|
+
inj.as_key(DeploySpec): spec,
|
83
|
+
}):
|
84
|
+
yield injector[DeployDriver]
|
85
|
+
return DeployDriverFactory(factory)
|
86
|
+
lst.append(inj.bind(provide_deploy_driver_factory, singleton=True))
|
87
|
+
|
88
|
+
lst.extend([
|
89
|
+
inj.bind_scope(DeployInjectorScope),
|
90
|
+
inj.bind_scope_seed(DeploySpec, DeployInjectorScope),
|
91
|
+
|
92
|
+
inj.bind(DeployDriver, in_=DeployInjectorScope),
|
93
|
+
])
|
94
|
+
|
95
|
+
#
|
96
|
+
|
68
97
|
lst.extend([
|
69
98
|
bind_command(DeployCommand, DeployCommandExecutor),
|
70
99
|
bind_command(InterpCommand, InterpCommandExecutor),
|
ominfra/scripts/manage.py
CHANGED
@@ -17,6 +17,7 @@ import base64
|
|
17
17
|
import collections
|
18
18
|
import collections.abc
|
19
19
|
import contextlib
|
20
|
+
import contextvars
|
20
21
|
import ctypes as ct
|
21
22
|
import dataclasses as dc
|
22
23
|
import datetime
|
@@ -4905,6 +4906,10 @@ class InjectorBinding:
|
|
4905
4906
|
key: InjectorKey
|
4906
4907
|
provider: InjectorProvider
|
4907
4908
|
|
4909
|
+
def __post_init__(self) -> None:
|
4910
|
+
check.isinstance(self.key, InjectorKey)
|
4911
|
+
check.isinstance(self.provider, InjectorProvider)
|
4912
|
+
|
4908
4913
|
|
4909
4914
|
class InjectorBindings(abc.ABC):
|
4910
4915
|
@abc.abstractmethod
|
@@ -5168,6 +5173,164 @@ def build_injector_provider_map(bs: InjectorBindings) -> ta.Mapping[InjectorKey,
|
|
5168
5173
|
return pm
|
5169
5174
|
|
5170
5175
|
|
5176
|
+
###
|
5177
|
+
# scopes
|
5178
|
+
|
5179
|
+
|
5180
|
+
class InjectorScope(abc.ABC): # noqa
|
5181
|
+
def __init__(
|
5182
|
+
self,
|
5183
|
+
*,
|
5184
|
+
_i: Injector,
|
5185
|
+
) -> None:
|
5186
|
+
check.not_in(abc.ABC, type(self).__bases__)
|
5187
|
+
|
5188
|
+
super().__init__()
|
5189
|
+
|
5190
|
+
self._i = _i
|
5191
|
+
|
5192
|
+
all_seeds: ta.Iterable[_InjectorScopeSeed] = self._i.provide(InjectorKey(_InjectorScopeSeed, array=True))
|
5193
|
+
self._sks = {s.k for s in all_seeds if s.sc is type(self)}
|
5194
|
+
|
5195
|
+
#
|
5196
|
+
|
5197
|
+
@dc.dataclass(frozen=True)
|
5198
|
+
class State:
|
5199
|
+
seeds: ta.Dict[InjectorKey, ta.Any]
|
5200
|
+
prvs: ta.Dict[InjectorKey, ta.Any] = dc.field(default_factory=dict)
|
5201
|
+
|
5202
|
+
def new_state(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> State:
|
5203
|
+
vs = dict(vs)
|
5204
|
+
check.equal(set(vs.keys()), self._sks)
|
5205
|
+
return InjectorScope.State(vs)
|
5206
|
+
|
5207
|
+
#
|
5208
|
+
|
5209
|
+
@abc.abstractmethod
|
5210
|
+
def state(self) -> State:
|
5211
|
+
raise NotImplementedError
|
5212
|
+
|
5213
|
+
@abc.abstractmethod
|
5214
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.ContextManager[None]:
|
5215
|
+
raise NotImplementedError
|
5216
|
+
|
5217
|
+
|
5218
|
+
class ExclusiveInjectorScope(InjectorScope, abc.ABC):
|
5219
|
+
_st: ta.Optional[InjectorScope.State] = None
|
5220
|
+
|
5221
|
+
def state(self) -> InjectorScope.State:
|
5222
|
+
return check.not_none(self._st)
|
5223
|
+
|
5224
|
+
@contextlib.contextmanager
|
5225
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.Iterator[None]:
|
5226
|
+
check.none(self._st)
|
5227
|
+
self._st = self.new_state(vs)
|
5228
|
+
try:
|
5229
|
+
yield
|
5230
|
+
finally:
|
5231
|
+
self._st = None
|
5232
|
+
|
5233
|
+
|
5234
|
+
class ContextvarInjectorScope(InjectorScope, abc.ABC):
|
5235
|
+
_cv: contextvars.ContextVar
|
5236
|
+
|
5237
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
5238
|
+
super().__init_subclass__(**kwargs)
|
5239
|
+
check.not_in(abc.ABC, cls.__bases__)
|
5240
|
+
check.state(not hasattr(cls, '_cv'))
|
5241
|
+
cls._cv = contextvars.ContextVar(f'{cls.__name__}_cv')
|
5242
|
+
|
5243
|
+
def state(self) -> InjectorScope.State:
|
5244
|
+
return self._cv.get()
|
5245
|
+
|
5246
|
+
@contextlib.contextmanager
|
5247
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.Iterator[None]:
|
5248
|
+
try:
|
5249
|
+
self._cv.get()
|
5250
|
+
except LookupError:
|
5251
|
+
pass
|
5252
|
+
else:
|
5253
|
+
raise RuntimeError(f'Scope already entered: {self}')
|
5254
|
+
st = self.new_state(vs)
|
5255
|
+
tok = self._cv.set(st)
|
5256
|
+
try:
|
5257
|
+
yield
|
5258
|
+
finally:
|
5259
|
+
self._cv.reset(tok)
|
5260
|
+
|
5261
|
+
|
5262
|
+
#
|
5263
|
+
|
5264
|
+
|
5265
|
+
@dc.dataclass(frozen=True)
|
5266
|
+
class ScopedInjectorProvider(InjectorProvider):
|
5267
|
+
p: InjectorProvider
|
5268
|
+
k: InjectorKey
|
5269
|
+
sc: ta.Type[InjectorScope]
|
5270
|
+
|
5271
|
+
def __post_init__(self) -> None:
|
5272
|
+
check.isinstance(self.p, InjectorProvider)
|
5273
|
+
check.isinstance(self.k, InjectorKey)
|
5274
|
+
check.issubclass(self.sc, InjectorScope)
|
5275
|
+
|
5276
|
+
def provider_fn(self) -> InjectorProviderFn:
|
5277
|
+
def pfn(i: Injector) -> ta.Any:
|
5278
|
+
st = i[self.sc].state()
|
5279
|
+
try:
|
5280
|
+
return st.prvs[self.k]
|
5281
|
+
except KeyError:
|
5282
|
+
pass
|
5283
|
+
v = ufn(i)
|
5284
|
+
st.prvs[self.k] = v
|
5285
|
+
return v
|
5286
|
+
|
5287
|
+
ufn = self.p.provider_fn()
|
5288
|
+
return pfn
|
5289
|
+
|
5290
|
+
|
5291
|
+
@dc.dataclass(frozen=True)
|
5292
|
+
class _ScopeSeedInjectorProvider(InjectorProvider):
|
5293
|
+
k: InjectorKey
|
5294
|
+
sc: ta.Type[InjectorScope]
|
5295
|
+
|
5296
|
+
def __post_init__(self) -> None:
|
5297
|
+
check.isinstance(self.k, InjectorKey)
|
5298
|
+
check.issubclass(self.sc, InjectorScope)
|
5299
|
+
|
5300
|
+
def provider_fn(self) -> InjectorProviderFn:
|
5301
|
+
def pfn(i: Injector) -> ta.Any:
|
5302
|
+
st = i[self.sc].state()
|
5303
|
+
return st.seeds[self.k]
|
5304
|
+
return pfn
|
5305
|
+
|
5306
|
+
|
5307
|
+
def bind_injector_scope(sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5308
|
+
return as_injector_bindings(
|
5309
|
+
InjectorBinder.bind(sc, singleton=True),
|
5310
|
+
)
|
5311
|
+
|
5312
|
+
|
5313
|
+
#
|
5314
|
+
|
5315
|
+
|
5316
|
+
@dc.dataclass(frozen=True)
|
5317
|
+
class _InjectorScopeSeed:
|
5318
|
+
sc: ta.Type['InjectorScope']
|
5319
|
+
k: InjectorKey
|
5320
|
+
|
5321
|
+
def __post_init__(self) -> None:
|
5322
|
+
check.issubclass(self.sc, InjectorScope)
|
5323
|
+
check.isinstance(self.k, InjectorKey)
|
5324
|
+
|
5325
|
+
|
5326
|
+
def bind_injector_scope_seed(k: ta.Any, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5327
|
+
kk = as_injector_key(k)
|
5328
|
+
return as_injector_bindings(
|
5329
|
+
InjectorBinding(kk, _ScopeSeedInjectorProvider(kk, sc)),
|
5330
|
+
InjectorBinder.bind(_InjectorScopeSeed(sc, kk), array=True),
|
5331
|
+
)
|
5332
|
+
|
5333
|
+
|
5171
5334
|
###
|
5172
5335
|
# inspection
|
5173
5336
|
|
@@ -5312,13 +5475,21 @@ _INJECTOR_EAGER_ARRAY_KEY: InjectorKey[_InjectorEager] = InjectorKey(_InjectorEa
|
|
5312
5475
|
|
5313
5476
|
|
5314
5477
|
class _Injector(Injector):
|
5478
|
+
_DEFAULT_BINDINGS: ta.ClassVar[ta.List[InjectorBinding]] = []
|
5479
|
+
|
5315
5480
|
def __init__(self, bs: InjectorBindings, p: ta.Optional[Injector] = None) -> None:
|
5316
5481
|
super().__init__()
|
5317
5482
|
|
5318
5483
|
self._bs = check.isinstance(bs, InjectorBindings)
|
5319
5484
|
self._p: ta.Optional[Injector] = check.isinstance(p, (Injector, type(None)))
|
5320
5485
|
|
5321
|
-
self._pfm = {
|
5486
|
+
self._pfm = {
|
5487
|
+
k: v.provider_fn()
|
5488
|
+
for k, v in build_injector_provider_map(as_injector_bindings(
|
5489
|
+
*self._DEFAULT_BINDINGS,
|
5490
|
+
bs,
|
5491
|
+
)).items()
|
5492
|
+
}
|
5322
5493
|
|
5323
5494
|
if _INJECTOR_INJECTOR_KEY in self._pfm:
|
5324
5495
|
raise DuplicateInjectorKeyError(_INJECTOR_INJECTOR_KEY)
|
@@ -5485,6 +5656,7 @@ class InjectorBinder:
|
|
5485
5656
|
to_const: ta.Any = None,
|
5486
5657
|
to_key: ta.Any = None,
|
5487
5658
|
|
5659
|
+
in_: ta.Optional[ta.Type[InjectorScope]] = None,
|
5488
5660
|
singleton: bool = False,
|
5489
5661
|
|
5490
5662
|
eager: bool = False,
|
@@ -5494,12 +5666,12 @@ class InjectorBinder:
|
|
5494
5666
|
if isinstance(obj, cls._BANNED_BIND_TYPES):
|
5495
5667
|
raise TypeError(obj)
|
5496
5668
|
|
5497
|
-
|
5669
|
+
#
|
5498
5670
|
|
5499
5671
|
if key is not None:
|
5500
5672
|
key = as_injector_key(key)
|
5501
5673
|
|
5502
|
-
|
5674
|
+
#
|
5503
5675
|
|
5504
5676
|
has_to = (
|
5505
5677
|
to_fn is not None or
|
@@ -5529,7 +5701,7 @@ class InjectorBinder:
|
|
5529
5701
|
key = InjectorKey(type(obj))
|
5530
5702
|
del has_to
|
5531
5703
|
|
5532
|
-
|
5704
|
+
#
|
5533
5705
|
|
5534
5706
|
if tag is not None:
|
5535
5707
|
if key.tag is not None:
|
@@ -5539,7 +5711,7 @@ class InjectorBinder:
|
|
5539
5711
|
if array is not None:
|
5540
5712
|
key = dc.replace(key, array=array)
|
5541
5713
|
|
5542
|
-
|
5714
|
+
#
|
5543
5715
|
|
5544
5716
|
providers: ta.List[InjectorProvider] = []
|
5545
5717
|
if to_fn is not None:
|
@@ -5554,23 +5726,34 @@ class InjectorBinder:
|
|
5554
5726
|
raise TypeError('Must specify provider')
|
5555
5727
|
if len(providers) > 1:
|
5556
5728
|
raise TypeError('May not specify multiple providers')
|
5557
|
-
provider
|
5729
|
+
provider = check.single(providers)
|
5558
5730
|
|
5559
|
-
|
5731
|
+
#
|
5560
5732
|
|
5733
|
+
pws: ta.List[ta.Any] = []
|
5734
|
+
if in_ is not None:
|
5735
|
+
check.issubclass(in_, InjectorScope)
|
5736
|
+
check.not_in(abc.ABC, in_.__bases__)
|
5737
|
+
pws.append(functools.partial(ScopedInjectorProvider, k=key, sc=in_))
|
5561
5738
|
if singleton:
|
5562
|
-
|
5739
|
+
pws.append(SingletonInjectorProvider)
|
5740
|
+
if len(pws) > 1:
|
5741
|
+
raise TypeError('May not specify multiple provider wrappers')
|
5742
|
+
elif pws:
|
5743
|
+
provider = check.single(pws)(provider)
|
5744
|
+
|
5745
|
+
#
|
5563
5746
|
|
5564
5747
|
binding = InjectorBinding(key, provider)
|
5565
5748
|
|
5566
|
-
|
5749
|
+
#
|
5567
5750
|
|
5568
5751
|
extras: ta.List[InjectorBinding] = []
|
5569
5752
|
|
5570
5753
|
if eager:
|
5571
5754
|
extras.append(bind_injector_eager_key(key))
|
5572
5755
|
|
5573
|
-
|
5756
|
+
#
|
5574
5757
|
|
5575
5758
|
if extras:
|
5576
5759
|
return as_injector_bindings(binding, *extras)
|
@@ -5643,7 +5826,8 @@ def bind_injector_eager_key(key: ta.Any) -> InjectorBinding:
|
|
5643
5826
|
return InjectorBinding(_INJECTOR_EAGER_ARRAY_KEY, ConstInjectorProvider(_InjectorEager(as_injector_key(key))))
|
5644
5827
|
|
5645
5828
|
|
5646
|
-
|
5829
|
+
###
|
5830
|
+
# api
|
5647
5831
|
|
5648
5832
|
|
5649
5833
|
class InjectionApi:
|
@@ -5666,6 +5850,14 @@ class InjectionApi:
|
|
5666
5850
|
def override(self, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
|
5667
5851
|
return injector_override(p, *args)
|
5668
5852
|
|
5853
|
+
# scopes
|
5854
|
+
|
5855
|
+
def bind_scope(self, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5856
|
+
return bind_injector_scope(sc)
|
5857
|
+
|
5858
|
+
def bind_scope_seed(self, k: ta.Any, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5859
|
+
return bind_injector_scope_seed(k, sc)
|
5860
|
+
|
5669
5861
|
# injector
|
5670
5862
|
|
5671
5863
|
def create_injector(self, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
|
@@ -5686,6 +5878,7 @@ class InjectionApi:
|
|
5686
5878
|
to_const: ta.Any = None,
|
5687
5879
|
to_key: ta.Any = None,
|
5688
5880
|
|
5881
|
+
in_: ta.Optional[ta.Type[InjectorScope]] = None,
|
5689
5882
|
singleton: bool = False,
|
5690
5883
|
|
5691
5884
|
eager: bool = False,
|
@@ -5702,6 +5895,7 @@ class InjectionApi:
|
|
5702
5895
|
to_const=to_const,
|
5703
5896
|
to_key=to_key,
|
5704
5897
|
|
5898
|
+
in_=in_,
|
5705
5899
|
singleton=singleton,
|
5706
5900
|
|
5707
5901
|
eager=eager,
|
@@ -7547,6 +7741,37 @@ class LocalCommandExecutor(CommandExecutor):
|
|
7547
7741
|
return await ce.execute(cmd)
|
7548
7742
|
|
7549
7743
|
|
7744
|
+
########################################
|
7745
|
+
# ../deploy/deploy.py
|
7746
|
+
|
7747
|
+
|
7748
|
+
DEPLOY_TAG_DATETIME_FMT = '%Y%m%dT%H%M%SZ'
|
7749
|
+
|
7750
|
+
|
7751
|
+
DeployManagerUtcClock = ta.NewType('DeployManagerUtcClock', Func0[datetime.datetime])
|
7752
|
+
|
7753
|
+
|
7754
|
+
class DeployManager:
|
7755
|
+
def __init__(
|
7756
|
+
self,
|
7757
|
+
*,
|
7758
|
+
|
7759
|
+
utc_clock: ta.Optional[DeployManagerUtcClock] = None,
|
7760
|
+
):
|
7761
|
+
super().__init__()
|
7762
|
+
|
7763
|
+
self._utc_clock = utc_clock
|
7764
|
+
|
7765
|
+
def _utc_now(self) -> datetime.datetime:
|
7766
|
+
if self._utc_clock is not None:
|
7767
|
+
return self._utc_clock() # noqa
|
7768
|
+
else:
|
7769
|
+
return datetime.datetime.now(tz=datetime.timezone.utc) # noqa
|
7770
|
+
|
7771
|
+
def make_deploy_time(self) -> DeployTime:
|
7772
|
+
return DeployTime(self._utc_now().strftime(DEPLOY_TAG_DATETIME_FMT))
|
7773
|
+
|
7774
|
+
|
7550
7775
|
########################################
|
7551
7776
|
# ../deploy/paths/paths.py
|
7552
7777
|
"""
|
@@ -10929,49 +11154,37 @@ class DeployAppManager(DeployPathOwner):
|
|
10929
11154
|
|
10930
11155
|
|
10931
11156
|
########################################
|
10932
|
-
# ../deploy/
|
11157
|
+
# ../deploy/driver.py
|
10933
11158
|
|
10934
11159
|
|
10935
|
-
|
10936
|
-
|
10937
|
-
|
10938
|
-
DeployManagerUtcClock = ta.NewType('DeployManagerUtcClock', Func0[datetime.datetime])
|
11160
|
+
class DeployDriverFactory(Func1[DeploySpec, ta.ContextManager['DeployDriver']]):
|
11161
|
+
pass
|
10939
11162
|
|
10940
11163
|
|
10941
|
-
class
|
11164
|
+
class DeployDriver:
|
10942
11165
|
def __init__(
|
10943
11166
|
self,
|
10944
11167
|
*,
|
10945
|
-
|
10946
|
-
paths: DeployPathsManager,
|
11168
|
+
spec: DeploySpec,
|
10947
11169
|
|
10948
|
-
|
10949
|
-
|
11170
|
+
deploys: DeployManager,
|
11171
|
+
paths: DeployPathsManager,
|
11172
|
+
apps: DeployAppManager,
|
11173
|
+
) -> None:
|
10950
11174
|
super().__init__()
|
10951
11175
|
|
10952
|
-
self.
|
10953
|
-
self._paths = paths
|
10954
|
-
|
10955
|
-
self._utc_clock = utc_clock
|
10956
|
-
|
10957
|
-
def _utc_now(self) -> datetime.datetime:
|
10958
|
-
if self._utc_clock is not None:
|
10959
|
-
return self._utc_clock() # noqa
|
10960
|
-
else:
|
10961
|
-
return datetime.datetime.now(tz=datetime.timezone.utc) # noqa
|
11176
|
+
self._spec = spec
|
10962
11177
|
|
10963
|
-
|
10964
|
-
|
11178
|
+
self._deploys = deploys
|
11179
|
+
self._paths = paths
|
11180
|
+
self._apps = apps
|
10965
11181
|
|
10966
|
-
async def
|
10967
|
-
self,
|
10968
|
-
spec: DeploySpec,
|
10969
|
-
) -> None:
|
11182
|
+
async def drive_deploy(self) -> None:
|
10970
11183
|
self._paths.validate_deploy_paths()
|
10971
11184
|
|
10972
11185
|
#
|
10973
11186
|
|
10974
|
-
hs = check.non_empty_str(
|
11187
|
+
hs = check.non_empty_str(self._spec.home)
|
10975
11188
|
hs = os.path.expanduser(hs)
|
10976
11189
|
hs = os.path.realpath(hs)
|
10977
11190
|
hs = os.path.abspath(hs)
|
@@ -10981,13 +11194,13 @@ class DeployManager:
|
|
10981
11194
|
#
|
10982
11195
|
|
10983
11196
|
deploy_tags = DeployTagMap(
|
10984
|
-
self.
|
10985
|
-
|
11197
|
+
self._deploys.make_deploy_time(),
|
11198
|
+
self._spec.key(),
|
10986
11199
|
)
|
10987
11200
|
|
10988
11201
|
#
|
10989
11202
|
|
10990
|
-
for app in
|
11203
|
+
for app in self._spec.apps:
|
10991
11204
|
app_tags = deploy_tags.add(
|
10992
11205
|
app.app,
|
10993
11206
|
app.key(),
|
@@ -11019,12 +11232,13 @@ class DeployCommand(Command['DeployCommand.Output']):
|
|
11019
11232
|
|
11020
11233
|
@dc.dataclass(frozen=True)
|
11021
11234
|
class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
|
11022
|
-
|
11235
|
+
_driver_factory: DeployDriverFactory
|
11023
11236
|
|
11024
11237
|
async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
|
11025
11238
|
log.info('Deploying! %r', cmd.spec)
|
11026
11239
|
|
11027
|
-
|
11240
|
+
with self._driver_factory(cmd.spec) as driver:
|
11241
|
+
await driver.drive_deploy()
|
11028
11242
|
|
11029
11243
|
return DeployCommand.Output()
|
11030
11244
|
|
@@ -11033,6 +11247,10 @@ class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]
|
|
11033
11247
|
# ../deploy/inject.py
|
11034
11248
|
|
11035
11249
|
|
11250
|
+
class DeployInjectorScope(ContextvarInjectorScope):
|
11251
|
+
pass
|
11252
|
+
|
11253
|
+
|
11036
11254
|
def bind_deploy(
|
11037
11255
|
*,
|
11038
11256
|
deploy_config: DeployConfig,
|
@@ -11076,6 +11294,25 @@ def bind_deploy(
|
|
11076
11294
|
|
11077
11295
|
#
|
11078
11296
|
|
11297
|
+
def provide_deploy_driver_factory(injector: Injector, sc: DeployInjectorScope) -> DeployDriverFactory:
|
11298
|
+
@contextlib.contextmanager
|
11299
|
+
def factory(spec: DeploySpec) -> ta.Iterator[DeployDriver]:
|
11300
|
+
with sc.enter({
|
11301
|
+
inj.as_key(DeploySpec): spec,
|
11302
|
+
}):
|
11303
|
+
yield injector[DeployDriver]
|
11304
|
+
return DeployDriverFactory(factory)
|
11305
|
+
lst.append(inj.bind(provide_deploy_driver_factory, singleton=True))
|
11306
|
+
|
11307
|
+
lst.extend([
|
11308
|
+
inj.bind_scope(DeployInjectorScope),
|
11309
|
+
inj.bind_scope_seed(DeploySpec, DeployInjectorScope),
|
11310
|
+
|
11311
|
+
inj.bind(DeployDriver, in_=DeployInjectorScope),
|
11312
|
+
])
|
11313
|
+
|
11314
|
+
#
|
11315
|
+
|
11079
11316
|
lst.extend([
|
11080
11317
|
bind_command(DeployCommand, DeployCommandExecutor),
|
11081
11318
|
bind_command(InterpCommand, InterpCommandExecutor),
|
ominfra/scripts/supervisor.py
CHANGED
@@ -37,6 +37,7 @@ import base64
|
|
37
37
|
import collections
|
38
38
|
import collections.abc
|
39
39
|
import contextlib
|
40
|
+
import contextvars
|
40
41
|
import ctypes as ct
|
41
42
|
import dataclasses as dc
|
42
43
|
import datetime
|
@@ -4070,6 +4071,10 @@ class InjectorBinding:
|
|
4070
4071
|
key: InjectorKey
|
4071
4072
|
provider: InjectorProvider
|
4072
4073
|
|
4074
|
+
def __post_init__(self) -> None:
|
4075
|
+
check.isinstance(self.key, InjectorKey)
|
4076
|
+
check.isinstance(self.provider, InjectorProvider)
|
4077
|
+
|
4073
4078
|
|
4074
4079
|
class InjectorBindings(abc.ABC):
|
4075
4080
|
@abc.abstractmethod
|
@@ -4333,6 +4338,164 @@ def build_injector_provider_map(bs: InjectorBindings) -> ta.Mapping[InjectorKey,
|
|
4333
4338
|
return pm
|
4334
4339
|
|
4335
4340
|
|
4341
|
+
###
|
4342
|
+
# scopes
|
4343
|
+
|
4344
|
+
|
4345
|
+
class InjectorScope(abc.ABC): # noqa
|
4346
|
+
def __init__(
|
4347
|
+
self,
|
4348
|
+
*,
|
4349
|
+
_i: Injector,
|
4350
|
+
) -> None:
|
4351
|
+
check.not_in(abc.ABC, type(self).__bases__)
|
4352
|
+
|
4353
|
+
super().__init__()
|
4354
|
+
|
4355
|
+
self._i = _i
|
4356
|
+
|
4357
|
+
all_seeds: ta.Iterable[_InjectorScopeSeed] = self._i.provide(InjectorKey(_InjectorScopeSeed, array=True))
|
4358
|
+
self._sks = {s.k for s in all_seeds if s.sc is type(self)}
|
4359
|
+
|
4360
|
+
#
|
4361
|
+
|
4362
|
+
@dc.dataclass(frozen=True)
|
4363
|
+
class State:
|
4364
|
+
seeds: ta.Dict[InjectorKey, ta.Any]
|
4365
|
+
prvs: ta.Dict[InjectorKey, ta.Any] = dc.field(default_factory=dict)
|
4366
|
+
|
4367
|
+
def new_state(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> State:
|
4368
|
+
vs = dict(vs)
|
4369
|
+
check.equal(set(vs.keys()), self._sks)
|
4370
|
+
return InjectorScope.State(vs)
|
4371
|
+
|
4372
|
+
#
|
4373
|
+
|
4374
|
+
@abc.abstractmethod
|
4375
|
+
def state(self) -> State:
|
4376
|
+
raise NotImplementedError
|
4377
|
+
|
4378
|
+
@abc.abstractmethod
|
4379
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.ContextManager[None]:
|
4380
|
+
raise NotImplementedError
|
4381
|
+
|
4382
|
+
|
4383
|
+
class ExclusiveInjectorScope(InjectorScope, abc.ABC):
|
4384
|
+
_st: ta.Optional[InjectorScope.State] = None
|
4385
|
+
|
4386
|
+
def state(self) -> InjectorScope.State:
|
4387
|
+
return check.not_none(self._st)
|
4388
|
+
|
4389
|
+
@contextlib.contextmanager
|
4390
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.Iterator[None]:
|
4391
|
+
check.none(self._st)
|
4392
|
+
self._st = self.new_state(vs)
|
4393
|
+
try:
|
4394
|
+
yield
|
4395
|
+
finally:
|
4396
|
+
self._st = None
|
4397
|
+
|
4398
|
+
|
4399
|
+
class ContextvarInjectorScope(InjectorScope, abc.ABC):
|
4400
|
+
_cv: contextvars.ContextVar
|
4401
|
+
|
4402
|
+
def __init_subclass__(cls, **kwargs: ta.Any) -> None:
|
4403
|
+
super().__init_subclass__(**kwargs)
|
4404
|
+
check.not_in(abc.ABC, cls.__bases__)
|
4405
|
+
check.state(not hasattr(cls, '_cv'))
|
4406
|
+
cls._cv = contextvars.ContextVar(f'{cls.__name__}_cv')
|
4407
|
+
|
4408
|
+
def state(self) -> InjectorScope.State:
|
4409
|
+
return self._cv.get()
|
4410
|
+
|
4411
|
+
@contextlib.contextmanager
|
4412
|
+
def enter(self, vs: ta.Mapping[InjectorKey, ta.Any]) -> ta.Iterator[None]:
|
4413
|
+
try:
|
4414
|
+
self._cv.get()
|
4415
|
+
except LookupError:
|
4416
|
+
pass
|
4417
|
+
else:
|
4418
|
+
raise RuntimeError(f'Scope already entered: {self}')
|
4419
|
+
st = self.new_state(vs)
|
4420
|
+
tok = self._cv.set(st)
|
4421
|
+
try:
|
4422
|
+
yield
|
4423
|
+
finally:
|
4424
|
+
self._cv.reset(tok)
|
4425
|
+
|
4426
|
+
|
4427
|
+
#
|
4428
|
+
|
4429
|
+
|
4430
|
+
@dc.dataclass(frozen=True)
|
4431
|
+
class ScopedInjectorProvider(InjectorProvider):
|
4432
|
+
p: InjectorProvider
|
4433
|
+
k: InjectorKey
|
4434
|
+
sc: ta.Type[InjectorScope]
|
4435
|
+
|
4436
|
+
def __post_init__(self) -> None:
|
4437
|
+
check.isinstance(self.p, InjectorProvider)
|
4438
|
+
check.isinstance(self.k, InjectorKey)
|
4439
|
+
check.issubclass(self.sc, InjectorScope)
|
4440
|
+
|
4441
|
+
def provider_fn(self) -> InjectorProviderFn:
|
4442
|
+
def pfn(i: Injector) -> ta.Any:
|
4443
|
+
st = i[self.sc].state()
|
4444
|
+
try:
|
4445
|
+
return st.prvs[self.k]
|
4446
|
+
except KeyError:
|
4447
|
+
pass
|
4448
|
+
v = ufn(i)
|
4449
|
+
st.prvs[self.k] = v
|
4450
|
+
return v
|
4451
|
+
|
4452
|
+
ufn = self.p.provider_fn()
|
4453
|
+
return pfn
|
4454
|
+
|
4455
|
+
|
4456
|
+
@dc.dataclass(frozen=True)
|
4457
|
+
class _ScopeSeedInjectorProvider(InjectorProvider):
|
4458
|
+
k: InjectorKey
|
4459
|
+
sc: ta.Type[InjectorScope]
|
4460
|
+
|
4461
|
+
def __post_init__(self) -> None:
|
4462
|
+
check.isinstance(self.k, InjectorKey)
|
4463
|
+
check.issubclass(self.sc, InjectorScope)
|
4464
|
+
|
4465
|
+
def provider_fn(self) -> InjectorProviderFn:
|
4466
|
+
def pfn(i: Injector) -> ta.Any:
|
4467
|
+
st = i[self.sc].state()
|
4468
|
+
return st.seeds[self.k]
|
4469
|
+
return pfn
|
4470
|
+
|
4471
|
+
|
4472
|
+
def bind_injector_scope(sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
4473
|
+
return as_injector_bindings(
|
4474
|
+
InjectorBinder.bind(sc, singleton=True),
|
4475
|
+
)
|
4476
|
+
|
4477
|
+
|
4478
|
+
#
|
4479
|
+
|
4480
|
+
|
4481
|
+
@dc.dataclass(frozen=True)
|
4482
|
+
class _InjectorScopeSeed:
|
4483
|
+
sc: ta.Type['InjectorScope']
|
4484
|
+
k: InjectorKey
|
4485
|
+
|
4486
|
+
def __post_init__(self) -> None:
|
4487
|
+
check.issubclass(self.sc, InjectorScope)
|
4488
|
+
check.isinstance(self.k, InjectorKey)
|
4489
|
+
|
4490
|
+
|
4491
|
+
def bind_injector_scope_seed(k: ta.Any, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
4492
|
+
kk = as_injector_key(k)
|
4493
|
+
return as_injector_bindings(
|
4494
|
+
InjectorBinding(kk, _ScopeSeedInjectorProvider(kk, sc)),
|
4495
|
+
InjectorBinder.bind(_InjectorScopeSeed(sc, kk), array=True),
|
4496
|
+
)
|
4497
|
+
|
4498
|
+
|
4336
4499
|
###
|
4337
4500
|
# inspection
|
4338
4501
|
|
@@ -4477,13 +4640,21 @@ _INJECTOR_EAGER_ARRAY_KEY: InjectorKey[_InjectorEager] = InjectorKey(_InjectorEa
|
|
4477
4640
|
|
4478
4641
|
|
4479
4642
|
class _Injector(Injector):
|
4643
|
+
_DEFAULT_BINDINGS: ta.ClassVar[ta.List[InjectorBinding]] = []
|
4644
|
+
|
4480
4645
|
def __init__(self, bs: InjectorBindings, p: ta.Optional[Injector] = None) -> None:
|
4481
4646
|
super().__init__()
|
4482
4647
|
|
4483
4648
|
self._bs = check.isinstance(bs, InjectorBindings)
|
4484
4649
|
self._p: ta.Optional[Injector] = check.isinstance(p, (Injector, type(None)))
|
4485
4650
|
|
4486
|
-
self._pfm = {
|
4651
|
+
self._pfm = {
|
4652
|
+
k: v.provider_fn()
|
4653
|
+
for k, v in build_injector_provider_map(as_injector_bindings(
|
4654
|
+
*self._DEFAULT_BINDINGS,
|
4655
|
+
bs,
|
4656
|
+
)).items()
|
4657
|
+
}
|
4487
4658
|
|
4488
4659
|
if _INJECTOR_INJECTOR_KEY in self._pfm:
|
4489
4660
|
raise DuplicateInjectorKeyError(_INJECTOR_INJECTOR_KEY)
|
@@ -4650,6 +4821,7 @@ class InjectorBinder:
|
|
4650
4821
|
to_const: ta.Any = None,
|
4651
4822
|
to_key: ta.Any = None,
|
4652
4823
|
|
4824
|
+
in_: ta.Optional[ta.Type[InjectorScope]] = None,
|
4653
4825
|
singleton: bool = False,
|
4654
4826
|
|
4655
4827
|
eager: bool = False,
|
@@ -4659,12 +4831,12 @@ class InjectorBinder:
|
|
4659
4831
|
if isinstance(obj, cls._BANNED_BIND_TYPES):
|
4660
4832
|
raise TypeError(obj)
|
4661
4833
|
|
4662
|
-
|
4834
|
+
#
|
4663
4835
|
|
4664
4836
|
if key is not None:
|
4665
4837
|
key = as_injector_key(key)
|
4666
4838
|
|
4667
|
-
|
4839
|
+
#
|
4668
4840
|
|
4669
4841
|
has_to = (
|
4670
4842
|
to_fn is not None or
|
@@ -4694,7 +4866,7 @@ class InjectorBinder:
|
|
4694
4866
|
key = InjectorKey(type(obj))
|
4695
4867
|
del has_to
|
4696
4868
|
|
4697
|
-
|
4869
|
+
#
|
4698
4870
|
|
4699
4871
|
if tag is not None:
|
4700
4872
|
if key.tag is not None:
|
@@ -4704,7 +4876,7 @@ class InjectorBinder:
|
|
4704
4876
|
if array is not None:
|
4705
4877
|
key = dc.replace(key, array=array)
|
4706
4878
|
|
4707
|
-
|
4879
|
+
#
|
4708
4880
|
|
4709
4881
|
providers: ta.List[InjectorProvider] = []
|
4710
4882
|
if to_fn is not None:
|
@@ -4719,23 +4891,34 @@ class InjectorBinder:
|
|
4719
4891
|
raise TypeError('Must specify provider')
|
4720
4892
|
if len(providers) > 1:
|
4721
4893
|
raise TypeError('May not specify multiple providers')
|
4722
|
-
provider
|
4894
|
+
provider = check.single(providers)
|
4723
4895
|
|
4724
|
-
|
4896
|
+
#
|
4725
4897
|
|
4898
|
+
pws: ta.List[ta.Any] = []
|
4899
|
+
if in_ is not None:
|
4900
|
+
check.issubclass(in_, InjectorScope)
|
4901
|
+
check.not_in(abc.ABC, in_.__bases__)
|
4902
|
+
pws.append(functools.partial(ScopedInjectorProvider, k=key, sc=in_))
|
4726
4903
|
if singleton:
|
4727
|
-
|
4904
|
+
pws.append(SingletonInjectorProvider)
|
4905
|
+
if len(pws) > 1:
|
4906
|
+
raise TypeError('May not specify multiple provider wrappers')
|
4907
|
+
elif pws:
|
4908
|
+
provider = check.single(pws)(provider)
|
4909
|
+
|
4910
|
+
#
|
4728
4911
|
|
4729
4912
|
binding = InjectorBinding(key, provider)
|
4730
4913
|
|
4731
|
-
|
4914
|
+
#
|
4732
4915
|
|
4733
4916
|
extras: ta.List[InjectorBinding] = []
|
4734
4917
|
|
4735
4918
|
if eager:
|
4736
4919
|
extras.append(bind_injector_eager_key(key))
|
4737
4920
|
|
4738
|
-
|
4921
|
+
#
|
4739
4922
|
|
4740
4923
|
if extras:
|
4741
4924
|
return as_injector_bindings(binding, *extras)
|
@@ -4808,7 +4991,8 @@ def bind_injector_eager_key(key: ta.Any) -> InjectorBinding:
|
|
4808
4991
|
return InjectorBinding(_INJECTOR_EAGER_ARRAY_KEY, ConstInjectorProvider(_InjectorEager(as_injector_key(key))))
|
4809
4992
|
|
4810
4993
|
|
4811
|
-
|
4994
|
+
###
|
4995
|
+
# api
|
4812
4996
|
|
4813
4997
|
|
4814
4998
|
class InjectionApi:
|
@@ -4831,6 +5015,14 @@ class InjectionApi:
|
|
4831
5015
|
def override(self, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
|
4832
5016
|
return injector_override(p, *args)
|
4833
5017
|
|
5018
|
+
# scopes
|
5019
|
+
|
5020
|
+
def bind_scope(self, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5021
|
+
return bind_injector_scope(sc)
|
5022
|
+
|
5023
|
+
def bind_scope_seed(self, k: ta.Any, sc: ta.Type[InjectorScope]) -> InjectorBindingOrBindings:
|
5024
|
+
return bind_injector_scope_seed(k, sc)
|
5025
|
+
|
4834
5026
|
# injector
|
4835
5027
|
|
4836
5028
|
def create_injector(self, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
|
@@ -4851,6 +5043,7 @@ class InjectionApi:
|
|
4851
5043
|
to_const: ta.Any = None,
|
4852
5044
|
to_key: ta.Any = None,
|
4853
5045
|
|
5046
|
+
in_: ta.Optional[ta.Type[InjectorScope]] = None,
|
4854
5047
|
singleton: bool = False,
|
4855
5048
|
|
4856
5049
|
eager: bool = False,
|
@@ -4867,6 +5060,7 @@ class InjectionApi:
|
|
4867
5060
|
to_const=to_const,
|
4868
5061
|
to_key=to_key,
|
4869
5062
|
|
5063
|
+
in_=in_,
|
4870
5064
|
singleton=singleton,
|
4871
5065
|
|
4872
5066
|
eager=eager,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ominfra
|
3
|
-
Version: 0.0.0.
|
3
|
+
Version: 0.0.0.dev178
|
4
4
|
Summary: ominfra
|
5
5
|
Author: wrmsr
|
6
6
|
License: BSD-3-Clause
|
@@ -12,8 +12,8 @@ Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Operating System :: POSIX
|
13
13
|
Requires-Python: >=3.12
|
14
14
|
License-File: LICENSE
|
15
|
-
Requires-Dist: omdev==0.0.0.
|
16
|
-
Requires-Dist: omlish==0.0.0.
|
15
|
+
Requires-Dist: omdev==0.0.0.dev178
|
16
|
+
Requires-Dist: omlish==0.0.0.dev178
|
17
17
|
Provides-Extra: all
|
18
18
|
Requires-Dist: paramiko~=3.5; extra == "all"
|
19
19
|
Requires-Dist: asyncssh~=2.18; extra == "all"
|
@@ -45,12 +45,13 @@ ominfra/manage/commands/subprocess.py,sha256=yHGMbAI-xKe_9BUs5IZ3Yav8qRE-I9aGnBt
|
|
45
45
|
ominfra/manage/commands/types.py,sha256=XFZPeqeIBAaIIQF3pdPbGxLlb-LCrz6WtlDWO2q_vz0,210
|
46
46
|
ominfra/manage/deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
47
|
ominfra/manage/deploy/apps.py,sha256=LeZ2iX2YHviOAnvgut7Oz15301eJoYYCpmD3ffoIagA,4742
|
48
|
-
ominfra/manage/deploy/commands.py,sha256=
|
48
|
+
ominfra/manage/deploy/commands.py,sha256=U74HYQ4nhvH7znAKyXGOmZfdnll2gMWxKWVW4GzxG-0,830
|
49
49
|
ominfra/manage/deploy/conf.py,sha256=fNfFlIb-bB3KAzaYZcjrbqaqKSiSq0Lpk0mIF6WgXiw,5410
|
50
50
|
ominfra/manage/deploy/config.py,sha256=kPpl8TRisz295cM4oj-RHA6oh5jdcJ_N9pVpkl_doO8,114
|
51
|
-
ominfra/manage/deploy/deploy.py,sha256=
|
51
|
+
ominfra/manage/deploy/deploy.py,sha256=vyBTbBm51HhRE-MQNvxEt39F8uOYsB4ToqZ3zmVkpqU,819
|
52
|
+
ominfra/manage/deploy/driver.py,sha256=ccLiVoZz_GnhQ3FRPFCu9hzsU6wsOWTOmHeYNBRIZkg,1576
|
52
53
|
ominfra/manage/deploy/git.py,sha256=g4wzUuSu9HwWSDhdVX-7BvA2htMwtWbRcHaoDy-xOJ4,3960
|
53
|
-
ominfra/manage/deploy/inject.py,sha256=
|
54
|
+
ominfra/manage/deploy/inject.py,sha256=JHQexbf-789mWL8GTSxyd4SnTbDB0nqwSyiJp-3QvAM,2834
|
54
55
|
ominfra/manage/deploy/interp.py,sha256=OKkenH8YKEW_mEDR6X7_ZLxK9a1Ox6KHSwFPTHT6OzA,1029
|
55
56
|
ominfra/manage/deploy/specs.py,sha256=usi5AmTlv8OGFcwhVHnu8Qrz1Criu5QP6_ScNMi9ehM,3748
|
56
57
|
ominfra/manage/deploy/tags.py,sha256=NVEJhHKMwoDuCFd8lInH_jIe99FQILBX3wrulh3GiDg,5166
|
@@ -86,8 +87,8 @@ ominfra/manage/targets/inject.py,sha256=P4597xWM-V3I_gCt2O71OLhYQkkXtuJvkYRsIbhh
|
|
86
87
|
ominfra/manage/targets/targets.py,sha256=7GP6UAZyJFEhpkJN6UQdpr_WN3p7C76v-s445y-WB6U,1885
|
87
88
|
ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
88
89
|
ominfra/scripts/journald2aws.py,sha256=yEnBAd0Q_3lBkVoTvlJ_uCcUxz7Ckn2qoSWZVhMihvQ,157696
|
89
|
-
ominfra/scripts/manage.py,sha256=
|
90
|
-
ominfra/scripts/supervisor.py,sha256=
|
90
|
+
ominfra/scripts/manage.py,sha256=XDt86ZEFjcShexhLQjmse1N6f_dk7AVVtozzETsNUdY,324293
|
91
|
+
ominfra/scripts/supervisor.py,sha256=6RMBLbB4pMNaJlnOBwhdpuhMqv6NDrjTup9SYzKsEjo,281844
|
91
92
|
ominfra/supervisor/LICENSE.txt,sha256=yvqaMNsDhWxziHa9ien6qCW1SkZv-DQlAg96XjfSee8,1746
|
92
93
|
ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
|
93
94
|
ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
|
@@ -129,9 +130,9 @@ ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
|
|
129
130
|
ominfra/tailscale/cli.py,sha256=h6akQJMl0KuWLHS7Ur6WcBZ2JwF0DJQhsPTnFBdGyNk,3571
|
130
131
|
ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
131
132
|
ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
|
132
|
-
ominfra-0.0.0.
|
133
|
-
ominfra-0.0.0.
|
134
|
-
ominfra-0.0.0.
|
135
|
-
ominfra-0.0.0.
|
136
|
-
ominfra-0.0.0.
|
137
|
-
ominfra-0.0.0.
|
133
|
+
ominfra-0.0.0.dev178.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
|
134
|
+
ominfra-0.0.0.dev178.dist-info/METADATA,sha256=Kfw95dyWOXq2P3oSLxG3ObbDVl139_CQAnrZy5k6QtE,731
|
135
|
+
ominfra-0.0.0.dev178.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
136
|
+
ominfra-0.0.0.dev178.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
|
137
|
+
ominfra-0.0.0.dev178.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
|
138
|
+
ominfra-0.0.0.dev178.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|