ominfra 0.0.0.dev170__py3-none-any.whl → 0.0.0.dev171__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  import datetime
3
3
  import os.path
4
+ import shutil
4
5
  import typing as ta
5
6
 
6
7
  from omlish.lite.cached import cached_nullary
@@ -142,6 +143,39 @@ class DeployAppManager(DeployPathOwner):
142
143
 
143
144
  #
144
145
 
146
+ def mirror_symlinks(src: str, dst: str) -> None:
147
+ def mirror_link(lp: str) -> None:
148
+ check.state(os.path.islink(lp))
149
+ shutil.copy2(
150
+ lp,
151
+ os.path.join(dst, os.path.relpath(lp, src)),
152
+ follow_symlinks=False,
153
+ )
154
+
155
+ for dp, dns, fns in os.walk(src, followlinks=False):
156
+ for fn in fns:
157
+ mirror_link(os.path.join(dp, fn))
158
+
159
+ for dn in dns:
160
+ dp2 = os.path.join(dp, dn)
161
+ if os.path.islink(dp2):
162
+ mirror_link(dp2)
163
+ else:
164
+ os.makedirs(os.path.join(dst, os.path.relpath(dp2, src)))
165
+
166
+ current_link = os.path.join(deploy_home, 'deploys/current')
167
+ # if os.path.exists(current_link):
168
+ # mirror_symlinks(
169
+ # os.path.join(current_link, 'conf'),
170
+ # conf_tag_dir,
171
+ # )
172
+ # mirror_symlinks(
173
+ # os.path.join(current_link, 'apps'),
174
+ # os.path.join(deploy_dir, 'apps'),
175
+ # )
176
+
177
+ #
178
+
145
179
  git_dir = os.path.join(app_tag_dir, 'git')
146
180
  await self._git.checkout(
147
181
  spec.git,
@@ -171,5 +205,4 @@ class DeployAppManager(DeployPathOwner):
171
205
 
172
206
  #
173
207
 
174
- current_link = os.path.join(deploy_home, 'deploys/current')
175
208
  os.replace(deploying_link, current_link)
@@ -9,6 +9,7 @@ import typing as ta
9
9
 
10
10
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
11
11
  from omlish.lite.check import check
12
+ from omlish.lite.shlex import shlex_maybe_quote
12
13
  from omlish.subprocesses import SUBPROCESS_CHANNEL_OPTION_VALUES
13
14
  from omlish.subprocesses import SubprocessChannelOption
14
15
 
@@ -22,11 +23,14 @@ class RemoteSpawning(abc.ABC):
22
23
  shell: ta.Optional[str] = None
23
24
  shell_quote: bool = False
24
25
 
25
- DEFAULT_PYTHON: ta.ClassVar[str] = 'python3'
26
- python: str = DEFAULT_PYTHON
26
+ DEFAULT_PYTHON: ta.ClassVar[ta.Sequence[str]] = ('python3',)
27
+ python: ta.Sequence[str] = DEFAULT_PYTHON
27
28
 
28
29
  stderr: ta.Optional[str] = None # SubprocessChannelOption
29
30
 
31
+ def __post_init__(self) -> None:
32
+ check.not_isinstance(self.python, str)
33
+
30
34
  @dc.dataclass(frozen=True)
31
35
  class Spawned:
32
36
  stdin: asyncio.StreamWriter
@@ -59,14 +63,18 @@ class SubprocessRemoteSpawning(RemoteSpawning):
59
63
  src: str,
60
64
  ) -> _PreparedCmd:
61
65
  if tgt.shell is not None:
62
- sh_src = f'{tgt.python} -c {shlex.quote(src)}'
66
+ sh_src = ' '.join([
67
+ *map(shlex_maybe_quote, tgt.python),
68
+ '-c',
69
+ shlex_maybe_quote(src),
70
+ ])
63
71
  if tgt.shell_quote:
64
72
  sh_src = shlex.quote(sh_src)
65
73
  sh_cmd = f'{tgt.shell} {sh_src}'
66
74
  return SubprocessRemoteSpawning._PreparedCmd([sh_cmd], shell=True)
67
75
 
68
76
  else:
69
- return SubprocessRemoteSpawning._PreparedCmd([tgt.python, '-c', src], shell=False)
77
+ return SubprocessRemoteSpawning._PreparedCmd([*tgt.python, '-c', src], shell=False)
70
78
 
71
79
  #
72
80
 
@@ -0,0 +1,29 @@
1
+ import io
2
+
3
+ from omlish.lite.cached import cached_nullary
4
+ from omlish.lite.resources import read_package_resource_text
5
+
6
+
7
+ BEST_PYTHON_SH = read_package_resource_text(__package__, 'bestpython.sh')
8
+
9
+
10
+ @cached_nullary
11
+ def get_best_python_sh() -> str:
12
+ buf = io.StringIO()
13
+
14
+ for l in BEST_PYTHON_SH.strip().splitlines():
15
+ if not (l := l.strip()):
16
+ continue
17
+
18
+ buf.write(l)
19
+
20
+ if l.split()[-1] not in ('do', 'then', 'else'):
21
+ buf.write(';')
22
+
23
+ buf.write(' ')
24
+
25
+ return buf.getvalue().strip(' ;')
26
+
27
+
28
+ if __name__ == '__main__':
29
+ print(__import__('shlex').quote(get_best_python_sh()))
@@ -0,0 +1,21 @@
1
+ bv=""
2
+ bx=""
3
+
4
+ for version in "" 3 3.{8..13}; do
5
+ x="python$version"
6
+ v=$($x -c "import sys; print(sys.version_info[:])" 2>/dev/null)
7
+ if [ $? -eq 0 ]; then
8
+ cv=$(echo $v | tr -d "(), ")
9
+ if [ -z "$bv" ] || [ "$cv" \> "$bv" ]; then
10
+ bv=$cv
11
+ bx=$x
12
+ fi
13
+ fi
14
+ done
15
+
16
+ if [ -z "$bx" ]; then
17
+ echo "no python" >&2
18
+ exit 1
19
+ fi
20
+
21
+ exec "$bx" "$@"
@@ -12,6 +12,7 @@ from ..commands.local import LocalCommandExecutor
12
12
  from ..remote.connection import InProcessRemoteExecutionConnector
13
13
  from ..remote.connection import PyremoteRemoteExecutionConnector
14
14
  from ..remote.spawning import RemoteSpawning
15
+ from .bestpython import get_best_python_sh
15
16
  from .targets import DockerManageTarget
16
17
  from .targets import InProcessManageTarget
17
18
  from .targets import LocalManageTarget
@@ -28,6 +29,13 @@ class ManageTargetConnector(abc.ABC):
28
29
  def connect(self, tgt: ManageTarget) -> ta.AsyncContextManager[CommandExecutor]:
29
30
  raise NotImplementedError
30
31
 
32
+ def _default_python(self, python: ta.Optional[ta.Sequence[str]]) -> ta.Sequence[str]:
33
+ check.not_isinstance(python, str)
34
+ if python is not None:
35
+ return python
36
+ else:
37
+ return ['sh', '-c', get_best_python_sh(), '--']
38
+
31
39
 
32
40
  ##
33
41
 
@@ -79,7 +87,7 @@ class LocalManageTargetConnector(ManageTargetConnector):
79
87
  elif isinstance(lmt, SubprocessManageTarget):
80
88
  async with self._pyremote_connector.connect(
81
89
  RemoteSpawning.Target(
82
- python=lmt.python,
90
+ python=self._default_python(lmt.python),
83
91
  ),
84
92
  self._bootstrap,
85
93
  ) as rce:
@@ -112,7 +120,7 @@ class DockerManageTargetConnector(ManageTargetConnector):
112
120
  async with self._pyremote_connector.connect(
113
121
  RemoteSpawning.Target(
114
122
  shell=' '.join(sh_parts),
115
- python=dmt.python,
123
+ python=self._default_python(dmt.python),
116
124
  ),
117
125
  self._bootstrap,
118
126
  ) as rce:
@@ -143,7 +151,7 @@ class SshManageTargetConnector(ManageTargetConnector):
143
151
  RemoteSpawning.Target(
144
152
  shell=' '.join(sh_parts),
145
153
  shell_quote=True,
146
- python=smt.python,
154
+ python=self._default_python(smt.python),
147
155
  ),
148
156
  self._bootstrap,
149
157
  ) as rce:
@@ -26,8 +26,11 @@ class ManageTarget(abc.ABC): # noqa
26
26
 
27
27
  @dc.dataclass(frozen=True)
28
28
  class PythonRemoteManageTarget:
29
- DEFAULT_PYTHON: ta.ClassVar[str] = 'python3'
30
- python: str = DEFAULT_PYTHON
29
+ DEFAULT_PYTHON: ta.ClassVar[ta.Optional[ta.Sequence[str]]] = None
30
+ python: ta.Optional[ta.Sequence[str]] = DEFAULT_PYTHON
31
+
32
+ def __post_init__(self) -> None:
33
+ check.not_isinstance(self.python, str)
31
34
 
32
35
 
33
36
  #
ominfra/pyremote.py CHANGED
@@ -256,11 +256,13 @@ def pyremote_build_bootstrap_cmd(context_name: str) -> str:
256
256
 
257
257
  bs_z = zlib.compress(bs_src.encode('utf-8'), 9)
258
258
  bs_z85 = base64.b85encode(bs_z).replace(b'\n', b'')
259
+ if b'"' in bs_z85:
260
+ raise ValueError(bs_z85)
259
261
 
260
262
  stmts = [
261
263
  f'import {", ".join(_PYREMOTE_BOOTSTRAP_IMPORTS)}',
262
- f'exec(zlib.decompress(base64.b85decode({bs_z85!r})))',
263
- f'_pyremote_bootstrap_main({context_name!r})',
264
+ f'exec(zlib.decompress(base64.b85decode(b"{bs_z85.decode("ascii")}")))',
265
+ f'_pyremote_bootstrap_main("{context_name}")',
264
266
  ]
265
267
 
266
268
  cmd = '; '.join(stmts)
ominfra/scripts/manage.py CHANGED
@@ -26,6 +26,7 @@ import fractions
26
26
  import functools
27
27
  import hashlib
28
28
  import inspect
29
+ import io
29
30
  import itertools
30
31
  import json
31
32
  import logging
@@ -1626,11 +1627,13 @@ def pyremote_build_bootstrap_cmd(context_name: str) -> str:
1626
1627
 
1627
1628
  bs_z = zlib.compress(bs_src.encode('utf-8'), 9)
1628
1629
  bs_z85 = base64.b85encode(bs_z).replace(b'\n', b'')
1630
+ if b'"' in bs_z85:
1631
+ raise ValueError(bs_z85)
1629
1632
 
1630
1633
  stmts = [
1631
1634
  f'import {", ".join(_PYREMOTE_BOOTSTRAP_IMPORTS)}',
1632
- f'exec(zlib.decompress(base64.b85decode({bs_z85!r})))',
1633
- f'_pyremote_bootstrap_main({context_name!r})',
1635
+ f'exec(zlib.decompress(base64.b85decode(b"{bs_z85.decode("ascii")}")))',
1636
+ f'_pyremote_bootstrap_main("{context_name}")',
1634
1637
  ]
1635
1638
 
1636
1639
  cmd = '; '.join(stmts)
@@ -2693,6 +2696,35 @@ def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
2693
2696
  todo.extend(reversed(cur.__subclasses__()))
2694
2697
 
2695
2698
 
2699
+ ########################################
2700
+ # ../../../omlish/lite/resources.py
2701
+
2702
+
2703
+ def read_package_resource_binary(package: str, resource: str) -> bytes:
2704
+ import importlib.resources
2705
+ return importlib.resources.read_binary(package, resource)
2706
+
2707
+
2708
+ def read_package_resource_text(package: str, resource: str) -> str:
2709
+ import importlib.resources
2710
+ return importlib.resources.read_text(package, resource)
2711
+
2712
+
2713
+ ########################################
2714
+ # ../../../omlish/lite/shlex.py
2715
+
2716
+
2717
+ def shlex_needs_quote(s: str) -> bool:
2718
+ return bool(s) and len(list(shlex.shlex(s))) > 1
2719
+
2720
+
2721
+ def shlex_maybe_quote(s: str) -> str:
2722
+ if shlex_needs_quote(s):
2723
+ return shlex.quote(s)
2724
+ else:
2725
+ return s
2726
+
2727
+
2696
2728
  ########################################
2697
2729
  # ../../../omlish/lite/strings.py
2698
2730
 
@@ -4280,6 +4312,53 @@ def detect_system_platform() -> Platform:
4280
4312
  return platform
4281
4313
 
4282
4314
 
4315
+ ########################################
4316
+ # ../targets/bestpython.py
4317
+
4318
+
4319
+ BEST_PYTHON_SH = """\
4320
+ bv=""
4321
+ bx=""
4322
+
4323
+ for version in "" 3 3.{8..13}; do
4324
+ x="python$version"
4325
+ v=$($x -c "import sys; print(sys.version_info[:])" 2>/dev/null)
4326
+ if [ $? -eq 0 ]; then
4327
+ cv=$(echo $v | tr -d "(), ")
4328
+ if [ -z "$bv" ] || [ "$cv" \\> "$bv" ]; then
4329
+ bv=$cv
4330
+ bx=$x
4331
+ fi
4332
+ fi
4333
+ done
4334
+
4335
+ if [ -z "$bx" ]; then
4336
+ echo "no python" >&2
4337
+ exit 1
4338
+ fi
4339
+
4340
+ exec "$bx" "$@"
4341
+ """ # noqa
4342
+
4343
+
4344
+ @cached_nullary
4345
+ def get_best_python_sh() -> str:
4346
+ buf = io.StringIO()
4347
+
4348
+ for l in BEST_PYTHON_SH.strip().splitlines():
4349
+ if not (l := l.strip()):
4350
+ continue
4351
+
4352
+ buf.write(l)
4353
+
4354
+ if l.split()[-1] not in ('do', 'then', 'else'):
4355
+ buf.write(';')
4356
+
4357
+ buf.write(' ')
4358
+
4359
+ return buf.getvalue().strip(' ;')
4360
+
4361
+
4283
4362
  ########################################
4284
4363
  # ../targets/targets.py
4285
4364
  """
@@ -4303,8 +4382,11 @@ class ManageTarget(abc.ABC): # noqa
4303
4382
 
4304
4383
  @dc.dataclass(frozen=True)
4305
4384
  class PythonRemoteManageTarget:
4306
- DEFAULT_PYTHON: ta.ClassVar[str] = 'python3'
4307
- python: str = DEFAULT_PYTHON
4385
+ DEFAULT_PYTHON: ta.ClassVar[ta.Optional[ta.Sequence[str]]] = None
4386
+ python: ta.Optional[ta.Sequence[str]] = DEFAULT_PYTHON
4387
+
4388
+ def __post_init__(self) -> None:
4389
+ check.not_isinstance(self.python, str)
4308
4390
 
4309
4391
 
4310
4392
  #
@@ -8852,11 +8934,14 @@ class RemoteSpawning(abc.ABC):
8852
8934
  shell: ta.Optional[str] = None
8853
8935
  shell_quote: bool = False
8854
8936
 
8855
- DEFAULT_PYTHON: ta.ClassVar[str] = 'python3'
8856
- python: str = DEFAULT_PYTHON
8937
+ DEFAULT_PYTHON: ta.ClassVar[ta.Sequence[str]] = ('python3',)
8938
+ python: ta.Sequence[str] = DEFAULT_PYTHON
8857
8939
 
8858
8940
  stderr: ta.Optional[str] = None # SubprocessChannelOption
8859
8941
 
8942
+ def __post_init__(self) -> None:
8943
+ check.not_isinstance(self.python, str)
8944
+
8860
8945
  @dc.dataclass(frozen=True)
8861
8946
  class Spawned:
8862
8947
  stdin: asyncio.StreamWriter
@@ -8889,14 +8974,18 @@ class SubprocessRemoteSpawning(RemoteSpawning):
8889
8974
  src: str,
8890
8975
  ) -> _PreparedCmd:
8891
8976
  if tgt.shell is not None:
8892
- sh_src = f'{tgt.python} -c {shlex.quote(src)}'
8977
+ sh_src = ' '.join([
8978
+ *map(shlex_maybe_quote, tgt.python),
8979
+ '-c',
8980
+ shlex_maybe_quote(src),
8981
+ ])
8893
8982
  if tgt.shell_quote:
8894
8983
  sh_src = shlex.quote(sh_src)
8895
8984
  sh_cmd = f'{tgt.shell} {sh_src}'
8896
8985
  return SubprocessRemoteSpawning._PreparedCmd([sh_cmd], shell=True)
8897
8986
 
8898
8987
  else:
8899
- return SubprocessRemoteSpawning._PreparedCmd([tgt.python, '-c', src], shell=False)
8988
+ return SubprocessRemoteSpawning._PreparedCmd([*tgt.python, '-c', src], shell=False)
8900
8989
 
8901
8990
  #
8902
8991
 
@@ -9348,6 +9437,39 @@ class DeployAppManager(DeployPathOwner):
9348
9437
 
9349
9438
  #
9350
9439
 
9440
+ def mirror_symlinks(src: str, dst: str) -> None:
9441
+ def mirror_link(lp: str) -> None:
9442
+ check.state(os.path.islink(lp))
9443
+ shutil.copy2(
9444
+ lp,
9445
+ os.path.join(dst, os.path.relpath(lp, src)),
9446
+ follow_symlinks=False,
9447
+ )
9448
+
9449
+ for dp, dns, fns in os.walk(src, followlinks=False):
9450
+ for fn in fns:
9451
+ mirror_link(os.path.join(dp, fn))
9452
+
9453
+ for dn in dns:
9454
+ dp2 = os.path.join(dp, dn)
9455
+ if os.path.islink(dp2):
9456
+ mirror_link(dp2)
9457
+ else:
9458
+ os.makedirs(os.path.join(dst, os.path.relpath(dp2, src)))
9459
+
9460
+ current_link = os.path.join(deploy_home, 'deploys/current')
9461
+ # if os.path.exists(current_link):
9462
+ # mirror_symlinks(
9463
+ # os.path.join(current_link, 'conf'),
9464
+ # conf_tag_dir,
9465
+ # )
9466
+ # mirror_symlinks(
9467
+ # os.path.join(current_link, 'apps'),
9468
+ # os.path.join(deploy_dir, 'apps'),
9469
+ # )
9470
+
9471
+ #
9472
+
9351
9473
  git_dir = os.path.join(app_tag_dir, 'git')
9352
9474
  await self._git.checkout(
9353
9475
  spec.git,
@@ -9377,7 +9499,6 @@ class DeployAppManager(DeployPathOwner):
9377
9499
 
9378
9500
  #
9379
9501
 
9380
- current_link = os.path.join(deploy_home, 'deploys/current')
9381
9502
  os.replace(deploying_link, current_link)
9382
9503
 
9383
9504
 
@@ -10225,6 +10346,13 @@ class ManageTargetConnector(abc.ABC):
10225
10346
  def connect(self, tgt: ManageTarget) -> ta.AsyncContextManager[CommandExecutor]:
10226
10347
  raise NotImplementedError
10227
10348
 
10349
+ def _default_python(self, python: ta.Optional[ta.Sequence[str]]) -> ta.Sequence[str]:
10350
+ check.not_isinstance(python, str)
10351
+ if python is not None:
10352
+ return python
10353
+ else:
10354
+ return ['sh', '-c', get_best_python_sh(), '--']
10355
+
10228
10356
 
10229
10357
  ##
10230
10358
 
@@ -10276,7 +10404,7 @@ class LocalManageTargetConnector(ManageTargetConnector):
10276
10404
  elif isinstance(lmt, SubprocessManageTarget):
10277
10405
  async with self._pyremote_connector.connect(
10278
10406
  RemoteSpawning.Target(
10279
- python=lmt.python,
10407
+ python=self._default_python(lmt.python),
10280
10408
  ),
10281
10409
  self._bootstrap,
10282
10410
  ) as rce:
@@ -10309,7 +10437,7 @@ class DockerManageTargetConnector(ManageTargetConnector):
10309
10437
  async with self._pyremote_connector.connect(
10310
10438
  RemoteSpawning.Target(
10311
10439
  shell=' '.join(sh_parts),
10312
- python=dmt.python,
10440
+ python=self._default_python(dmt.python),
10313
10441
  ),
10314
10442
  self._bootstrap,
10315
10443
  ) as rce:
@@ -10340,7 +10468,7 @@ class SshManageTargetConnector(ManageTargetConnector):
10340
10468
  RemoteSpawning.Target(
10341
10469
  shell=' '.join(sh_parts),
10342
10470
  shell_quote=True,
10343
- python=smt.python,
10471
+ python=self._default_python(smt.python),
10344
10472
  ),
10345
10473
  self._bootstrap,
10346
10474
  ) as rce:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev170
3
+ Version: 0.0.0.dev171
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.dev170
16
- Requires-Dist: omlish==0.0.0.dev170
15
+ Requires-Dist: omdev==0.0.0.dev171
16
+ Requires-Dist: omlish==0.0.0.dev171
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -3,7 +3,7 @@ ominfra/__about__.py,sha256=6i1AoruFYQCd-PyhhbDQDWY2d1tiQu9nkwWr-fXAqfY,705
3
3
  ominfra/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  ominfra/cmds.py,sha256=E0AfnvEmnKntXWvmLW5L05_NeDpBET1VBXn7vV6EwBQ,2083
5
5
  ominfra/configs.py,sha256=fUjGcYTZDyWcIF0BkHBxkGz64S33DR5NP8tHIf3IaXk,2291
6
- ominfra/pyremote.py,sha256=YK21mzMMQIpEUGQtUU7n8H8MeSIC5kwFcOXgKXPAZOE,15124
6
+ ominfra/pyremote.py,sha256=HLfAZl3Xw5CpxLS5PS380zqCyE7n3vKVksIYT2Fbdc8,15197
7
7
  ominfra/ssh.py,sha256=jQpc4WvkMckIfk4vILda8zFaeharRqc_6wxW50b0OjQ,5431
8
8
  ominfra/threadworkers.py,sha256=oX4ubZn7h932saXpRIJu2MNhBExgGGMuGhdXarZxLJw,4948
9
9
  ominfra/clouds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -44,7 +44,7 @@ ominfra/manage/commands/ping.py,sha256=DVZFzL1Z_f-Bq53vxMrL3xOi0iK_nMonJE4KvQf9w
44
44
  ominfra/manage/commands/subprocess.py,sha256=yHGMbAI-xKe_9BUs5IZ3Yav8qRE-I9aGnBtTwW15Pnw,2440
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
- ominfra/manage/deploy/apps.py,sha256=HE2-ThrWR4wplT5hpPSQx0ERAkV-f58hj38al_FaZ7o,4457
47
+ ominfra/manage/deploy/apps.py,sha256=O8iLGeldK48SQp8JkWSBEA93X5o-EuR9-f15wDj-1Bc,5567
48
48
  ominfra/manage/deploy/commands.py,sha256=fKFKhFwqIqC_PsgA-W66qIJ5S32xRgBBaRt3lbPX5Zg,763
49
49
  ominfra/manage/deploy/conf.py,sha256=AvIZFNuURpS0mKZazr36oBMKi4kJDeTlt74JZmDrpcA,5227
50
50
  ominfra/manage/deploy/config.py,sha256=aR6ubMEWqkTI55XtcG1Cczn6YhCVN6eSL8DT5EHQJN0,166
@@ -69,7 +69,7 @@ ominfra/manage/remote/connection.py,sha256=T4fL-GXXAfnbCbkZ3_28t8LAwwki4Td3j41eY
69
69
  ominfra/manage/remote/execution.py,sha256=_bygZi_0Uel615uIg43S14CTdmv1unEIu9TPz2mVRJ4,11738
70
70
  ominfra/manage/remote/inject.py,sha256=nSNP_VInCCZOWVrUIRHBvLmnM45geFoYmMh-zqc__as,1080
71
71
  ominfra/manage/remote/payload.py,sha256=Rn-Yo26POpHEOOfUHX3jWkqcQVEAvkJ_5Bu13jwoob4,944
72
- ominfra/manage/remote/spawning.py,sha256=dXfJE-T3WdM4ATDQxhbJ7N8xgN4FwDD-JsCrRTl297M,3027
72
+ ominfra/manage/remote/spawning.py,sha256=CWeHBl4dzHLFLwJyFrt5hiAmhL0FaQzIYZ8j8EhI6VE,3301
73
73
  ominfra/manage/system/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
74
  ominfra/manage/system/commands.py,sha256=XrYvsxiwTJh17buIWmoFGH8zTUIXmrXvYkLy1INtmkU,1173
75
75
  ominfra/manage/system/config.py,sha256=mEVBL1cy4twO6F0bdnCI01Sm0xuLe1Z5eiAzCvbmoAc,196
@@ -77,12 +77,14 @@ ominfra/manage/system/inject.py,sha256=Ksc7Xw_Yh3lWwkTRxB2JCeOYO-nMyKj-Kssd1RDkR
77
77
  ominfra/manage/system/packages.py,sha256=HImCsgzXxcfzAoD2PjrstaSE_qgBWtTFUVb0lTEOxkI,4614
78
78
  ominfra/manage/system/platforms.py,sha256=F0bgYzUzCjZ2LbWVvnEq2ya_X_LfRW406LQYFL7bG44,1202
79
79
  ominfra/manage/targets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
- ominfra/manage/targets/connection.py,sha256=5e8h9Miej2DKJxZfLyxpGe8y-Y0V_b_AuUW159XVeJM,4643
80
+ ominfra/manage/targets/bestpython.py,sha256=6_CH_Vm9Am5aD5UV3m8uC-B8bvMNSjVIWicPmFw0aLI,631
81
+ ominfra/manage/targets/bestpython.sh,sha256=380kB4kdA1J2XZqcdmxNIOuxDP9ojtX-QSK3I6W85dM,392
82
+ ominfra/manage/targets/connection.py,sha256=rVI1YJxFClcF-sdttqWyIz9_XjPI01GUdwxYck0P1PA,5016
81
83
  ominfra/manage/targets/inject.py,sha256=P4597xWM-V3I_gCt2O71OLhYQkkXtuJvkYRsIbhhMcE,1561
82
- ominfra/manage/targets/targets.py,sha256=CFl8Uirgn3gfowO1Fn-LBK-6qYqEMFJ9snPUl0gCRuM,1753
84
+ ominfra/manage/targets/targets.py,sha256=7GP6UAZyJFEhpkJN6UQdpr_WN3p7C76v-s445y-WB6U,1885
83
85
  ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
84
86
  ominfra/scripts/journald2aws.py,sha256=OjbemVx-zyCBuWZVgTky66n2-MfyyS7ups4A9hsvHfA,155684
85
- ominfra/scripts/manage.py,sha256=Xq28GDDorMsopZqYqZ240lcn1IFCHZi5-YOjZAEXVFY,306243
87
+ ominfra/scripts/manage.py,sha256=p1Jl4so6Sz2oDJiR6t6Smv3QtE82X-OztYaXyqcyKZM,309660
86
88
  ominfra/scripts/supervisor.py,sha256=viYrsafRW5fLN2KUS1MtxCOm9CO4iOgIu60cmN3joSg,274450
87
89
  ominfra/supervisor/LICENSE.txt,sha256=yvqaMNsDhWxziHa9ien6qCW1SkZv-DQlAg96XjfSee8,1746
88
90
  ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -125,9 +127,9 @@ ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
125
127
  ominfra/tailscale/cli.py,sha256=h6akQJMl0KuWLHS7Ur6WcBZ2JwF0DJQhsPTnFBdGyNk,3571
126
128
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
127
129
  ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
128
- ominfra-0.0.0.dev170.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
129
- ominfra-0.0.0.dev170.dist-info/METADATA,sha256=Jf1wa_IsisZtBKdGJalcUP8gK5eD-86j7V51LwcOOXU,731
130
- ominfra-0.0.0.dev170.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
131
- ominfra-0.0.0.dev170.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
132
- ominfra-0.0.0.dev170.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
133
- ominfra-0.0.0.dev170.dist-info/RECORD,,
130
+ ominfra-0.0.0.dev171.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
131
+ ominfra-0.0.0.dev171.dist-info/METADATA,sha256=4laS68lV28814KDlS884shBLi-scgN6KtxdwFokQMO0,731
132
+ ominfra-0.0.0.dev171.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
133
+ ominfra-0.0.0.dev171.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
134
+ ominfra-0.0.0.dev171.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
135
+ ominfra-0.0.0.dev171.dist-info/RECORD,,