ominfra 0.0.0.dev159__tar.gz → 0.0.0.dev160__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. {ominfra-0.0.0.dev159/ominfra.egg-info → ominfra-0.0.0.dev160}/PKG-INFO +3 -3
  2. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/apps.py +3 -4
  3. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/commands.py +10 -1
  4. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/git.py +13 -6
  5. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/paths.py +7 -36
  6. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/specs.py +16 -2
  7. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/scripts/journald2aws.py +21 -9
  8. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/scripts/manage.py +87 -78
  9. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/scripts/supervisor.py +21 -9
  10. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160/ominfra.egg-info}/PKG-INFO +3 -3
  11. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra.egg-info/requires.txt +2 -2
  12. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/pyproject.toml +3 -3
  13. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/LICENSE +0 -0
  14. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/MANIFEST.in +0 -0
  15. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/README.rst +0 -0
  16. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/.manifests.json +0 -0
  17. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/__about__.py +0 -0
  18. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/__init__.py +0 -0
  19. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/__init__.py +0 -0
  20. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/__init__.py +0 -0
  21. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/__main__.py +0 -0
  22. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/auth.py +0 -0
  23. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/cli.py +0 -0
  24. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/dataclasses.py +0 -0
  25. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  26. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  27. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  28. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  29. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  30. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  31. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/logs.py +0 -0
  32. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/aws/metadata.py +0 -0
  33. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/gcp/__init__.py +0 -0
  34. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/clouds/gcp/auth.py +0 -0
  35. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/cmds.py +0 -0
  36. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/configs.py +0 -0
  37. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/journald/__init__.py +0 -0
  38. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/journald/fields.py +0 -0
  39. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/journald/genmessages.py +0 -0
  40. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/journald/messages.py +0 -0
  41. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/journald/tailer.py +0 -0
  42. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/__init__.py +0 -0
  43. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/__main__.py +0 -0
  44. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/bootstrap.py +0 -0
  45. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/bootstrap_.py +0 -0
  46. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/__init__.py +0 -0
  47. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/base.py +0 -0
  48. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/inject.py +0 -0
  49. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/local.py +0 -0
  50. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/marshal.py +0 -0
  51. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/ping.py +0 -0
  52. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/subprocess.py +0 -0
  53. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/commands/types.py +0 -0
  54. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/config.py +0 -0
  55. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/__init__.py +0 -0
  56. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/atomics.py +0 -0
  57. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/config.py +0 -0
  58. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/inject.py +0 -0
  59. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/interp.py +0 -0
  60. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/tmp.py +0 -0
  61. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/types.py +0 -0
  62. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/deploy/venvs.py +0 -0
  63. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/inject.py +0 -0
  64. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/main.py +0 -0
  65. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/marshal.py +0 -0
  66. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/__init__.py +0 -0
  67. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/_main.py +0 -0
  68. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/channel.py +0 -0
  69. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/config.py +0 -0
  70. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/connection.py +0 -0
  71. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/execution.py +0 -0
  72. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/inject.py +0 -0
  73. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/payload.py +0 -0
  74. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/remote/spawning.py +0 -0
  75. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/system/__init__.py +0 -0
  76. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/system/commands.py +0 -0
  77. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/system/config.py +0 -0
  78. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/system/inject.py +0 -0
  79. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/system/packages.py +0 -0
  80. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/system/platforms.py +0 -0
  81. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/targets/__init__.py +0 -0
  82. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/targets/connection.py +0 -0
  83. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/targets/inject.py +0 -0
  84. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/manage/targets/targets.py +0 -0
  85. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/pyremote.py +0 -0
  86. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/scripts/__init__.py +0 -0
  87. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/ssh.py +0 -0
  88. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/LICENSE.txt +0 -0
  89. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/__init__.py +0 -0
  90. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/__main__.py +0 -0
  91. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/configs.py +0 -0
  92. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/dispatchers.py +0 -0
  93. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/dispatchersimpl.py +0 -0
  94. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/events.py +0 -0
  95. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/exceptions.py +0 -0
  96. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/groups.py +0 -0
  97. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/groupsimpl.py +0 -0
  98. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/http.py +0 -0
  99. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/inject.py +0 -0
  100. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/io.py +0 -0
  101. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/main.py +0 -0
  102. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/pipes.py +0 -0
  103. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/privileges.py +0 -0
  104. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/process.py +0 -0
  105. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/processimpl.py +0 -0
  106. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/setup.py +0 -0
  107. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/setupimpl.py +0 -0
  108. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/signals.py +0 -0
  109. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/spawning.py +0 -0
  110. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/spawningimpl.py +0 -0
  111. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/states.py +0 -0
  112. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/supervisor.py +0 -0
  113. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/types.py +0 -0
  114. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/__init__.py +0 -0
  115. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/collections.py +0 -0
  116. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/diag.py +0 -0
  117. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/fds.py +0 -0
  118. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/fs.py +0 -0
  119. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/os.py +0 -0
  120. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/ostypes.py +0 -0
  121. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/signals.py +0 -0
  122. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/strings.py +0 -0
  123. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/supervisor/utils/users.py +0 -0
  124. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/tailscale/__init__.py +0 -0
  125. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/tailscale/api.py +0 -0
  126. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/tailscale/cli.py +0 -0
  127. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/threadworkers.py +0 -0
  128. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/tools/__init__.py +0 -0
  129. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra/tools/listresources.py +0 -0
  130. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra.egg-info/SOURCES.txt +0 -0
  131. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra.egg-info/dependency_links.txt +0 -0
  132. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra.egg-info/entry_points.txt +0 -0
  133. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/ominfra.egg-info/top_level.txt +0 -0
  134. {ominfra-0.0.0.dev159 → ominfra-0.0.0.dev160}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev159
3
+ Version: 0.0.0.dev160
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.dev159
16
- Requires-Dist: omlish==0.0.0.dev159
15
+ Requires-Dist: omdev==0.0.0.dev160
16
+ Requires-Dist: omlish==0.0.0.dev160
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -57,15 +57,14 @@ class DeployAppManager(DeployPathOwner):
57
57
  async def prepare_app(
58
58
  self,
59
59
  spec: DeploySpec,
60
- ):
61
- app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.rev, spec.key()))
60
+ ) -> None:
61
+ app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.checkout.rev, spec.key()))
62
62
  app_dir = os.path.join(self._dir(), spec.app, app_tag.tag)
63
63
 
64
64
  #
65
65
 
66
66
  await self._git.checkout(
67
- spec.repo,
68
- spec.rev,
67
+ spec.checkout,
69
68
  app_dir,
70
69
  )
71
70
 
@@ -5,6 +5,8 @@ from omlish.lite.logs import log
5
5
 
6
6
  from ..commands.base import Command
7
7
  from ..commands.base import CommandExecutor
8
+ from .apps import DeployAppManager
9
+ from .specs import DeploySpec
8
10
 
9
11
 
10
12
  ##
@@ -12,13 +14,20 @@ from ..commands.base import CommandExecutor
12
14
 
13
15
  @dc.dataclass(frozen=True)
14
16
  class DeployCommand(Command['DeployCommand.Output']):
17
+ spec: DeploySpec
18
+
15
19
  @dc.dataclass(frozen=True)
16
20
  class Output(Command.Output):
17
21
  pass
18
22
 
19
23
 
24
+ @dc.dataclass(frozen=True)
20
25
  class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
26
+ _apps: DeployAppManager
27
+
21
28
  async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
22
- log.info('Deploying!')
29
+ log.info('Deploying! %r', cmd.spec)
30
+
31
+ await self._apps.prepare_app(cmd.spec)
23
32
 
24
33
  return DeployCommand.Output()
@@ -18,6 +18,7 @@ from omlish.lite.check import check
18
18
 
19
19
  from .atomics import DeployAtomicPathSwapping
20
20
  from .paths import SingleDirDeployPathOwner
21
+ from .specs import DeployGitCheckout
21
22
  from .specs import DeployGitRepo
22
23
  from .types import DeployHome
23
24
  from .types import DeployRev
@@ -69,12 +70,16 @@ class DeployGitManager(SingleDirDeployPathOwner):
69
70
  else:
70
71
  return f'https://{self._repo.host}/{self._repo.path}'
71
72
 
73
+ #
74
+
72
75
  async def _call(self, *cmd: str) -> None:
73
76
  await asyncio_subprocesses.check_call(
74
77
  *cmd,
75
78
  cwd=self._dir,
76
79
  )
77
80
 
81
+ #
82
+
78
83
  @async_cached_nullary
79
84
  async def init(self) -> None:
80
85
  os.makedirs(self._dir, exist_ok=True)
@@ -88,7 +93,9 @@ class DeployGitManager(SingleDirDeployPathOwner):
88
93
  await self.init()
89
94
  await self._call('git', 'fetch', '--depth=1', 'origin', rev)
90
95
 
91
- async def checkout(self, rev: DeployRev, dst_dir: str) -> None:
96
+ #
97
+
98
+ async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
92
99
  check.state(not os.path.exists(dst_dir))
93
100
  with self._git._atomics.begin_atomic_path_swap( # noqa
94
101
  'dir',
@@ -96,14 +103,14 @@ class DeployGitManager(SingleDirDeployPathOwner):
96
103
  auto_commit=True,
97
104
  make_dirs=True,
98
105
  ) as dst_swap:
99
- await self.fetch(rev)
106
+ await self.fetch(checkout.rev)
100
107
 
101
108
  dst_call = functools.partial(asyncio_subprocesses.check_call, cwd=dst_swap.tmp_path)
102
109
  await dst_call('git', 'init')
103
110
 
104
111
  await dst_call('git', 'remote', 'add', 'local', self._dir)
105
- await dst_call('git', 'fetch', '--depth=1', 'local', rev)
106
- await dst_call('git', 'checkout', rev)
112
+ await dst_call('git', 'fetch', '--depth=1', 'local', checkout.rev)
113
+ await dst_call('git', 'checkout', checkout.rev, *(checkout.subtrees or []))
107
114
 
108
115
  def get_repo_dir(self, repo: DeployGitRepo) -> RepoDir:
109
116
  try:
@@ -112,5 +119,5 @@ class DeployGitManager(SingleDirDeployPathOwner):
112
119
  repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(self, repo)
113
120
  return repo_dir
114
121
 
115
- async def checkout(self, repo: DeployGitRepo, rev: DeployRev, dst_dir: str) -> None:
116
- await self.get_repo_dir(repo).checkout(rev, dst_dir)
122
+ async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
123
+ await self.get_repo_dir(checkout.repo).checkout(checkout, dst_dir)
@@ -1,40 +1,11 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  """
3
- ~deploy
4
- deploy.pid (flock)
5
- /app
6
- /<appplaceholder> - shallow clone
7
- /conf
8
- /env
9
- <appplaceholder>.env
10
- /nginx
11
- <appplaceholder>.conf
12
- /supervisor
13
- <appplaceholder>.conf
14
- /venv
15
- /<appplaceholder>
16
-
17
- /tmp
18
-
19
- ?
20
- /logs
21
- /wrmsr--omlish--<placeholder>
22
-
23
- placeholder = <name>--<rev>--<when>
24
-
25
- ==
26
-
27
- for dn in [
28
- 'app',
29
- 'conf',
30
- 'conf/env',
31
- 'conf/nginx',
32
- 'conf/supervisor',
33
- 'venv',
34
- ]:
35
-
36
- ==
37
-
3
+ TODO:
4
+ - run/pidfile
5
+ - logs/...
6
+ - current symlink
7
+ - conf/{nginx,supervisor}
8
+ - env/?
38
9
  """
39
10
  import abc
40
11
  import dataclasses as dc
@@ -59,7 +30,7 @@ DEPLOY_PATH_PLACEHOLDER_SEPARATORS = '-.'
59
30
 
60
31
  DEPLOY_PATH_PLACEHOLDERS: ta.FrozenSet[str] = frozenset([
61
32
  'app',
62
- 'tag', # <rev>-<dt>
33
+ 'tag',
63
34
  ])
64
35
 
65
36
 
@@ -25,14 +25,28 @@ class DeployGitRepo:
25
25
  check.not_in('.', check.non_empty_str(self.path))
26
26
 
27
27
 
28
+ @dc.dataclass(frozen=True)
29
+ class DeployGitCheckout:
30
+ repo: DeployGitRepo
31
+ rev: DeployRev
32
+
33
+ subtrees: ta.Optional[ta.Sequence[str]] = None
34
+
35
+ def __post_init__(self) -> None:
36
+ hash(self)
37
+ check.non_empty_str(self.rev)
38
+ if self.subtrees is not None:
39
+ for st in self.subtrees:
40
+ check.non_empty_str(st)
41
+
42
+
28
43
  ##
29
44
 
30
45
 
31
46
  @dc.dataclass(frozen=True)
32
47
  class DeploySpec:
33
48
  app: DeployApp
34
- repo: DeployGitRepo
35
- rev: DeployRev
49
+ checkout: DeployGitCheckout
36
50
 
37
51
  def __post_init__(self) -> None:
38
52
  hash(self)
@@ -1487,6 +1487,10 @@ def is_new_type(spec: ta.Any) -> bool:
1487
1487
  return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
1488
1488
 
1489
1489
 
1490
+ def get_new_type_supertype(spec: ta.Any) -> ta.Any:
1491
+ return spec.__supertype__
1492
+
1493
+
1490
1494
  def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
1491
1495
  seen = set()
1492
1496
  todo = list(reversed(cls.__subclasses__()))
@@ -2450,9 +2454,7 @@ class aclosing(contextlib.AbstractAsyncContextManager): # noqa
2450
2454
  """
2451
2455
  TODO:
2452
2456
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
2453
- - namedtuple
2454
2457
  - literals
2455
- - newtypes?
2456
2458
  """
2457
2459
 
2458
2460
 
@@ -2462,7 +2464,7 @@ TODO:
2462
2464
  @dc.dataclass(frozen=True)
2463
2465
  class ObjMarshalOptions:
2464
2466
  raw_bytes: bool = False
2465
- nonstrict_dataclasses: bool = False
2467
+ non_strict_fields: bool = False
2466
2468
 
2467
2469
 
2468
2470
  class ObjMarshaler(abc.ABC):
@@ -2591,10 +2593,10 @@ class IterableObjMarshaler(ObjMarshaler):
2591
2593
 
2592
2594
 
2593
2595
  @dc.dataclass(frozen=True)
2594
- class DataclassObjMarshaler(ObjMarshaler):
2596
+ class FieldsObjMarshaler(ObjMarshaler):
2595
2597
  ty: type
2596
2598
  fs: ta.Mapping[str, ObjMarshaler]
2597
- nonstrict: bool = False
2599
+ non_strict: bool = False
2598
2600
 
2599
2601
  def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
2600
2602
  return {
@@ -2606,7 +2608,7 @@ class DataclassObjMarshaler(ObjMarshaler):
2606
2608
  return self.ty(**{
2607
2609
  k: self.fs[k].unmarshal(v, ctx)
2608
2610
  for k, v in o.items()
2609
- if not (self.nonstrict or ctx.options.nonstrict_dataclasses) or k in self.fs
2611
+ if not (self.non_strict or ctx.options.non_strict_fields) or k in self.fs
2610
2612
  })
2611
2613
 
2612
2614
 
@@ -2738,7 +2740,7 @@ class ObjMarshalerManager:
2738
2740
  ty: ta.Any,
2739
2741
  rec: ta.Callable[[ta.Any], ObjMarshaler],
2740
2742
  *,
2741
- nonstrict_dataclasses: bool = False,
2743
+ non_strict_fields: bool = False,
2742
2744
  ) -> ObjMarshaler:
2743
2745
  if isinstance(ty, type):
2744
2746
  if abc.ABC in ty.__bases__:
@@ -2760,12 +2762,22 @@ class ObjMarshalerManager:
2760
2762
  return EnumObjMarshaler(ty)
2761
2763
 
2762
2764
  if dc.is_dataclass(ty):
2763
- return DataclassObjMarshaler(
2765
+ return FieldsObjMarshaler(
2764
2766
  ty,
2765
2767
  {f.name: rec(f.type) for f in dc.fields(ty)},
2766
- nonstrict=nonstrict_dataclasses,
2768
+ non_strict=non_strict_fields,
2769
+ )
2770
+
2771
+ if issubclass(ty, tuple) and hasattr(ty, '_fields'):
2772
+ return FieldsObjMarshaler(
2773
+ ty,
2774
+ {p.name: rec(p.annotation) for p in inspect.signature(ty).parameters.values()},
2775
+ non_strict=non_strict_fields,
2767
2776
  )
2768
2777
 
2778
+ if is_new_type(ty):
2779
+ return rec(get_new_type_supertype(ty))
2780
+
2769
2781
  if is_generic_alias(ty):
2770
2782
  try:
2771
2783
  mt = self._generic_mapping_types[ta.get_origin(ty)]
@@ -2692,6 +2692,10 @@ def is_new_type(spec: ta.Any) -> bool:
2692
2692
  return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
2693
2693
 
2694
2694
 
2695
+ def get_new_type_supertype(spec: ta.Any) -> ta.Any:
2696
+ return spec.__supertype__
2697
+
2698
+
2695
2699
  def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
2696
2700
  seen = set()
2697
2701
  todo = list(reversed(cls.__subclasses__()))
@@ -4261,41 +4265,12 @@ class TempDirDeployAtomicPathSwapping(DeployAtomicPathSwapping):
4261
4265
  ########################################
4262
4266
  # ../deploy/paths.py
4263
4267
  """
4264
- ~deploy
4265
- deploy.pid (flock)
4266
- /app
4267
- /<appplaceholder> - shallow clone
4268
- /conf
4269
- /env
4270
- <appplaceholder>.env
4271
- /nginx
4272
- <appplaceholder>.conf
4273
- /supervisor
4274
- <appplaceholder>.conf
4275
- /venv
4276
- /<appplaceholder>
4277
-
4278
- /tmp
4279
-
4280
- ?
4281
- /logs
4282
- /wrmsr--omlish--<placeholder>
4283
-
4284
- placeholder = <name>--<rev>--<when>
4285
-
4286
- ==
4287
-
4288
- for dn in [
4289
- 'app',
4290
- 'conf',
4291
- 'conf/env',
4292
- 'conf/nginx',
4293
- 'conf/supervisor',
4294
- 'venv',
4295
- ]:
4296
-
4297
- ==
4298
-
4268
+ TODO:
4269
+ - run/pidfile
4270
+ - logs/...
4271
+ - current symlink
4272
+ - conf/{nginx,supervisor}
4273
+ - env/?
4299
4274
  """
4300
4275
 
4301
4276
 
@@ -4307,7 +4282,7 @@ DEPLOY_PATH_PLACEHOLDER_SEPARATORS = '-.'
4307
4282
 
4308
4283
  DEPLOY_PATH_PLACEHOLDERS: ta.FrozenSet[str] = frozenset([
4309
4284
  'app',
4310
- 'tag', # <rev>-<dt>
4285
+ 'tag',
4311
4286
  ])
4312
4287
 
4313
4288
 
@@ -4534,14 +4509,28 @@ class DeployGitRepo:
4534
4509
  check.not_in('.', check.non_empty_str(self.path))
4535
4510
 
4536
4511
 
4512
+ @dc.dataclass(frozen=True)
4513
+ class DeployGitCheckout:
4514
+ repo: DeployGitRepo
4515
+ rev: DeployRev
4516
+
4517
+ subtrees: ta.Optional[ta.Sequence[str]] = None
4518
+
4519
+ def __post_init__(self) -> None:
4520
+ hash(self)
4521
+ check.non_empty_str(self.rev)
4522
+ if self.subtrees is not None:
4523
+ for st in self.subtrees:
4524
+ check.non_empty_str(st)
4525
+
4526
+
4537
4527
  ##
4538
4528
 
4539
4529
 
4540
4530
  @dc.dataclass(frozen=True)
4541
4531
  class DeploySpec:
4542
4532
  app: DeployApp
4543
- repo: DeployGitRepo
4544
- rev: DeployRev
4533
+ checkout: DeployGitCheckout
4545
4534
 
4546
4535
  def __post_init__(self) -> None:
4547
4536
  hash(self)
@@ -6008,9 +5997,7 @@ inj = Injection
6008
5997
  """
6009
5998
  TODO:
6010
5999
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
6011
- - namedtuple
6012
6000
  - literals
6013
- - newtypes?
6014
6001
  """
6015
6002
 
6016
6003
 
@@ -6020,7 +6007,7 @@ TODO:
6020
6007
  @dc.dataclass(frozen=True)
6021
6008
  class ObjMarshalOptions:
6022
6009
  raw_bytes: bool = False
6023
- nonstrict_dataclasses: bool = False
6010
+ non_strict_fields: bool = False
6024
6011
 
6025
6012
 
6026
6013
  class ObjMarshaler(abc.ABC):
@@ -6149,10 +6136,10 @@ class IterableObjMarshaler(ObjMarshaler):
6149
6136
 
6150
6137
 
6151
6138
  @dc.dataclass(frozen=True)
6152
- class DataclassObjMarshaler(ObjMarshaler):
6139
+ class FieldsObjMarshaler(ObjMarshaler):
6153
6140
  ty: type
6154
6141
  fs: ta.Mapping[str, ObjMarshaler]
6155
- nonstrict: bool = False
6142
+ non_strict: bool = False
6156
6143
 
6157
6144
  def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
6158
6145
  return {
@@ -6164,7 +6151,7 @@ class DataclassObjMarshaler(ObjMarshaler):
6164
6151
  return self.ty(**{
6165
6152
  k: self.fs[k].unmarshal(v, ctx)
6166
6153
  for k, v in o.items()
6167
- if not (self.nonstrict or ctx.options.nonstrict_dataclasses) or k in self.fs
6154
+ if not (self.non_strict or ctx.options.non_strict_fields) or k in self.fs
6168
6155
  })
6169
6156
 
6170
6157
 
@@ -6296,7 +6283,7 @@ class ObjMarshalerManager:
6296
6283
  ty: ta.Any,
6297
6284
  rec: ta.Callable[[ta.Any], ObjMarshaler],
6298
6285
  *,
6299
- nonstrict_dataclasses: bool = False,
6286
+ non_strict_fields: bool = False,
6300
6287
  ) -> ObjMarshaler:
6301
6288
  if isinstance(ty, type):
6302
6289
  if abc.ABC in ty.__bases__:
@@ -6318,12 +6305,22 @@ class ObjMarshalerManager:
6318
6305
  return EnumObjMarshaler(ty)
6319
6306
 
6320
6307
  if dc.is_dataclass(ty):
6321
- return DataclassObjMarshaler(
6308
+ return FieldsObjMarshaler(
6322
6309
  ty,
6323
6310
  {f.name: rec(f.type) for f in dc.fields(ty)},
6324
- nonstrict=nonstrict_dataclasses,
6311
+ non_strict=non_strict_fields,
6312
+ )
6313
+
6314
+ if issubclass(ty, tuple) and hasattr(ty, '_fields'):
6315
+ return FieldsObjMarshaler(
6316
+ ty,
6317
+ {p.name: rec(p.annotation) for p in inspect.signature(ty).parameters.values()},
6318
+ non_strict=non_strict_fields,
6325
6319
  )
6326
6320
 
6321
+ if is_new_type(ty):
6322
+ return rec(get_new_type_supertype(ty))
6323
+
6327
6324
  if is_generic_alias(ty):
6328
6325
  try:
6329
6326
  mt = self._generic_mapping_types[ta.get_origin(ty)]
@@ -6749,27 +6746,6 @@ class PingCommandExecutor(CommandExecutor[PingCommand, PingCommand.Output]):
6749
6746
  CommandExecutorMap = ta.NewType('CommandExecutorMap', ta.Mapping[ta.Type[Command], CommandExecutor])
6750
6747
 
6751
6748
 
6752
- ########################################
6753
- # ../deploy/commands.py
6754
-
6755
-
6756
- ##
6757
-
6758
-
6759
- @dc.dataclass(frozen=True)
6760
- class DeployCommand(Command['DeployCommand.Output']):
6761
- @dc.dataclass(frozen=True)
6762
- class Output(Command.Output):
6763
- pass
6764
-
6765
-
6766
- class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
6767
- async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
6768
- log.info('Deploying!')
6769
-
6770
- return DeployCommand.Output()
6771
-
6772
-
6773
6749
  ########################################
6774
6750
  # ../deploy/tmp.py
6775
6751
 
@@ -8237,12 +8213,16 @@ class DeployGitManager(SingleDirDeployPathOwner):
8237
8213
  else:
8238
8214
  return f'https://{self._repo.host}/{self._repo.path}'
8239
8215
 
8216
+ #
8217
+
8240
8218
  async def _call(self, *cmd: str) -> None:
8241
8219
  await asyncio_subprocesses.check_call(
8242
8220
  *cmd,
8243
8221
  cwd=self._dir,
8244
8222
  )
8245
8223
 
8224
+ #
8225
+
8246
8226
  @async_cached_nullary
8247
8227
  async def init(self) -> None:
8248
8228
  os.makedirs(self._dir, exist_ok=True)
@@ -8256,7 +8236,9 @@ class DeployGitManager(SingleDirDeployPathOwner):
8256
8236
  await self.init()
8257
8237
  await self._call('git', 'fetch', '--depth=1', 'origin', rev)
8258
8238
 
8259
- async def checkout(self, rev: DeployRev, dst_dir: str) -> None:
8239
+ #
8240
+
8241
+ async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
8260
8242
  check.state(not os.path.exists(dst_dir))
8261
8243
  with self._git._atomics.begin_atomic_path_swap( # noqa
8262
8244
  'dir',
@@ -8264,14 +8246,14 @@ class DeployGitManager(SingleDirDeployPathOwner):
8264
8246
  auto_commit=True,
8265
8247
  make_dirs=True,
8266
8248
  ) as dst_swap:
8267
- await self.fetch(rev)
8249
+ await self.fetch(checkout.rev)
8268
8250
 
8269
8251
  dst_call = functools.partial(asyncio_subprocesses.check_call, cwd=dst_swap.tmp_path)
8270
8252
  await dst_call('git', 'init')
8271
8253
 
8272
8254
  await dst_call('git', 'remote', 'add', 'local', self._dir)
8273
- await dst_call('git', 'fetch', '--depth=1', 'local', rev)
8274
- await dst_call('git', 'checkout', rev)
8255
+ await dst_call('git', 'fetch', '--depth=1', 'local', checkout.rev)
8256
+ await dst_call('git', 'checkout', checkout.rev, *(checkout.subtrees or []))
8275
8257
 
8276
8258
  def get_repo_dir(self, repo: DeployGitRepo) -> RepoDir:
8277
8259
  try:
@@ -8280,8 +8262,8 @@ class DeployGitManager(SingleDirDeployPathOwner):
8280
8262
  repo_dir = self._repo_dirs[repo] = DeployGitManager.RepoDir(self, repo)
8281
8263
  return repo_dir
8282
8264
 
8283
- async def checkout(self, repo: DeployGitRepo, rev: DeployRev, dst_dir: str) -> None:
8284
- await self.get_repo_dir(repo).checkout(rev, dst_dir)
8265
+ async def checkout(self, checkout: DeployGitCheckout, dst_dir: str) -> None:
8266
+ await self.get_repo_dir(checkout.repo).checkout(checkout, dst_dir)
8285
8267
 
8286
8268
 
8287
8269
  ########################################
@@ -8919,15 +8901,14 @@ class DeployAppManager(DeployPathOwner):
8919
8901
  async def prepare_app(
8920
8902
  self,
8921
8903
  spec: DeploySpec,
8922
- ):
8923
- app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.rev, spec.key()))
8904
+ ) -> None:
8905
+ app_tag = DeployAppTag(spec.app, make_deploy_tag(spec.checkout.rev, spec.key()))
8924
8906
  app_dir = os.path.join(self._dir(), spec.app, app_tag.tag)
8925
8907
 
8926
8908
  #
8927
8909
 
8928
8910
  await self._git.checkout(
8929
- spec.repo,
8930
- spec.rev,
8911
+ spec.checkout,
8931
8912
  app_dir,
8932
8913
  )
8933
8914
 
@@ -9650,6 +9631,34 @@ class SystemInterpProvider(InterpProvider):
9650
9631
  raise KeyError(version)
9651
9632
 
9652
9633
 
9634
+ ########################################
9635
+ # ../deploy/commands.py
9636
+
9637
+
9638
+ ##
9639
+
9640
+
9641
+ @dc.dataclass(frozen=True)
9642
+ class DeployCommand(Command['DeployCommand.Output']):
9643
+ spec: DeploySpec
9644
+
9645
+ @dc.dataclass(frozen=True)
9646
+ class Output(Command.Output):
9647
+ pass
9648
+
9649
+
9650
+ @dc.dataclass(frozen=True)
9651
+ class DeployCommandExecutor(CommandExecutor[DeployCommand, DeployCommand.Output]):
9652
+ _apps: DeployAppManager
9653
+
9654
+ async def execute(self, cmd: DeployCommand) -> DeployCommand.Output:
9655
+ log.info('Deploying! %r', cmd.spec)
9656
+
9657
+ await self._apps.prepare_app(cmd.spec)
9658
+
9659
+ return DeployCommand.Output()
9660
+
9661
+
9653
9662
  ########################################
9654
9663
  # ../remote/inject.py
9655
9664
 
@@ -2296,6 +2296,10 @@ def is_new_type(spec: ta.Any) -> bool:
2296
2296
  return isinstance(spec, types.FunctionType) and spec.__code__ is ta.NewType.__code__.co_consts[1] # type: ignore # noqa
2297
2297
 
2298
2298
 
2299
+ def get_new_type_supertype(spec: ta.Any) -> ta.Any:
2300
+ return spec.__supertype__
2301
+
2302
+
2299
2303
  def deep_subclasses(cls: ta.Type[T]) -> ta.Iterator[ta.Type[T]]:
2300
2304
  seen = set()
2301
2305
  todo = list(reversed(cls.__subclasses__()))
@@ -4854,9 +4858,7 @@ inj = Injection
4854
4858
  """
4855
4859
  TODO:
4856
4860
  - pickle stdlib objs? have to pin to 3.8 pickle protocol, will be cross-version
4857
- - namedtuple
4858
4861
  - literals
4859
- - newtypes?
4860
4862
  """
4861
4863
 
4862
4864
 
@@ -4866,7 +4868,7 @@ TODO:
4866
4868
  @dc.dataclass(frozen=True)
4867
4869
  class ObjMarshalOptions:
4868
4870
  raw_bytes: bool = False
4869
- nonstrict_dataclasses: bool = False
4871
+ non_strict_fields: bool = False
4870
4872
 
4871
4873
 
4872
4874
  class ObjMarshaler(abc.ABC):
@@ -4995,10 +4997,10 @@ class IterableObjMarshaler(ObjMarshaler):
4995
4997
 
4996
4998
 
4997
4999
  @dc.dataclass(frozen=True)
4998
- class DataclassObjMarshaler(ObjMarshaler):
5000
+ class FieldsObjMarshaler(ObjMarshaler):
4999
5001
  ty: type
5000
5002
  fs: ta.Mapping[str, ObjMarshaler]
5001
- nonstrict: bool = False
5003
+ non_strict: bool = False
5002
5004
 
5003
5005
  def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
5004
5006
  return {
@@ -5010,7 +5012,7 @@ class DataclassObjMarshaler(ObjMarshaler):
5010
5012
  return self.ty(**{
5011
5013
  k: self.fs[k].unmarshal(v, ctx)
5012
5014
  for k, v in o.items()
5013
- if not (self.nonstrict or ctx.options.nonstrict_dataclasses) or k in self.fs
5015
+ if not (self.non_strict or ctx.options.non_strict_fields) or k in self.fs
5014
5016
  })
5015
5017
 
5016
5018
 
@@ -5142,7 +5144,7 @@ class ObjMarshalerManager:
5142
5144
  ty: ta.Any,
5143
5145
  rec: ta.Callable[[ta.Any], ObjMarshaler],
5144
5146
  *,
5145
- nonstrict_dataclasses: bool = False,
5147
+ non_strict_fields: bool = False,
5146
5148
  ) -> ObjMarshaler:
5147
5149
  if isinstance(ty, type):
5148
5150
  if abc.ABC in ty.__bases__:
@@ -5164,12 +5166,22 @@ class ObjMarshalerManager:
5164
5166
  return EnumObjMarshaler(ty)
5165
5167
 
5166
5168
  if dc.is_dataclass(ty):
5167
- return DataclassObjMarshaler(
5169
+ return FieldsObjMarshaler(
5168
5170
  ty,
5169
5171
  {f.name: rec(f.type) for f in dc.fields(ty)},
5170
- nonstrict=nonstrict_dataclasses,
5172
+ non_strict=non_strict_fields,
5173
+ )
5174
+
5175
+ if issubclass(ty, tuple) and hasattr(ty, '_fields'):
5176
+ return FieldsObjMarshaler(
5177
+ ty,
5178
+ {p.name: rec(p.annotation) for p in inspect.signature(ty).parameters.values()},
5179
+ non_strict=non_strict_fields,
5171
5180
  )
5172
5181
 
5182
+ if is_new_type(ty):
5183
+ return rec(get_new_type_supertype(ty))
5184
+
5173
5185
  if is_generic_alias(ty):
5174
5186
  try:
5175
5187
  mt = self._generic_mapping_types[ta.get_origin(ty)]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev159
3
+ Version: 0.0.0.dev160
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.dev159
16
- Requires-Dist: omlish==0.0.0.dev159
15
+ Requires-Dist: omdev==0.0.0.dev160
16
+ Requires-Dist: omlish==0.0.0.dev160
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -1,5 +1,5 @@
1
- omdev==0.0.0.dev159
2
- omlish==0.0.0.dev159
1
+ omdev==0.0.0.dev160
2
+ omlish==0.0.0.dev160
3
3
 
4
4
  [all]
5
5
  paramiko~=3.5
@@ -12,7 +12,7 @@ authors = [
12
12
  urls = {source = 'https://github.com/wrmsr/omlish'}
13
13
  license = {text = 'BSD-3-Clause'}
14
14
  requires-python = '>=3.12'
15
- version = '0.0.0.dev159'
15
+ version = '0.0.0.dev160'
16
16
  classifiers = [
17
17
  'License :: OSI Approved :: BSD License',
18
18
  'Development Status :: 2 - Pre-Alpha',
@@ -22,8 +22,8 @@ classifiers = [
22
22
  ]
23
23
  description = 'ominfra'
24
24
  dependencies = [
25
- 'omdev == 0.0.0.dev159',
26
- 'omlish == 0.0.0.dev159',
25
+ 'omdev == 0.0.0.dev160',
26
+ 'omlish == 0.0.0.dev160',
27
27
  ]
28
28
 
29
29
  [project.optional-dependencies]
File without changes
File without changes