ominfra 0.0.0.dev160__py3-none-any.whl → 0.0.0.dev162__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
  """
@@ -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
- )