ominfra 0.0.0.dev175__tar.gz → 0.0.0.dev176__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. {ominfra-0.0.0.dev175/ominfra.egg-info → ominfra-0.0.0.dev176}/PKG-INFO +3 -3
  2. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/configs.py +4 -2
  3. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/marshal.py +1 -1
  4. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/apps.py +2 -0
  5. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/tags.py +4 -0
  6. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/venvs.py +11 -1
  7. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/main.py +12 -3
  8. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/scripts/journald2aws.py +40 -5
  9. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/scripts/manage.py +1422 -1367
  10. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/scripts/supervisor.py +40 -5
  11. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176/ominfra.egg-info}/PKG-INFO +3 -3
  12. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra.egg-info/requires.txt +2 -2
  13. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/pyproject.toml +3 -3
  14. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/LICENSE +0 -0
  15. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/MANIFEST.in +0 -0
  16. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/README.rst +0 -0
  17. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/.manifests.json +0 -0
  18. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/__about__.py +0 -0
  19. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/__init__.py +0 -0
  20. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/__init__.py +0 -0
  21. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/__init__.py +0 -0
  22. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/__main__.py +0 -0
  23. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/auth.py +0 -0
  24. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/cli.py +0 -0
  25. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/dataclasses.py +0 -0
  26. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  27. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  28. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  29. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  30. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  31. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  32. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/logs.py +0 -0
  33. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/aws/metadata.py +0 -0
  34. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/gcp/__init__.py +0 -0
  35. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/clouds/gcp/auth.py +0 -0
  36. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/cmds.py +0 -0
  37. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/journald/__init__.py +0 -0
  38. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/journald/fields.py +0 -0
  39. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/journald/genmessages.py +0 -0
  40. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/journald/messages.py +0 -0
  41. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/journald/tailer.py +0 -0
  42. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/__init__.py +0 -0
  43. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/__main__.py +0 -0
  44. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/bootstrap.py +0 -0
  45. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/bootstrap_.py +0 -0
  46. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/__init__.py +0 -0
  47. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/base.py +0 -0
  48. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/inject.py +0 -0
  49. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/local.py +0 -0
  50. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/ping.py +0 -0
  51. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/subprocess.py +0 -0
  52. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/commands/types.py +0 -0
  53. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/config.py +0 -0
  54. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/__init__.py +0 -0
  55. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/commands.py +0 -0
  56. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/conf.py +0 -0
  57. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/config.py +0 -0
  58. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/deploy.py +0 -0
  59. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/git.py +0 -0
  60. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/inject.py +0 -0
  61. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/interp.py +0 -0
  62. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/paths/__init__.py +0 -0
  63. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/paths/inject.py +0 -0
  64. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/paths/manager.py +0 -0
  65. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/paths/owners.py +0 -0
  66. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/paths/paths.py +0 -0
  67. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/paths/types.py +0 -0
  68. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/specs.py +0 -0
  69. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/tmp.py +0 -0
  70. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/deploy/types.py +0 -0
  71. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/inject.py +0 -0
  72. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/marshal.py +0 -0
  73. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/__init__.py +0 -0
  74. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/_main.py +0 -0
  75. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/channel.py +0 -0
  76. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/config.py +0 -0
  77. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/connection.py +0 -0
  78. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/execution.py +0 -0
  79. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/inject.py +0 -0
  80. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/payload.py +0 -0
  81. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/remote/spawning.py +0 -0
  82. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/system/__init__.py +0 -0
  83. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/system/commands.py +0 -0
  84. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/system/config.py +0 -0
  85. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/system/inject.py +0 -0
  86. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/system/packages.py +0 -0
  87. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/system/platforms.py +0 -0
  88. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/targets/__init__.py +0 -0
  89. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/targets/bestpython.py +0 -0
  90. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/targets/bestpython.sh +0 -0
  91. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/targets/connection.py +0 -0
  92. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/targets/inject.py +0 -0
  93. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/manage/targets/targets.py +0 -0
  94. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/pyremote.py +0 -0
  95. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/scripts/__init__.py +0 -0
  96. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/ssh.py +0 -0
  97. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/LICENSE.txt +0 -0
  98. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/__init__.py +0 -0
  99. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/__main__.py +0 -0
  100. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/configs.py +0 -0
  101. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/dispatchers.py +0 -0
  102. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/dispatchersimpl.py +0 -0
  103. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/events.py +0 -0
  104. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/exceptions.py +0 -0
  105. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/groups.py +0 -0
  106. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/groupsimpl.py +0 -0
  107. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/http.py +0 -0
  108. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/inject.py +0 -0
  109. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/io.py +0 -0
  110. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/main.py +0 -0
  111. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/pipes.py +0 -0
  112. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/privileges.py +0 -0
  113. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/process.py +0 -0
  114. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/processimpl.py +0 -0
  115. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/setup.py +0 -0
  116. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/setupimpl.py +0 -0
  117. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/signals.py +0 -0
  118. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/spawning.py +0 -0
  119. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/spawningimpl.py +0 -0
  120. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/states.py +0 -0
  121. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/supervisor.py +0 -0
  122. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/types.py +0 -0
  123. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/__init__.py +0 -0
  124. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/collections.py +0 -0
  125. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/diag.py +0 -0
  126. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/fds.py +0 -0
  127. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/fs.py +0 -0
  128. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/os.py +0 -0
  129. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/ostypes.py +0 -0
  130. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/signals.py +0 -0
  131. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/strings.py +0 -0
  132. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/supervisor/utils/users.py +0 -0
  133. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/tailscale/__init__.py +0 -0
  134. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/tailscale/api.py +0 -0
  135. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/tailscale/cli.py +0 -0
  136. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/threadworkers.py +0 -0
  137. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/tools/__init__.py +0 -0
  138. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra/tools/listresources.py +0 -0
  139. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra.egg-info/SOURCES.txt +0 -0
  140. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra.egg-info/dependency_links.txt +0 -0
  141. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra.egg-info/entry_points.txt +0 -0
  142. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/ominfra.egg-info/top_level.txt +0 -0
  143. {ominfra-0.0.0.dev175 → ominfra-0.0.0.dev176}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev175
3
+ Version: 0.0.0.dev176
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.dev175
16
- Requires-Dist: omlish==0.0.0.dev175
15
+ Requires-Dist: omdev==0.0.0.dev176
16
+ Requires-Dist: omlish==0.0.0.dev176
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko~=3.5; extra == "all"
19
19
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -6,7 +6,8 @@ import typing as ta
6
6
 
7
7
  from omdev.toml.parser import toml_loads
8
8
  from omlish.lite.check import check
9
- from omlish.lite.marshal import unmarshal_obj
9
+ from omlish.lite.marshal import OBJ_MARSHALER_MANAGER
10
+ from omlish.lite.marshal import ObjMarshalerManager
10
11
 
11
12
 
12
13
  T = ta.TypeVar('T')
@@ -46,6 +47,7 @@ def read_config_file(
46
47
  cls: ta.Type[T],
47
48
  *,
48
49
  prepare: ta.Optional[ta.Callable[[ConfigMapping], ConfigMapping]] = None,
50
+ msh: ObjMarshalerManager = OBJ_MARSHALER_MANAGER,
49
51
  ) -> T:
50
52
  with open(path) as cf:
51
53
  config_dct = parse_config_file(os.path.basename(path), cf)
@@ -53,7 +55,7 @@ def read_config_file(
53
55
  if prepare is not None:
54
56
  config_dct = prepare(config_dct)
55
57
 
56
- return unmarshal_obj(config_dct, cls)
58
+ return msh.unmarshal_obj(config_dct, cls)
57
59
 
58
60
 
59
61
  def build_config_named_children(
@@ -13,7 +13,7 @@ def install_command_marshaling(
13
13
  lambda c: c,
14
14
  lambda c: c.Output,
15
15
  ]:
16
- msh.register_opj_marshaler(
16
+ msh.set_obj_marshaler(
17
17
  fn(Command),
18
18
  PolymorphicObjMarshaler.of([
19
19
  PolymorphicObjMarshaler.Impl(
@@ -86,6 +86,8 @@ class DeployAppManager(DeployPathOwner):
86
86
  os.makedirs(deploy_dir, exist_ok=True)
87
87
 
88
88
  deploying_link = os.path.join(deploy_home, 'deploys/deploying')
89
+ if os.path.exists(deploying_link):
90
+ os.unlink(deploying_link)
89
91
  relative_symlink(
90
92
  deploy_dir,
91
93
  deploying_link,
@@ -4,6 +4,8 @@ import dataclasses as dc
4
4
  import typing as ta
5
5
 
6
6
  from omlish.lite.check import check
7
+ from omlish.lite.marshal import SingleFieldObjMarshaler
8
+ from omlish.lite.marshal import register_type_obj_marshaler
7
9
 
8
10
 
9
11
  ##
@@ -82,6 +84,8 @@ def _register_deploy_tag(cls):
82
84
  _DEPLOY_TAGS_BY_NAME[cls.tag_name] = cls
83
85
  _DEPLOY_TAGS_BY_KWARG[cls.tag_kwarg] = cls
84
86
 
87
+ register_type_obj_marshaler(cls, SingleFieldObjMarshaler(cls, 's'))
88
+
85
89
  return cls
86
90
 
87
91
 
@@ -6,7 +6,10 @@ TODO:
6
6
  """
7
7
  import os.path
8
8
 
9
+ from omdev.interp.resolvers import DEFAULT_INTERP_RESOLVER
10
+ from omdev.interp.types import InterpSpecifier
9
11
  from omlish.asyncs.asyncio.subprocesses import asyncio_subprocesses
12
+ from omlish.lite.check import check
10
13
  from omlish.os.atomics import AtomicPathSwapping
11
14
 
12
15
  from .specs import DeployVenvSpec
@@ -28,7 +31,14 @@ class DeployVenvManager:
28
31
  git_dir: str,
29
32
  venv_dir: str,
30
33
  ) -> None:
31
- sys_exe = 'python3'
34
+ if spec.interp is not None:
35
+ i = InterpSpecifier.parse(check.not_none(spec.interp))
36
+ o = check.not_none(await DEFAULT_INTERP_RESOLVER.resolve(i))
37
+ sys_exe = o.exe
38
+ else:
39
+ sys_exe = 'python3'
40
+
41
+ #
32
42
 
33
43
  # !! NOTE: (most) venvs cannot be relocated, so an atomic swap can't be used. it's up to the path manager to
34
44
  # garbage collect orphaned dirs.
@@ -35,6 +35,8 @@ from .targets.targets import ManageTarget
35
35
 
36
36
  @dc.dataclass(frozen=True)
37
37
  class ManageConfig:
38
+ deploy_home: ta.Optional[str] = None
39
+
38
40
  targets: ta.Optional[ta.Mapping[str, ManageTarget]] = None
39
41
 
40
42
 
@@ -69,7 +71,8 @@ class MainCli(ArgparseCli):
69
71
  argparse_arg('--deploy-home'),
70
72
 
71
73
  argparse_arg('target'),
72
- argparse_arg('command', nargs='+'),
74
+ argparse_arg('-f', '--command-file', action='append'),
75
+ argparse_arg('command', nargs='*'),
73
76
  )
74
77
  async def run(self) -> None:
75
78
  bs = MainBootstrap(
@@ -80,7 +83,7 @@ class MainCli(ArgparseCli):
80
83
  ),
81
84
 
82
85
  deploy_config=DeployConfig(
83
- deploy_home=self.args.deploy_home,
86
+ deploy_home=self.args.deploy_home or self.config().deploy_home,
84
87
  ),
85
88
 
86
89
  remote_config=RemoteConfig(
@@ -115,13 +118,19 @@ class MainCli(ArgparseCli):
115
118
  #
116
119
 
117
120
  cmds: ta.List[Command] = []
121
+
118
122
  cmd: Command
119
- for c in self.args.command:
123
+
124
+ for c in self.args.command or []:
120
125
  if not c.startswith('{'):
121
126
  c = json.dumps({c: {}})
122
127
  cmd = msh.unmarshal_obj(json.loads(c), Command)
123
128
  cmds.append(cmd)
124
129
 
130
+ for cf in self.args.command_file or []:
131
+ cmd = read_config_file(cf, Command, msh=msh)
132
+ cmds.append(cmd)
133
+
125
134
  #
126
135
 
127
136
  async with injector[ManageTargetConnector].connect(tgt) as ce:
@@ -2686,6 +2686,18 @@ class FieldsObjMarshaler(ObjMarshaler):
2686
2686
  })
2687
2687
 
2688
2688
 
2689
+ @dc.dataclass(frozen=True)
2690
+ class SingleFieldObjMarshaler(ObjMarshaler):
2691
+ ty: type
2692
+ fld: str
2693
+
2694
+ def marshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
2695
+ return getattr(o, self.fld)
2696
+
2697
+ def unmarshal(self, o: ta.Any, ctx: 'ObjMarshalContext') -> ta.Any:
2698
+ return self.ty(**{self.fld: o})
2699
+
2700
+
2689
2701
  @dc.dataclass(frozen=True)
2690
2702
  class PolymorphicObjMarshaler(ObjMarshaler):
2691
2703
  class Impl(ta.NamedTuple):
@@ -2760,7 +2772,7 @@ _DEFAULT_OBJ_MARSHALERS: ta.Dict[ta.Any, ObjMarshaler] = {
2760
2772
  **{t: IterableObjMarshaler(t, DynamicObjMarshaler()) for t in (list, tuple, set, frozenset)},
2761
2773
  **{t: MappingObjMarshaler(t, DynamicObjMarshaler(), DynamicObjMarshaler()) for t in (dict,)},
2762
2774
 
2763
- ta.Any: DynamicObjMarshaler(),
2775
+ **{t: DynamicObjMarshaler() for t in (ta.Any, object)},
2764
2776
 
2765
2777
  **{t: DatetimeObjMarshaler(t) for t in (datetime.date, datetime.time, datetime.datetime)},
2766
2778
  decimal.Decimal: DecimalObjMarshaler(),
@@ -2785,6 +2797,16 @@ _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES: ta.Dict[ta.Any, type] = {
2785
2797
  ##
2786
2798
 
2787
2799
 
2800
+ _REGISTERED_OBJ_MARSHALERS_BY_TYPE: ta.MutableMapping[type, ObjMarshaler] = weakref.WeakKeyDictionary()
2801
+
2802
+
2803
+ def register_type_obj_marshaler(ty: type, om: ObjMarshaler) -> None:
2804
+ _REGISTERED_OBJ_MARSHALERS_BY_TYPE[ty] = om
2805
+
2806
+
2807
+ ##
2808
+
2809
+
2788
2810
  class ObjMarshalerManager:
2789
2811
  def __init__(
2790
2812
  self,
@@ -2794,6 +2816,8 @@ class ObjMarshalerManager:
2794
2816
  default_obj_marshalers: ta.Dict[ta.Any, ObjMarshaler] = _DEFAULT_OBJ_MARSHALERS, # noqa
2795
2817
  generic_mapping_types: ta.Dict[ta.Any, type] = _OBJ_MARSHALER_GENERIC_MAPPING_TYPES, # noqa
2796
2818
  generic_iterable_types: ta.Dict[ta.Any, type] = _OBJ_MARSHALER_GENERIC_ITERABLE_TYPES, # noqa
2819
+
2820
+ registered_obj_marshalers: ta.Mapping[type, ObjMarshaler] = _REGISTERED_OBJ_MARSHALERS_BY_TYPE,
2797
2821
  ) -> None:
2798
2822
  super().__init__()
2799
2823
 
@@ -2802,6 +2826,7 @@ class ObjMarshalerManager:
2802
2826
  self._obj_marshalers = dict(default_obj_marshalers)
2803
2827
  self._generic_mapping_types = generic_mapping_types
2804
2828
  self._generic_iterable_types = generic_iterable_types
2829
+ self._registered_obj_marshalers = registered_obj_marshalers
2805
2830
 
2806
2831
  self._lock = threading.RLock()
2807
2832
  self._marshalers: ta.Dict[ta.Any, ObjMarshaler] = dict(_DEFAULT_OBJ_MARSHALERS)
@@ -2817,6 +2842,9 @@ class ObjMarshalerManager:
2817
2842
  non_strict_fields: bool = False,
2818
2843
  ) -> ObjMarshaler:
2819
2844
  if isinstance(ty, type):
2845
+ if (reg := self._registered_obj_marshalers.get(ty)) is not None:
2846
+ return reg
2847
+
2820
2848
  if abc.ABC in ty.__bases__:
2821
2849
  impls = [ity for ity in deep_subclasses(ty) if abc.ABC not in ity.__bases__] # type: ignore
2822
2850
  if all(ity.__qualname__.endswith(ty.__name__) for ity in impls):
@@ -2881,9 +2909,15 @@ class ObjMarshalerManager:
2881
2909
 
2882
2910
  #
2883
2911
 
2884
- def register_opj_marshaler(self, ty: ta.Any, m: ObjMarshaler) -> None:
2912
+ def set_obj_marshaler(
2913
+ self,
2914
+ ty: ta.Any,
2915
+ m: ObjMarshaler,
2916
+ *,
2917
+ override: bool = False,
2918
+ ) -> None:
2885
2919
  with self._lock:
2886
- if ty in self._obj_marshalers:
2920
+ if not override and ty in self._obj_marshalers:
2887
2921
  raise KeyError(ty)
2888
2922
  self._obj_marshalers[ty] = m
2889
2923
 
@@ -2974,7 +3008,7 @@ class ObjMarshalContext:
2974
3008
 
2975
3009
  OBJ_MARSHALER_MANAGER = ObjMarshalerManager()
2976
3010
 
2977
- register_opj_marshaler = OBJ_MARSHALER_MANAGER.register_opj_marshaler
3011
+ set_obj_marshaler = OBJ_MARSHALER_MANAGER.set_obj_marshaler
2978
3012
  get_obj_marshaler = OBJ_MARSHALER_MANAGER.get_obj_marshaler
2979
3013
 
2980
3014
  marshal_obj = OBJ_MARSHALER_MANAGER.marshal_obj
@@ -3259,6 +3293,7 @@ def read_config_file(
3259
3293
  cls: ta.Type[T],
3260
3294
  *,
3261
3295
  prepare: ta.Optional[ta.Callable[[ConfigMapping], ConfigMapping]] = None,
3296
+ msh: ObjMarshalerManager = OBJ_MARSHALER_MANAGER,
3262
3297
  ) -> T:
3263
3298
  with open(path) as cf:
3264
3299
  config_dct = parse_config_file(os.path.basename(path), cf)
@@ -3266,7 +3301,7 @@ def read_config_file(
3266
3301
  if prepare is not None:
3267
3302
  config_dct = prepare(config_dct)
3268
3303
 
3269
- return unmarshal_obj(config_dct, cls)
3304
+ return msh.unmarshal_obj(config_dct, cls)
3270
3305
 
3271
3306
 
3272
3307
  def build_config_named_children(