ominfra 0.0.0.dev160__py3-none-any.whl → 0.0.0.dev162__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.
@@ -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
  """
@@ -5687,7 +5489,7 @@ class InjectorBinder:
5687
5489
  def __new__(cls, *args, **kwargs): # noqa
5688
5490
  raise TypeError
5689
5491
 
5690
- _FN_TYPES: ta.Tuple[type, ...] = (
5492
+ _FN_TYPES: ta.ClassVar[ta.Tuple[type, ...]] = (
5691
5493
  types.FunctionType,
5692
5494
  types.MethodType,
5693
5495
 
@@ -5709,7 +5511,7 @@ class InjectorBinder:
5709
5511
  cls._FN_TYPES = (*cls._FN_TYPES, icls)
5710
5512
  return icls
5711
5513
 
5712
- _BANNED_BIND_TYPES: ta.Tuple[type, ...] = (
5514
+ _BANNED_BIND_TYPES: ta.ClassVar[ta.Tuple[type, ...]] = (
5713
5515
  InjectorProvider,
5714
5516
  )
5715
5517
 
@@ -5888,45 +5690,35 @@ def bind_injector_eager_key(key: ta.Any) -> InjectorBinding:
5888
5690
  ##
5889
5691
 
5890
5692
 
5891
- class Injection:
5892
- def __new__(cls, *args, **kwargs): # noqa
5893
- raise TypeError
5894
-
5693
+ class InjectionApi:
5895
5694
  # keys
5896
5695
 
5897
- @classmethod
5898
- def as_key(cls, o: ta.Any) -> InjectorKey:
5696
+ def as_key(self, o: ta.Any) -> InjectorKey:
5899
5697
  return as_injector_key(o)
5900
5698
 
5901
- @classmethod
5902
- def array(cls, o: ta.Any) -> InjectorKey:
5699
+ def array(self, o: ta.Any) -> InjectorKey:
5903
5700
  return dc.replace(as_injector_key(o), array=True)
5904
5701
 
5905
- @classmethod
5906
- def tag(cls, o: ta.Any, t: ta.Any) -> InjectorKey:
5702
+ def tag(self, o: ta.Any, t: ta.Any) -> InjectorKey:
5907
5703
  return dc.replace(as_injector_key(o), tag=t)
5908
5704
 
5909
5705
  # bindings
5910
5706
 
5911
- @classmethod
5912
- def as_bindings(cls, *args: InjectorBindingOrBindings) -> InjectorBindings:
5707
+ def as_bindings(self, *args: InjectorBindingOrBindings) -> InjectorBindings:
5913
5708
  return as_injector_bindings(*args)
5914
5709
 
5915
- @classmethod
5916
- def override(cls, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
5710
+ def override(self, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
5917
5711
  return injector_override(p, *args)
5918
5712
 
5919
5713
  # injector
5920
5714
 
5921
- @classmethod
5922
- def create_injector(cls, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
5715
+ def create_injector(self, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
5923
5716
  return _Injector(as_injector_bindings(*args), parent)
5924
5717
 
5925
5718
  # binder
5926
5719
 
5927
- @classmethod
5928
5720
  def bind(
5929
- cls,
5721
+ self,
5930
5722
  obj: ta.Any,
5931
5723
  *,
5932
5724
  key: ta.Any = None,
@@ -5961,35 +5753,32 @@ class Injection:
5961
5753
 
5962
5754
  # helpers
5963
5755
 
5964
- @classmethod
5965
5756
  def bind_factory(
5966
- cls,
5757
+ self,
5967
5758
  fn: ta.Callable[..., T],
5968
5759
  cls_: U,
5969
5760
  ann: ta.Any = None,
5970
5761
  ) -> InjectorBindingOrBindings:
5971
- return cls.bind(make_injector_factory(fn, cls_, ann))
5762
+ return self.bind(make_injector_factory(fn, cls_, ann))
5972
5763
 
5973
- @classmethod
5974
5764
  def bind_array(
5975
- cls,
5765
+ self,
5976
5766
  obj: ta.Any = None,
5977
5767
  *,
5978
5768
  tag: ta.Any = None,
5979
5769
  ) -> InjectorBindingOrBindings:
5980
5770
  return bind_injector_array(obj, tag=tag)
5981
5771
 
5982
- @classmethod
5983
5772
  def bind_array_type(
5984
- cls,
5773
+ self,
5985
5774
  ele: ta.Union[InjectorKey, InjectorKeyCls],
5986
5775
  cls_: U,
5987
5776
  ann: ta.Any = None,
5988
5777
  ) -> InjectorBindingOrBindings:
5989
- return cls.bind(make_injector_array_type(ele, cls_, ann))
5778
+ return self.bind(make_injector_array_type(ele, cls_, ann))
5990
5779
 
5991
5780
 
5992
- inj = Injection
5781
+ inj = InjectionApi()
5993
5782
 
5994
5783
 
5995
5784
  ########################################
@@ -6516,6 +6305,201 @@ class JsonLogFormatter(logging.Formatter):
6516
6305
  return self._json_dumps(dct)
6517
6306
 
6518
6307
 
6308
+ ########################################
6309
+ # ../../../omlish/os/atomics.py
6310
+
6311
+
6312
+ ##
6313
+
6314
+
6315
+ class AtomicPathSwap(abc.ABC):
6316
+ def __init__(
6317
+ self,
6318
+ kind: AtomicPathSwapKind,
6319
+ dst_path: str,
6320
+ *,
6321
+ auto_commit: bool = False,
6322
+ ) -> None:
6323
+ super().__init__()
6324
+
6325
+ self._kind = kind
6326
+ self._dst_path = dst_path
6327
+ self._auto_commit = auto_commit
6328
+
6329
+ self._state: AtomicPathSwapState = 'open'
6330
+
6331
+ def __repr__(self) -> str:
6332
+ return attr_repr(self, 'kind', 'dst_path', 'tmp_path')
6333
+
6334
+ @property
6335
+ def kind(self) -> AtomicPathSwapKind:
6336
+ return self._kind
6337
+
6338
+ @property
6339
+ def dst_path(self) -> str:
6340
+ return self._dst_path
6341
+
6342
+ @property
6343
+ @abc.abstractmethod
6344
+ def tmp_path(self) -> str:
6345
+ raise NotImplementedError
6346
+
6347
+ #
6348
+
6349
+ @property
6350
+ def state(self) -> AtomicPathSwapState:
6351
+ return self._state
6352
+
6353
+ def _check_state(self, *states: AtomicPathSwapState) -> None:
6354
+ if self._state not in states:
6355
+ raise RuntimeError(f'Atomic path swap not in correct state: {self._state}, {states}')
6356
+
6357
+ #
6358
+
6359
+ @abc.abstractmethod
6360
+ def _commit(self) -> None:
6361
+ raise NotImplementedError
6362
+
6363
+ def commit(self) -> None:
6364
+ if self._state == 'committed':
6365
+ return
6366
+ self._check_state('open')
6367
+ try:
6368
+ self._commit()
6369
+ except Exception: # noqa
6370
+ self._abort()
6371
+ raise
6372
+ else:
6373
+ self._state = 'committed'
6374
+
6375
+ #
6376
+
6377
+ @abc.abstractmethod
6378
+ def _abort(self) -> None:
6379
+ raise NotImplementedError
6380
+
6381
+ def abort(self) -> None:
6382
+ if self._state == 'aborted':
6383
+ return
6384
+ self._abort()
6385
+ self._state = 'aborted'
6386
+
6387
+ #
6388
+
6389
+ def __enter__(self) -> 'AtomicPathSwap':
6390
+ return self
6391
+
6392
+ def __exit__(self, exc_type, exc_val, exc_tb):
6393
+ if (
6394
+ exc_type is None and
6395
+ self._auto_commit and
6396
+ self._state == 'open'
6397
+ ):
6398
+ self.commit()
6399
+ else:
6400
+ self.abort()
6401
+
6402
+
6403
+ class AtomicPathSwapping(abc.ABC):
6404
+ @abc.abstractmethod
6405
+ def begin_atomic_path_swap(
6406
+ self,
6407
+ kind: AtomicPathSwapKind,
6408
+ dst_path: str,
6409
+ *,
6410
+ name_hint: ta.Optional[str] = None,
6411
+ make_dirs: bool = False,
6412
+ **kwargs: ta.Any,
6413
+ ) -> AtomicPathSwap:
6414
+ raise NotImplementedError
6415
+
6416
+
6417
+ ##
6418
+
6419
+
6420
+ class OsRenameAtomicPathSwap(AtomicPathSwap):
6421
+ def __init__(
6422
+ self,
6423
+ kind: AtomicPathSwapKind,
6424
+ dst_path: str,
6425
+ tmp_path: str,
6426
+ **kwargs: ta.Any,
6427
+ ) -> None:
6428
+ if kind == 'dir':
6429
+ check.state(os.path.isdir(tmp_path))
6430
+ elif kind == 'file':
6431
+ check.state(os.path.isfile(tmp_path))
6432
+ else:
6433
+ raise TypeError(kind)
6434
+
6435
+ super().__init__(
6436
+ kind,
6437
+ dst_path,
6438
+ **kwargs,
6439
+ )
6440
+
6441
+ self._tmp_path = tmp_path
6442
+
6443
+ @property
6444
+ def tmp_path(self) -> str:
6445
+ return self._tmp_path
6446
+
6447
+ def _commit(self) -> None:
6448
+ os.rename(self._tmp_path, self._dst_path)
6449
+
6450
+ def _abort(self) -> None:
6451
+ shutil.rmtree(self._tmp_path, ignore_errors=True)
6452
+
6453
+
6454
+ class TempDirAtomicPathSwapping(AtomicPathSwapping):
6455
+ def __init__(
6456
+ self,
6457
+ *,
6458
+ temp_dir: ta.Optional[str] = None,
6459
+ root_dir: ta.Optional[str] = None,
6460
+ ) -> None:
6461
+ super().__init__()
6462
+
6463
+ if root_dir is not None:
6464
+ root_dir = os.path.abspath(root_dir)
6465
+ self._root_dir = root_dir
6466
+ self._temp_dir = temp_dir
6467
+
6468
+ def begin_atomic_path_swap(
6469
+ self,
6470
+ kind: AtomicPathSwapKind,
6471
+ dst_path: str,
6472
+ *,
6473
+ name_hint: ta.Optional[str] = None,
6474
+ make_dirs: bool = False,
6475
+ **kwargs: ta.Any,
6476
+ ) -> AtomicPathSwap:
6477
+ dst_path = os.path.abspath(dst_path)
6478
+ if self._root_dir is not None and not dst_path.startswith(check.non_empty_str(self._root_dir)):
6479
+ raise RuntimeError(f'Atomic path swap dst must be in root dir: {dst_path}, {self._root_dir}')
6480
+
6481
+ dst_dir = os.path.dirname(dst_path)
6482
+ if make_dirs:
6483
+ os.makedirs(dst_dir, exist_ok=True)
6484
+ if not os.path.isdir(dst_dir):
6485
+ raise RuntimeError(f'Atomic path swap dst dir does not exist: {dst_dir}')
6486
+
6487
+ if kind == 'dir':
6488
+ tmp_path = tempfile.mkdtemp(prefix=name_hint, dir=self._temp_dir)
6489
+ elif kind == 'file':
6490
+ fd, tmp_path = tempfile.mkstemp(prefix=name_hint, dir=self._temp_dir)
6491
+ os.close(fd)
6492
+ else:
6493
+ raise TypeError(kind)
6494
+
6495
+ return OsRenameAtomicPathSwap(
6496
+ kind,
6497
+ dst_path,
6498
+ tmp_path,
6499
+ **kwargs,
6500
+ )
6501
+
6502
+
6519
6503
  ########################################
6520
6504
  # ../../../omdev/interp/types.py
6521
6505
 
@@ -6752,7 +6736,7 @@ CommandExecutorMap = ta.NewType('CommandExecutorMap', ta.Mapping[ta.Type[Command
6752
6736
 
6753
6737
  class DeployTmpManager(
6754
6738
  SingleDirDeployPathOwner,
6755
- DeployAtomicPathSwapping,
6739
+ AtomicPathSwapping,
6756
6740
  ):
6757
6741
  def __init__(
6758
6742
  self,
@@ -6765,18 +6749,18 @@ class DeployTmpManager(
6765
6749
  )
6766
6750
 
6767
6751
  @cached_nullary
6768
- def _swapping(self) -> DeployAtomicPathSwapping:
6769
- return TempDirDeployAtomicPathSwapping(
6752
+ def _swapping(self) -> AtomicPathSwapping:
6753
+ return TempDirAtomicPathSwapping(
6770
6754
  temp_dir=self._make_dir(),
6771
6755
  root_dir=check.non_empty_str(self._deploy_home),
6772
6756
  )
6773
6757
 
6774
6758
  def begin_atomic_path_swap(
6775
6759
  self,
6776
- kind: DeployAtomicPathSwapKind,
6760
+ kind: AtomicPathSwapKind,
6777
6761
  dst_path: str,
6778
6762
  **kwargs: ta.Any,
6779
- ) -> DeployAtomicPathSwap:
6763
+ ) -> AtomicPathSwap:
6780
6764
  return self._swapping().begin_atomic_path_swap(
6781
6765
  kind,
6782
6766
  dst_path,
@@ -8175,7 +8159,7 @@ class DeployGitManager(SingleDirDeployPathOwner):
8175
8159
  self,
8176
8160
  *,
8177
8161
  deploy_home: ta.Optional[DeployHome] = None,
8178
- atomics: DeployAtomicPathSwapping,
8162
+ atomics: AtomicPathSwapping,
8179
8163
  ) -> None:
8180
8164
  super().__init__(
8181
8165
  owned_dir='git',
@@ -8280,7 +8264,7 @@ class DeployVenvManager(DeployPathOwner):
8280
8264
  self,
8281
8265
  *,
8282
8266
  deploy_home: ta.Optional[DeployHome] = None,
8283
- atomics: DeployAtomicPathSwapping,
8267
+ atomics: AtomicPathSwapping,
8284
8268
  ) -> None:
8285
8269
  super().__init__()
8286
8270
 
@@ -9824,7 +9808,7 @@ class DockerManageTargetConnector(ManageTargetConnector):
9824
9808
  if dmt.image is not None:
9825
9809
  sh_parts.extend(['run', '-i', dmt.image])
9826
9810
  elif dmt.container_id is not None:
9827
- sh_parts.extend(['exec', dmt.container_id])
9811
+ sh_parts.extend(['exec', '-i', dmt.container_id])
9828
9812
  else:
9829
9813
  raise ValueError(dmt)
9830
9814
 
@@ -10044,7 +10028,7 @@ def bind_deploy(
10044
10028
  inj.bind(DeployGitManager, singleton=True),
10045
10029
 
10046
10030
  inj.bind(DeployTmpManager, singleton=True),
10047
- inj.bind(DeployAtomicPathSwapping, to_key=DeployTmpManager),
10031
+ inj.bind(AtomicPathSwapping, to_key=DeployTmpManager),
10048
10032
 
10049
10033
  inj.bind(DeployVenvManager, singleton=True),
10050
10034
 
@@ -4548,7 +4548,7 @@ class InjectorBinder:
4548
4548
  def __new__(cls, *args, **kwargs): # noqa
4549
4549
  raise TypeError
4550
4550
 
4551
- _FN_TYPES: ta.Tuple[type, ...] = (
4551
+ _FN_TYPES: ta.ClassVar[ta.Tuple[type, ...]] = (
4552
4552
  types.FunctionType,
4553
4553
  types.MethodType,
4554
4554
 
@@ -4570,7 +4570,7 @@ class InjectorBinder:
4570
4570
  cls._FN_TYPES = (*cls._FN_TYPES, icls)
4571
4571
  return icls
4572
4572
 
4573
- _BANNED_BIND_TYPES: ta.Tuple[type, ...] = (
4573
+ _BANNED_BIND_TYPES: ta.ClassVar[ta.Tuple[type, ...]] = (
4574
4574
  InjectorProvider,
4575
4575
  )
4576
4576
 
@@ -4749,45 +4749,35 @@ def bind_injector_eager_key(key: ta.Any) -> InjectorBinding:
4749
4749
  ##
4750
4750
 
4751
4751
 
4752
- class Injection:
4753
- def __new__(cls, *args, **kwargs): # noqa
4754
- raise TypeError
4755
-
4752
+ class InjectionApi:
4756
4753
  # keys
4757
4754
 
4758
- @classmethod
4759
- def as_key(cls, o: ta.Any) -> InjectorKey:
4755
+ def as_key(self, o: ta.Any) -> InjectorKey:
4760
4756
  return as_injector_key(o)
4761
4757
 
4762
- @classmethod
4763
- def array(cls, o: ta.Any) -> InjectorKey:
4758
+ def array(self, o: ta.Any) -> InjectorKey:
4764
4759
  return dc.replace(as_injector_key(o), array=True)
4765
4760
 
4766
- @classmethod
4767
- def tag(cls, o: ta.Any, t: ta.Any) -> InjectorKey:
4761
+ def tag(self, o: ta.Any, t: ta.Any) -> InjectorKey:
4768
4762
  return dc.replace(as_injector_key(o), tag=t)
4769
4763
 
4770
4764
  # bindings
4771
4765
 
4772
- @classmethod
4773
- def as_bindings(cls, *args: InjectorBindingOrBindings) -> InjectorBindings:
4766
+ def as_bindings(self, *args: InjectorBindingOrBindings) -> InjectorBindings:
4774
4767
  return as_injector_bindings(*args)
4775
4768
 
4776
- @classmethod
4777
- def override(cls, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
4769
+ def override(self, p: InjectorBindings, *args: InjectorBindingOrBindings) -> InjectorBindings:
4778
4770
  return injector_override(p, *args)
4779
4771
 
4780
4772
  # injector
4781
4773
 
4782
- @classmethod
4783
- def create_injector(cls, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
4774
+ def create_injector(self, *args: InjectorBindingOrBindings, parent: ta.Optional[Injector] = None) -> Injector:
4784
4775
  return _Injector(as_injector_bindings(*args), parent)
4785
4776
 
4786
4777
  # binder
4787
4778
 
4788
- @classmethod
4789
4779
  def bind(
4790
- cls,
4780
+ self,
4791
4781
  obj: ta.Any,
4792
4782
  *,
4793
4783
  key: ta.Any = None,
@@ -4822,35 +4812,32 @@ class Injection:
4822
4812
 
4823
4813
  # helpers
4824
4814
 
4825
- @classmethod
4826
4815
  def bind_factory(
4827
- cls,
4816
+ self,
4828
4817
  fn: ta.Callable[..., T],
4829
4818
  cls_: U,
4830
4819
  ann: ta.Any = None,
4831
4820
  ) -> InjectorBindingOrBindings:
4832
- return cls.bind(make_injector_factory(fn, cls_, ann))
4821
+ return self.bind(make_injector_factory(fn, cls_, ann))
4833
4822
 
4834
- @classmethod
4835
4823
  def bind_array(
4836
- cls,
4824
+ self,
4837
4825
  obj: ta.Any = None,
4838
4826
  *,
4839
4827
  tag: ta.Any = None,
4840
4828
  ) -> InjectorBindingOrBindings:
4841
4829
  return bind_injector_array(obj, tag=tag)
4842
4830
 
4843
- @classmethod
4844
4831
  def bind_array_type(
4845
- cls,
4832
+ self,
4846
4833
  ele: ta.Union[InjectorKey, InjectorKeyCls],
4847
4834
  cls_: U,
4848
4835
  ann: ta.Any = None,
4849
4836
  ) -> InjectorBindingOrBindings:
4850
- return cls.bind(make_injector_array_type(ele, cls_, ann))
4837
+ return self.bind(make_injector_array_type(ele, cls_, ann))
4851
4838
 
4852
4839
 
4853
- inj = Injection
4840
+ inj = InjectionApi()
4854
4841
 
4855
4842
 
4856
4843
  ########################################
@@ -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.dev162
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.dev162
16
+ Requires-Dist: omlish==0.0.0.dev162
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,13 +71,13 @@ 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
81
- ominfra/scripts/supervisor.py,sha256=npGYEWSZfY7E24mdkJ3HrL_ax6AcqjHfqh-7nZ_sX0U,273987
79
+ ominfra/scripts/manage.py,sha256=mslFxApTHF_954w462BIpZdk9V1oy02fJhcN1N1-Wf4,293592
80
+ ominfra/scripts/supervisor.py,sha256=uPcw4o8gt8xvQ97jXK-WBAaZj3D81Lq9tqDoKxGvLCU,273791
82
81
  ominfra/supervisor/LICENSE.txt,sha256=yvqaMNsDhWxziHa9ien6qCW1SkZv-DQlAg96XjfSee8,1746
83
82
  ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
84
83
  ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
@@ -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.dev162.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
123
+ ominfra-0.0.0.dev162.dist-info/METADATA,sha256=tmh0OqIMABojtwp_fUbGyKMod6s85abgUC2tuyhS30Q,731
124
+ ominfra-0.0.0.dev162.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
125
+ ominfra-0.0.0.dev162.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
126
+ ominfra-0.0.0.dev162.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
127
+ ominfra-0.0.0.dev162.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
- )