ominfra 0.0.0.dev170__py3-none-any.whl → 0.0.0.dev171__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.
@@ -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,,