ominfra 0.0.0.dev160__py3-none-any.whl → 0.0.0.dev161__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,8 +15,8 @@ import typing as ta
15
15
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
16
16
  from omlish.lite.cached import async_cached_nullary
17
17
  from omlish.lite.check import check
18
+ from omlish.os.atomics import AtomicPathSwapping
18
19
 
19
- from .atomics import DeployAtomicPathSwapping
20
20
  from .paths import SingleDirDeployPathOwner
21
21
  from .specs import DeployGitCheckout
22
22
  from .specs import DeployGitRepo
@@ -32,7 +32,7 @@ class DeployGitManager(SingleDirDeployPathOwner):
32
32
  self,
33
33
  *,
34
34
  deploy_home: ta.Optional[DeployHome] = None,
35
- atomics: DeployAtomicPathSwapping,
35
+ atomics: AtomicPathSwapping,
36
36
  ) -> None:
37
37
  super().__init__(
38
38
  owned_dir='git',
@@ -5,10 +5,10 @@ import typing as ta
5
5
  from omlish.lite.inject import InjectorBindingOrBindings
6
6
  from omlish.lite.inject import InjectorBindings
7
7
  from omlish.lite.inject import inj
8
+ from omlish.os.atomics import AtomicPathSwapping
8
9
 
9
10
  from ..commands.inject import bind_command
10
11
  from .apps import DeployAppManager
11
- from .atomics import DeployAtomicPathSwapping
12
12
  from .commands import DeployCommand
13
13
  from .commands import DeployCommandExecutor
14
14
  from .config import DeployConfig
@@ -34,7 +34,7 @@ def bind_deploy(
34
34
  inj.bind(DeployGitManager, singleton=True),
35
35
 
36
36
  inj.bind(DeployTmpManager, singleton=True),
37
- inj.bind(DeployAtomicPathSwapping, to_key=DeployTmpManager),
37
+ inj.bind(AtomicPathSwapping, to_key=DeployTmpManager),
38
38
 
39
39
  inj.bind(DeployVenvManager, singleton=True),
40
40
 
@@ -3,18 +3,18 @@ import typing as ta
3
3
 
4
4
  from omlish.lite.cached import cached_nullary
5
5
  from omlish.lite.check import check
6
+ from omlish.os.atomics import AtomicPathSwap
7
+ from omlish.os.atomics import AtomicPathSwapKind
8
+ from omlish.os.atomics import AtomicPathSwapping
9
+ from omlish.os.atomics import TempDirAtomicPathSwapping
6
10
 
7
- from .atomics import DeployAtomicPathSwap
8
- from .atomics import DeployAtomicPathSwapKind
9
- from .atomics import DeployAtomicPathSwapping
10
- from .atomics import TempDirDeployAtomicPathSwapping
11
11
  from .paths import SingleDirDeployPathOwner
12
12
  from .types import DeployHome
13
13
 
14
14
 
15
15
  class DeployTmpManager(
16
16
  SingleDirDeployPathOwner,
17
- DeployAtomicPathSwapping,
17
+ AtomicPathSwapping,
18
18
  ):
19
19
  def __init__(
20
20
  self,
@@ -27,18 +27,18 @@ class DeployTmpManager(
27
27
  )
28
28
 
29
29
  @cached_nullary
30
- def _swapping(self) -> DeployAtomicPathSwapping:
31
- return TempDirDeployAtomicPathSwapping(
30
+ def _swapping(self) -> AtomicPathSwapping:
31
+ return TempDirAtomicPathSwapping(
32
32
  temp_dir=self._make_dir(),
33
33
  root_dir=check.non_empty_str(self._deploy_home),
34
34
  )
35
35
 
36
36
  def begin_atomic_path_swap(
37
37
  self,
38
- kind: DeployAtomicPathSwapKind,
38
+ kind: AtomicPathSwapKind,
39
39
  dst_path: str,
40
40
  **kwargs: ta.Any,
41
- ) -> DeployAtomicPathSwap:
41
+ ) -> AtomicPathSwap:
42
42
  return self._swapping().begin_atomic_path_swap(
43
43
  kind,
44
44
  dst_path,
@@ -10,8 +10,8 @@ import typing as ta
10
10
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
11
11
  from omlish.lite.cached import cached_nullary
12
12
  from omlish.lite.check import check
13
+ from omlish.os.atomics import AtomicPathSwapping
13
14
 
14
- from .atomics import DeployAtomicPathSwapping
15
15
  from .paths import DeployPath
16
16
  from .paths import DeployPathOwner
17
17
  from .types import DeployAppTag
@@ -23,7 +23,7 @@ class DeployVenvManager(DeployPathOwner):
23
23
  self,
24
24
  *,
25
25
  deploy_home: ta.Optional[DeployHome] = None,
26
- atomics: DeployAtomicPathSwapping,
26
+ atomics: AtomicPathSwapping,
27
27
  ) -> None:
28
28
  super().__init__()
29
29
 
@@ -105,7 +105,7 @@ class DockerManageTargetConnector(ManageTargetConnector):
105
105
  if dmt.image is not None:
106
106
  sh_parts.extend(['run', '-i', dmt.image])
107
107
  elif dmt.container_id is not None:
108
- sh_parts.extend(['exec', dmt.container_id])
108
+ sh_parts.extend(['exec', '-i', dmt.container_id])
109
109
  else:
110
110
  raise ValueError(dmt)
111
111
 
ominfra/scripts/manage.py CHANGED
@@ -100,10 +100,6 @@ CallableVersionOperator = ta.Callable[['Version', str], bool]
100
100
  CommandT = ta.TypeVar('CommandT', bound='Command')
101
101
  CommandOutputT = ta.TypeVar('CommandOutputT', bound='Command.Output')
102
102
 
103
- # deploy/atomics.py
104
- DeployAtomicPathSwapKind = ta.Literal['dir', 'file']
105
- DeployAtomicPathSwapState = ta.Literal['open', 'committed', 'aborted'] # ta.TypeAlias
106
-
107
103
  # deploy/paths.py
108
104
  DeployPathKind = ta.Literal['dir', 'file'] # ta.TypeAlias
109
105
  DeployPathPlaceholder = ta.Literal['app', 'tag'] # ta.TypeAlias
@@ -121,6 +117,10 @@ InjectorProviderFn = ta.Callable[['Injector'], ta.Any]
121
117
  InjectorProviderFnMap = ta.Mapping['InjectorKey', 'InjectorProviderFn']
122
118
  InjectorBindingOrBindings = ta.Union['InjectorBinding', 'InjectorBindings']
123
119
 
120
+ # ../../omlish/os/atomics.py
121
+ AtomicPathSwapKind = ta.Literal['dir', 'file']
122
+ AtomicPathSwapState = ta.Literal['open', 'committed', 'aborted'] # ta.TypeAlias
123
+
124
124
  # ../configs.py
125
125
  ConfigMapping = ta.Mapping[str, ta.Any]
126
126
 
@@ -4064,204 +4064,6 @@ def build_command_name_map(crs: CommandRegistrations) -> CommandNameMap:
4064
4064
  return CommandNameMap(dct)
4065
4065
 
4066
4066
 
4067
- ########################################
4068
- # ../deploy/atomics.py
4069
-
4070
-
4071
- ##
4072
-
4073
-
4074
- class DeployAtomicPathSwap(abc.ABC):
4075
- def __init__(
4076
- self,
4077
- kind: DeployAtomicPathSwapKind,
4078
- dst_path: str,
4079
- *,
4080
- auto_commit: bool = False,
4081
- ) -> None:
4082
- super().__init__()
4083
-
4084
- self._kind = kind
4085
- self._dst_path = dst_path
4086
- self._auto_commit = auto_commit
4087
-
4088
- self._state: DeployAtomicPathSwapState = 'open'
4089
-
4090
- def __repr__(self) -> str:
4091
- return attr_repr(self, 'kind', 'dst_path', 'tmp_path')
4092
-
4093
- @property
4094
- def kind(self) -> DeployAtomicPathSwapKind:
4095
- return self._kind
4096
-
4097
- @property
4098
- def dst_path(self) -> str:
4099
- return self._dst_path
4100
-
4101
- @property
4102
- @abc.abstractmethod
4103
- def tmp_path(self) -> str:
4104
- raise NotImplementedError
4105
-
4106
- #
4107
-
4108
- @property
4109
- def state(self) -> DeployAtomicPathSwapState:
4110
- return self._state
4111
-
4112
- def _check_state(self, *states: DeployAtomicPathSwapState) -> None:
4113
- if self._state not in states:
4114
- raise RuntimeError(f'Atomic path swap not in correct state: {self._state}, {states}')
4115
-
4116
- #
4117
-
4118
- @abc.abstractmethod
4119
- def _commit(self) -> None:
4120
- raise NotImplementedError
4121
-
4122
- def commit(self) -> None:
4123
- if self._state == 'committed':
4124
- return
4125
- self._check_state('open')
4126
- try:
4127
- self._commit()
4128
- except Exception: # noqa
4129
- self._abort()
4130
- raise
4131
- else:
4132
- self._state = 'committed'
4133
-
4134
- #
4135
-
4136
- @abc.abstractmethod
4137
- def _abort(self) -> None:
4138
- raise NotImplementedError
4139
-
4140
- def abort(self) -> None:
4141
- if self._state == 'aborted':
4142
- return
4143
- self._abort()
4144
- self._state = 'aborted'
4145
-
4146
- #
4147
-
4148
- def __enter__(self) -> 'DeployAtomicPathSwap':
4149
- return self
4150
-
4151
- def __exit__(self, exc_type, exc_val, exc_tb):
4152
- if (
4153
- exc_type is None and
4154
- self._auto_commit and
4155
- self._state == 'open'
4156
- ):
4157
- self.commit()
4158
- else:
4159
- self.abort()
4160
-
4161
-
4162
- #
4163
-
4164
-
4165
- class DeployAtomicPathSwapping(abc.ABC):
4166
- @abc.abstractmethod
4167
- def begin_atomic_path_swap(
4168
- self,
4169
- kind: DeployAtomicPathSwapKind,
4170
- dst_path: str,
4171
- *,
4172
- name_hint: ta.Optional[str] = None,
4173
- make_dirs: bool = False,
4174
- **kwargs: ta.Any,
4175
- ) -> DeployAtomicPathSwap:
4176
- raise NotImplementedError
4177
-
4178
-
4179
- ##
4180
-
4181
-
4182
- class OsRenameDeployAtomicPathSwap(DeployAtomicPathSwap):
4183
- def __init__(
4184
- self,
4185
- kind: DeployAtomicPathSwapKind,
4186
- dst_path: str,
4187
- tmp_path: str,
4188
- **kwargs: ta.Any,
4189
- ) -> None:
4190
- if kind == 'dir':
4191
- check.state(os.path.isdir(tmp_path))
4192
- elif kind == 'file':
4193
- check.state(os.path.isfile(tmp_path))
4194
- else:
4195
- raise TypeError(kind)
4196
-
4197
- super().__init__(
4198
- kind,
4199
- dst_path,
4200
- **kwargs,
4201
- )
4202
-
4203
- self._tmp_path = tmp_path
4204
-
4205
- @property
4206
- def tmp_path(self) -> str:
4207
- return self._tmp_path
4208
-
4209
- def _commit(self) -> None:
4210
- os.rename(self._tmp_path, self._dst_path)
4211
-
4212
- def _abort(self) -> None:
4213
- shutil.rmtree(self._tmp_path, ignore_errors=True)
4214
-
4215
-
4216
- class TempDirDeployAtomicPathSwapping(DeployAtomicPathSwapping):
4217
- def __init__(
4218
- self,
4219
- *,
4220
- temp_dir: ta.Optional[str] = None,
4221
- root_dir: ta.Optional[str] = None,
4222
- ) -> None:
4223
- super().__init__()
4224
-
4225
- if root_dir is not None:
4226
- root_dir = os.path.abspath(root_dir)
4227
- self._root_dir = root_dir
4228
- self._temp_dir = temp_dir
4229
-
4230
- def begin_atomic_path_swap(
4231
- self,
4232
- kind: DeployAtomicPathSwapKind,
4233
- dst_path: str,
4234
- *,
4235
- name_hint: ta.Optional[str] = None,
4236
- make_dirs: bool = False,
4237
- **kwargs: ta.Any,
4238
- ) -> DeployAtomicPathSwap:
4239
- dst_path = os.path.abspath(dst_path)
4240
- if self._root_dir is not None and not dst_path.startswith(check.non_empty_str(self._root_dir)):
4241
- raise RuntimeError(f'Atomic path swap dst must be in root dir: {dst_path}, {self._root_dir}')
4242
-
4243
- dst_dir = os.path.dirname(dst_path)
4244
- if make_dirs:
4245
- os.makedirs(dst_dir, exist_ok=True)
4246
- if not os.path.isdir(dst_dir):
4247
- raise RuntimeError(f'Atomic path swap dst dir does not exist: {dst_dir}')
4248
-
4249
- if kind == 'dir':
4250
- tmp_path = tempfile.mkdtemp(prefix=name_hint, dir=self._temp_dir)
4251
- elif kind == 'file':
4252
- fd, tmp_path = tempfile.mkstemp(prefix=name_hint, dir=self._temp_dir)
4253
- os.close(fd)
4254
- else:
4255
- raise TypeError(kind)
4256
-
4257
- return OsRenameDeployAtomicPathSwap(
4258
- kind,
4259
- dst_path,
4260
- tmp_path,
4261
- **kwargs,
4262
- )
4263
-
4264
-
4265
4067
  ########################################
4266
4068
  # ../deploy/paths.py
4267
4069
  """
@@ -6516,6 +6318,201 @@ class JsonLogFormatter(logging.Formatter):
6516
6318
  return self._json_dumps(dct)
6517
6319
 
6518
6320
 
6321
+ ########################################
6322
+ # ../../../omlish/os/atomics.py
6323
+
6324
+
6325
+ ##
6326
+
6327
+
6328
+ class AtomicPathSwap(abc.ABC):
6329
+ def __init__(
6330
+ self,
6331
+ kind: AtomicPathSwapKind,
6332
+ dst_path: str,
6333
+ *,
6334
+ auto_commit: bool = False,
6335
+ ) -> None:
6336
+ super().__init__()
6337
+
6338
+ self._kind = kind
6339
+ self._dst_path = dst_path
6340
+ self._auto_commit = auto_commit
6341
+
6342
+ self._state: AtomicPathSwapState = 'open'
6343
+
6344
+ def __repr__(self) -> str:
6345
+ return attr_repr(self, 'kind', 'dst_path', 'tmp_path')
6346
+
6347
+ @property
6348
+ def kind(self) -> AtomicPathSwapKind:
6349
+ return self._kind
6350
+
6351
+ @property
6352
+ def dst_path(self) -> str:
6353
+ return self._dst_path
6354
+
6355
+ @property
6356
+ @abc.abstractmethod
6357
+ def tmp_path(self) -> str:
6358
+ raise NotImplementedError
6359
+
6360
+ #
6361
+
6362
+ @property
6363
+ def state(self) -> AtomicPathSwapState:
6364
+ return self._state
6365
+
6366
+ def _check_state(self, *states: AtomicPathSwapState) -> None:
6367
+ if self._state not in states:
6368
+ raise RuntimeError(f'Atomic path swap not in correct state: {self._state}, {states}')
6369
+
6370
+ #
6371
+
6372
+ @abc.abstractmethod
6373
+ def _commit(self) -> None:
6374
+ raise NotImplementedError
6375
+
6376
+ def commit(self) -> None:
6377
+ if self._state == 'committed':
6378
+ return
6379
+ self._check_state('open')
6380
+ try:
6381
+ self._commit()
6382
+ except Exception: # noqa
6383
+ self._abort()
6384
+ raise
6385
+ else:
6386
+ self._state = 'committed'
6387
+
6388
+ #
6389
+
6390
+ @abc.abstractmethod
6391
+ def _abort(self) -> None:
6392
+ raise NotImplementedError
6393
+
6394
+ def abort(self) -> None:
6395
+ if self._state == 'aborted':
6396
+ return
6397
+ self._abort()
6398
+ self._state = 'aborted'
6399
+
6400
+ #
6401
+
6402
+ def __enter__(self) -> 'AtomicPathSwap':
6403
+ return self
6404
+
6405
+ def __exit__(self, exc_type, exc_val, exc_tb):
6406
+ if (
6407
+ exc_type is None and
6408
+ self._auto_commit and
6409
+ self._state == 'open'
6410
+ ):
6411
+ self.commit()
6412
+ else:
6413
+ self.abort()
6414
+
6415
+
6416
+ class AtomicPathSwapping(abc.ABC):
6417
+ @abc.abstractmethod
6418
+ def begin_atomic_path_swap(
6419
+ self,
6420
+ kind: AtomicPathSwapKind,
6421
+ dst_path: str,
6422
+ *,
6423
+ name_hint: ta.Optional[str] = None,
6424
+ make_dirs: bool = False,
6425
+ **kwargs: ta.Any,
6426
+ ) -> AtomicPathSwap:
6427
+ raise NotImplementedError
6428
+
6429
+
6430
+ ##
6431
+
6432
+
6433
+ class OsRenameAtomicPathSwap(AtomicPathSwap):
6434
+ def __init__(
6435
+ self,
6436
+ kind: AtomicPathSwapKind,
6437
+ dst_path: str,
6438
+ tmp_path: str,
6439
+ **kwargs: ta.Any,
6440
+ ) -> None:
6441
+ if kind == 'dir':
6442
+ check.state(os.path.isdir(tmp_path))
6443
+ elif kind == 'file':
6444
+ check.state(os.path.isfile(tmp_path))
6445
+ else:
6446
+ raise TypeError(kind)
6447
+
6448
+ super().__init__(
6449
+ kind,
6450
+ dst_path,
6451
+ **kwargs,
6452
+ )
6453
+
6454
+ self._tmp_path = tmp_path
6455
+
6456
+ @property
6457
+ def tmp_path(self) -> str:
6458
+ return self._tmp_path
6459
+
6460
+ def _commit(self) -> None:
6461
+ os.rename(self._tmp_path, self._dst_path)
6462
+
6463
+ def _abort(self) -> None:
6464
+ shutil.rmtree(self._tmp_path, ignore_errors=True)
6465
+
6466
+
6467
+ class TempDirAtomicPathSwapping(AtomicPathSwapping):
6468
+ def __init__(
6469
+ self,
6470
+ *,
6471
+ temp_dir: ta.Optional[str] = None,
6472
+ root_dir: ta.Optional[str] = None,
6473
+ ) -> None:
6474
+ super().__init__()
6475
+
6476
+ if root_dir is not None:
6477
+ root_dir = os.path.abspath(root_dir)
6478
+ self._root_dir = root_dir
6479
+ self._temp_dir = temp_dir
6480
+
6481
+ def begin_atomic_path_swap(
6482
+ self,
6483
+ kind: AtomicPathSwapKind,
6484
+ dst_path: str,
6485
+ *,
6486
+ name_hint: ta.Optional[str] = None,
6487
+ make_dirs: bool = False,
6488
+ **kwargs: ta.Any,
6489
+ ) -> AtomicPathSwap:
6490
+ dst_path = os.path.abspath(dst_path)
6491
+ if self._root_dir is not None and not dst_path.startswith(check.non_empty_str(self._root_dir)):
6492
+ raise RuntimeError(f'Atomic path swap dst must be in root dir: {dst_path}, {self._root_dir}')
6493
+
6494
+ dst_dir = os.path.dirname(dst_path)
6495
+ if make_dirs:
6496
+ os.makedirs(dst_dir, exist_ok=True)
6497
+ if not os.path.isdir(dst_dir):
6498
+ raise RuntimeError(f'Atomic path swap dst dir does not exist: {dst_dir}')
6499
+
6500
+ if kind == 'dir':
6501
+ tmp_path = tempfile.mkdtemp(prefix=name_hint, dir=self._temp_dir)
6502
+ elif kind == 'file':
6503
+ fd, tmp_path = tempfile.mkstemp(prefix=name_hint, dir=self._temp_dir)
6504
+ os.close(fd)
6505
+ else:
6506
+ raise TypeError(kind)
6507
+
6508
+ return OsRenameAtomicPathSwap(
6509
+ kind,
6510
+ dst_path,
6511
+ tmp_path,
6512
+ **kwargs,
6513
+ )
6514
+
6515
+
6519
6516
  ########################################
6520
6517
  # ../../../omdev/interp/types.py
6521
6518
 
@@ -6752,7 +6749,7 @@ CommandExecutorMap = ta.NewType('CommandExecutorMap', ta.Mapping[ta.Type[Command
6752
6749
 
6753
6750
  class DeployTmpManager(
6754
6751
  SingleDirDeployPathOwner,
6755
- DeployAtomicPathSwapping,
6752
+ AtomicPathSwapping,
6756
6753
  ):
6757
6754
  def __init__(
6758
6755
  self,
@@ -6765,18 +6762,18 @@ class DeployTmpManager(
6765
6762
  )
6766
6763
 
6767
6764
  @cached_nullary
6768
- def _swapping(self) -> DeployAtomicPathSwapping:
6769
- return TempDirDeployAtomicPathSwapping(
6765
+ def _swapping(self) -> AtomicPathSwapping:
6766
+ return TempDirAtomicPathSwapping(
6770
6767
  temp_dir=self._make_dir(),
6771
6768
  root_dir=check.non_empty_str(self._deploy_home),
6772
6769
  )
6773
6770
 
6774
6771
  def begin_atomic_path_swap(
6775
6772
  self,
6776
- kind: DeployAtomicPathSwapKind,
6773
+ kind: AtomicPathSwapKind,
6777
6774
  dst_path: str,
6778
6775
  **kwargs: ta.Any,
6779
- ) -> DeployAtomicPathSwap:
6776
+ ) -> AtomicPathSwap:
6780
6777
  return self._swapping().begin_atomic_path_swap(
6781
6778
  kind,
6782
6779
  dst_path,
@@ -8175,7 +8172,7 @@ class DeployGitManager(SingleDirDeployPathOwner):
8175
8172
  self,
8176
8173
  *,
8177
8174
  deploy_home: ta.Optional[DeployHome] = None,
8178
- atomics: DeployAtomicPathSwapping,
8175
+ atomics: AtomicPathSwapping,
8179
8176
  ) -> None:
8180
8177
  super().__init__(
8181
8178
  owned_dir='git',
@@ -8280,7 +8277,7 @@ class DeployVenvManager(DeployPathOwner):
8280
8277
  self,
8281
8278
  *,
8282
8279
  deploy_home: ta.Optional[DeployHome] = None,
8283
- atomics: DeployAtomicPathSwapping,
8280
+ atomics: AtomicPathSwapping,
8284
8281
  ) -> None:
8285
8282
  super().__init__()
8286
8283
 
@@ -9824,7 +9821,7 @@ class DockerManageTargetConnector(ManageTargetConnector):
9824
9821
  if dmt.image is not None:
9825
9822
  sh_parts.extend(['run', '-i', dmt.image])
9826
9823
  elif dmt.container_id is not None:
9827
- sh_parts.extend(['exec', dmt.container_id])
9824
+ sh_parts.extend(['exec', '-i', dmt.container_id])
9828
9825
  else:
9829
9826
  raise ValueError(dmt)
9830
9827
 
@@ -10044,7 +10041,7 @@ def bind_deploy(
10044
10041
  inj.bind(DeployGitManager, singleton=True),
10045
10042
 
10046
10043
  inj.bind(DeployTmpManager, singleton=True),
10047
- inj.bind(DeployAtomicPathSwapping, to_key=DeployTmpManager),
10044
+ inj.bind(AtomicPathSwapping, to_key=DeployTmpManager),
10048
10045
 
10049
10046
  inj.bind(DeployVenvManager, singleton=True),
10050
10047
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev160
3
+ Version: 0.0.0.dev161
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.dev160
16
- Requires-Dist: omlish==0.0.0.dev160
15
+ Requires-Dist: omdev==0.0.0.dev161
16
+ Requires-Dist: omlish==0.0.0.dev161
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -45,17 +45,16 @@ 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=lXcbyX8_wrvvwKtIMM9P_Mh7xL8yj6z9_PFTl_0u-0U,1887
48
- ominfra/manage/deploy/atomics.py,sha256=j9_L2LXls2dR1I4rQw3msIa2D90JwEO9Mb8KBGOKmyU,5180
49
48
  ominfra/manage/deploy/commands.py,sha256=N9qVntnRgJ_IneI7rEQB2Za0oU7gouPfm-sl2MCwW1E,764
50
49
  ominfra/manage/deploy/config.py,sha256=aR6ubMEWqkTI55XtcG1Cczn6YhCVN6eSL8DT5EHQJN0,166
51
- ominfra/manage/deploy/git.py,sha256=T-ad5HtavIsZG3Y1lNimYXvrvklWfm2kZBcV1DLlI-A,3750
52
- ominfra/manage/deploy/inject.py,sha256=JBc96rxOL7Q6P78yZP4WHp08i2AHvV0JHbRpUzbFblw,1444
50
+ ominfra/manage/deploy/git.py,sha256=6CGLvGH8uYkuT8gyZHybJb7sgUPTtFgy7grj1YHkI9g,3747
51
+ ominfra/manage/deploy/inject.py,sha256=8wuIgdzkDCHbc69nD1meLjwfCOMdWOIfDT5yijL-du8,1441
53
52
  ominfra/manage/deploy/interp.py,sha256=OKkenH8YKEW_mEDR6X7_ZLxK9a1Ox6KHSwFPTHT6OzA,1029
54
53
  ominfra/manage/deploy/paths.py,sha256=tK8zZFWOHDRdTN5AlTe-3MpgZqovhWrljGosQmeEYvo,6839
55
54
  ominfra/manage/deploy/specs.py,sha256=Yq3WiLNJcodUBEsJfP18gPGB3X2ABI1g8YLlsUvJOXg,1230
56
- ominfra/manage/deploy/tmp.py,sha256=Wg29UMsWL_A8anFsE-XyvkTNsMfH26Nr8BvJxgKNxMo,1248
55
+ ominfra/manage/deploy/tmp.py,sha256=L0pIfQuxQ7_6gC_AAv7eubI37_IPzCVR29hkn1MHL2Q,1230
57
56
  ominfra/manage/deploy/types.py,sha256=o95wqvTGNRq8Cxx7VpqeX-9x1tI8k8BpqPFvJZkJYBA,305
58
- ominfra/manage/deploy/venvs.py,sha256=A1nqFo1Zhxg-Sw3Uyxe6hck4ZEh3bBq8GIjnJPvNLd8,2232
57
+ ominfra/manage/deploy/venvs.py,sha256=ZG9tXhzg0R173T1IFIc5DE45xEuJK97DjlN1cQPAvXI,2229
59
58
  ominfra/manage/remote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
59
  ominfra/manage/remote/_main.py,sha256=p5KoiS2WMw6QAqlDl_Zun-JybmCsy8awIfpBMLBjGMY,4356
61
60
  ominfra/manage/remote/channel.py,sha256=36xR9Ti9ZA8TUBtxmY0u7_3Lv7E6wzQTxlZl7gLR5GE,2224
@@ -72,12 +71,12 @@ ominfra/manage/system/inject.py,sha256=Ksc7Xw_Yh3lWwkTRxB2JCeOYO-nMyKj-Kssd1RDkR
72
71
  ominfra/manage/system/packages.py,sha256=HImCsgzXxcfzAoD2PjrstaSE_qgBWtTFUVb0lTEOxkI,4614
73
72
  ominfra/manage/system/platforms.py,sha256=F0bgYzUzCjZ2LbWVvnEq2ya_X_LfRW406LQYFL7bG44,1202
74
73
  ominfra/manage/targets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
- ominfra/manage/targets/connection.py,sha256=j2QrVS-QFOZJ47TqwaMt8MSPg0whokysGePagjJg3Jg,4637
74
+ ominfra/manage/targets/connection.py,sha256=5e8h9Miej2DKJxZfLyxpGe8y-Y0V_b_AuUW159XVeJM,4643
76
75
  ominfra/manage/targets/inject.py,sha256=P4597xWM-V3I_gCt2O71OLhYQkkXtuJvkYRsIbhhMcE,1561
77
76
  ominfra/manage/targets/targets.py,sha256=CFl8Uirgn3gfowO1Fn-LBK-6qYqEMFJ9snPUl0gCRuM,1753
78
77
  ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
78
  ominfra/scripts/journald2aws.py,sha256=EC8tSKW3hztBV_Kr_ykK72AmcvnWivUxcz6Sfg3M_hI,155085
80
- ominfra/scripts/manage.py,sha256=mrjtcbAYVv3RkhEV_tcdPra5lZTJG27k0qgAZsye9zk,293936
79
+ ominfra/scripts/manage.py,sha256=MQQGcgbIDwUfD31nDGJD2DhWhlazj8GVwQi7kOzi3gc,293788
81
80
  ominfra/scripts/supervisor.py,sha256=npGYEWSZfY7E24mdkJ3HrL_ax6AcqjHfqh-7nZ_sX0U,273987
82
81
  ominfra/supervisor/LICENSE.txt,sha256=yvqaMNsDhWxziHa9ien6qCW1SkZv-DQlAg96XjfSee8,1746
83
82
  ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -120,9 +119,9 @@ ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
120
119
  ominfra/tailscale/cli.py,sha256=h6akQJMl0KuWLHS7Ur6WcBZ2JwF0DJQhsPTnFBdGyNk,3571
121
120
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
121
  ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
123
- ominfra-0.0.0.dev160.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
124
- ominfra-0.0.0.dev160.dist-info/METADATA,sha256=eS2Inhifb3u6Dusi7KHOATGGlcALPwhc363rDTOzVz0,731
125
- ominfra-0.0.0.dev160.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
126
- ominfra-0.0.0.dev160.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
127
- ominfra-0.0.0.dev160.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
128
- ominfra-0.0.0.dev160.dist-info/RECORD,,
122
+ ominfra-0.0.0.dev161.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
123
+ ominfra-0.0.0.dev161.dist-info/METADATA,sha256=9BUyOL7-nhzomsloRZDx7T8VL-T0KbCHxyQ74LxzbFY,731
124
+ ominfra-0.0.0.dev161.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
125
+ ominfra-0.0.0.dev161.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
126
+ ominfra-0.0.0.dev161.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
127
+ ominfra-0.0.0.dev161.dist-info/RECORD,,
@@ -1,207 +0,0 @@
1
- # ruff: noqa: UP006 UP007
2
- import abc
3
- import os
4
- import shutil
5
- import tempfile
6
- import typing as ta
7
-
8
- from omlish.lite.check import check
9
- from omlish.lite.strings import attr_repr
10
-
11
-
12
- DeployAtomicPathSwapKind = ta.Literal['dir', 'file']
13
- DeployAtomicPathSwapState = ta.Literal['open', 'committed', 'aborted'] # ta.TypeAlias
14
-
15
-
16
- ##
17
-
18
-
19
- class DeployAtomicPathSwap(abc.ABC):
20
- def __init__(
21
- self,
22
- kind: DeployAtomicPathSwapKind,
23
- dst_path: str,
24
- *,
25
- auto_commit: bool = False,
26
- ) -> None:
27
- super().__init__()
28
-
29
- self._kind = kind
30
- self._dst_path = dst_path
31
- self._auto_commit = auto_commit
32
-
33
- self._state: DeployAtomicPathSwapState = 'open'
34
-
35
- def __repr__(self) -> str:
36
- return attr_repr(self, 'kind', 'dst_path', 'tmp_path')
37
-
38
- @property
39
- def kind(self) -> DeployAtomicPathSwapKind:
40
- return self._kind
41
-
42
- @property
43
- def dst_path(self) -> str:
44
- return self._dst_path
45
-
46
- @property
47
- @abc.abstractmethod
48
- def tmp_path(self) -> str:
49
- raise NotImplementedError
50
-
51
- #
52
-
53
- @property
54
- def state(self) -> DeployAtomicPathSwapState:
55
- return self._state
56
-
57
- def _check_state(self, *states: DeployAtomicPathSwapState) -> None:
58
- if self._state not in states:
59
- raise RuntimeError(f'Atomic path swap not in correct state: {self._state}, {states}')
60
-
61
- #
62
-
63
- @abc.abstractmethod
64
- def _commit(self) -> None:
65
- raise NotImplementedError
66
-
67
- def commit(self) -> None:
68
- if self._state == 'committed':
69
- return
70
- self._check_state('open')
71
- try:
72
- self._commit()
73
- except Exception: # noqa
74
- self._abort()
75
- raise
76
- else:
77
- self._state = 'committed'
78
-
79
- #
80
-
81
- @abc.abstractmethod
82
- def _abort(self) -> None:
83
- raise NotImplementedError
84
-
85
- def abort(self) -> None:
86
- if self._state == 'aborted':
87
- return
88
- self._abort()
89
- self._state = 'aborted'
90
-
91
- #
92
-
93
- def __enter__(self) -> 'DeployAtomicPathSwap':
94
- return self
95
-
96
- def __exit__(self, exc_type, exc_val, exc_tb):
97
- if (
98
- exc_type is None and
99
- self._auto_commit and
100
- self._state == 'open'
101
- ):
102
- self.commit()
103
- else:
104
- self.abort()
105
-
106
-
107
- #
108
-
109
-
110
- class DeployAtomicPathSwapping(abc.ABC):
111
- @abc.abstractmethod
112
- def begin_atomic_path_swap(
113
- self,
114
- kind: DeployAtomicPathSwapKind,
115
- dst_path: str,
116
- *,
117
- name_hint: ta.Optional[str] = None,
118
- make_dirs: bool = False,
119
- **kwargs: ta.Any,
120
- ) -> DeployAtomicPathSwap:
121
- raise NotImplementedError
122
-
123
-
124
- ##
125
-
126
-
127
- class OsRenameDeployAtomicPathSwap(DeployAtomicPathSwap):
128
- def __init__(
129
- self,
130
- kind: DeployAtomicPathSwapKind,
131
- dst_path: str,
132
- tmp_path: str,
133
- **kwargs: ta.Any,
134
- ) -> None:
135
- if kind == 'dir':
136
- check.state(os.path.isdir(tmp_path))
137
- elif kind == 'file':
138
- check.state(os.path.isfile(tmp_path))
139
- else:
140
- raise TypeError(kind)
141
-
142
- super().__init__(
143
- kind,
144
- dst_path,
145
- **kwargs,
146
- )
147
-
148
- self._tmp_path = tmp_path
149
-
150
- @property
151
- def tmp_path(self) -> str:
152
- return self._tmp_path
153
-
154
- def _commit(self) -> None:
155
- os.rename(self._tmp_path, self._dst_path)
156
-
157
- def _abort(self) -> None:
158
- shutil.rmtree(self._tmp_path, ignore_errors=True)
159
-
160
-
161
- class TempDirDeployAtomicPathSwapping(DeployAtomicPathSwapping):
162
- def __init__(
163
- self,
164
- *,
165
- temp_dir: ta.Optional[str] = None,
166
- root_dir: ta.Optional[str] = None,
167
- ) -> None:
168
- super().__init__()
169
-
170
- if root_dir is not None:
171
- root_dir = os.path.abspath(root_dir)
172
- self._root_dir = root_dir
173
- self._temp_dir = temp_dir
174
-
175
- def begin_atomic_path_swap(
176
- self,
177
- kind: DeployAtomicPathSwapKind,
178
- dst_path: str,
179
- *,
180
- name_hint: ta.Optional[str] = None,
181
- make_dirs: bool = False,
182
- **kwargs: ta.Any,
183
- ) -> DeployAtomicPathSwap:
184
- dst_path = os.path.abspath(dst_path)
185
- if self._root_dir is not None and not dst_path.startswith(check.non_empty_str(self._root_dir)):
186
- raise RuntimeError(f'Atomic path swap dst must be in root dir: {dst_path}, {self._root_dir}')
187
-
188
- dst_dir = os.path.dirname(dst_path)
189
- if make_dirs:
190
- os.makedirs(dst_dir, exist_ok=True)
191
- if not os.path.isdir(dst_dir):
192
- raise RuntimeError(f'Atomic path swap dst dir does not exist: {dst_dir}')
193
-
194
- if kind == 'dir':
195
- tmp_path = tempfile.mkdtemp(prefix=name_hint, dir=self._temp_dir)
196
- elif kind == 'file':
197
- fd, tmp_path = tempfile.mkstemp(prefix=name_hint, dir=self._temp_dir)
198
- os.close(fd)
199
- else:
200
- raise TypeError(kind)
201
-
202
- return OsRenameDeployAtomicPathSwap(
203
- kind,
204
- dst_path,
205
- tmp_path,
206
- **kwargs,
207
- )