ominfra 0.0.0.dev177__py3-none-any.whl → 0.0.0.dev178__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.
- 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
|