ominfra 0.0.0.dev199__tar.gz → 0.0.0.dev200__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. {ominfra-0.0.0.dev199/ominfra.egg-info → ominfra-0.0.0.dev200}/PKG-INFO +5 -5
  2. ominfra-0.0.0.dev200/ominfra/clouds/aws/models/base.py +101 -0
  3. ominfra-0.0.0.dev200/ominfra/clouds/aws/models/gen/__main__.py +4 -0
  4. ominfra-0.0.0.dev200/ominfra/clouds/aws/models/gen/cli.py +130 -0
  5. ominfra-0.0.0.dev200/ominfra/clouds/aws/models/gen/gen.py +440 -0
  6. ominfra-0.0.0.dev200/ominfra/clouds/aws/models/services/ec2.py +3222 -0
  7. ominfra-0.0.0.dev200/ominfra/clouds/aws/models/services/s3.py +869 -0
  8. ominfra-0.0.0.dev200/ominfra/clouds/aws/models/services/services.toml +16 -0
  9. ominfra-0.0.0.dev200/ominfra/supervisor/utils/__init__.py +0 -0
  10. ominfra-0.0.0.dev200/ominfra/tailscale/__init__.py +0 -0
  11. ominfra-0.0.0.dev200/ominfra/tools/__init__.py +0 -0
  12. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200/ominfra.egg-info}/PKG-INFO +5 -5
  13. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra.egg-info/SOURCES.txt +10 -0
  14. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra.egg-info/requires.txt +3 -3
  15. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/pyproject.toml +5 -4
  16. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/LICENSE +0 -0
  17. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/MANIFEST.in +0 -0
  18. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/README.rst +0 -0
  19. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/.manifests.json +0 -0
  20. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/__about__.py +0 -0
  21. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/__init__.py +0 -0
  22. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/__init__.py +0 -0
  23. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/__init__.py +0 -0
  24. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/__main__.py +0 -0
  25. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/auth.py +0 -0
  26. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/cli.py +0 -0
  27. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/dataclasses.py +0 -0
  28. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/journald2aws/__init__.py +0 -0
  29. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/journald2aws/__main__.py +0 -0
  30. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/journald2aws/cursor.py +0 -0
  31. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/journald2aws/driver.py +0 -0
  32. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/journald2aws/main.py +0 -0
  33. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/journald2aws/poster.py +0 -0
  34. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/logs.py +0 -0
  35. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/aws/metadata.py +0 -0
  36. {ominfra-0.0.0.dev199/ominfra/clouds/gcp → ominfra-0.0.0.dev200/ominfra/clouds/aws/models}/__init__.py +0 -0
  37. {ominfra-0.0.0.dev199/ominfra/journald → ominfra-0.0.0.dev200/ominfra/clouds/aws/models/gen}/__init__.py +0 -0
  38. {ominfra-0.0.0.dev199/ominfra/manage/commands → ominfra-0.0.0.dev200/ominfra/clouds/aws/models/services}/__init__.py +0 -0
  39. {ominfra-0.0.0.dev199/ominfra/manage/deploy → ominfra-0.0.0.dev200/ominfra/clouds/gcp}/__init__.py +0 -0
  40. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/clouds/gcp/auth.py +0 -0
  41. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/cmds.py +0 -0
  42. {ominfra-0.0.0.dev199/ominfra/manage/deploy/conf → ominfra-0.0.0.dev200/ominfra/journald}/__init__.py +0 -0
  43. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/journald/fields.py +0 -0
  44. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/journald/genmessages.py +0 -0
  45. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/journald/messages.py +0 -0
  46. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/journald/tailer.py +0 -0
  47. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/__init__.py +0 -0
  48. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/__main__.py +0 -0
  49. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/bootstrap.py +0 -0
  50. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/bootstrap_.py +0 -0
  51. {ominfra-0.0.0.dev199/ominfra/manage/deploy/paths → ominfra-0.0.0.dev200/ominfra/manage/commands}/__init__.py +0 -0
  52. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/base.py +0 -0
  53. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/inject.py +0 -0
  54. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/injection.py +0 -0
  55. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/local.py +0 -0
  56. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/marshal.py +0 -0
  57. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/ping.py +0 -0
  58. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/subprocess.py +0 -0
  59. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/commands/types.py +0 -0
  60. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/config.py +0 -0
  61. {ominfra-0.0.0.dev199/ominfra/manage/remote → ominfra-0.0.0.dev200/ominfra/manage/deploy}/__init__.py +0 -0
  62. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/apps.py +0 -0
  63. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/commands.py +0 -0
  64. {ominfra-0.0.0.dev199/ominfra/manage/system → ominfra-0.0.0.dev200/ominfra/manage/deploy/conf}/__init__.py +0 -0
  65. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/conf/inject.py +0 -0
  66. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/conf/manager.py +0 -0
  67. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/conf/specs.py +0 -0
  68. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/config.py +0 -0
  69. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/deploy.py +0 -0
  70. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/git.py +0 -0
  71. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/inject.py +0 -0
  72. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/injection.py +0 -0
  73. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/interp.py +0 -0
  74. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/nginx.py +0 -0
  75. {ominfra-0.0.0.dev199/ominfra/manage/targets → ominfra-0.0.0.dev200/ominfra/manage/deploy/paths}/__init__.py +0 -0
  76. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/paths/inject.py +0 -0
  77. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/paths/manager.py +0 -0
  78. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/paths/owners.py +0 -0
  79. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/paths/paths.py +0 -0
  80. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/paths/specs.py +0 -0
  81. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/paths/types.py +0 -0
  82. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/specs.py +0 -0
  83. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/systemd.py +0 -0
  84. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/tags.py +0 -0
  85. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/tmp.py +0 -0
  86. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/types.py +0 -0
  87. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/deploy/venvs.py +0 -0
  88. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/inject.py +0 -0
  89. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/main.py +0 -0
  90. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/marshal.py +0 -0
  91. {ominfra-0.0.0.dev199/ominfra/scripts → ominfra-0.0.0.dev200/ominfra/manage/remote}/__init__.py +0 -0
  92. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/_main.py +0 -0
  93. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/channel.py +0 -0
  94. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/config.py +0 -0
  95. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/connection.py +0 -0
  96. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/execution.py +0 -0
  97. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/inject.py +0 -0
  98. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/payload.py +0 -0
  99. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/remote/spawning.py +0 -0
  100. {ominfra-0.0.0.dev199/ominfra/supervisor/utils → ominfra-0.0.0.dev200/ominfra/manage/system}/__init__.py +0 -0
  101. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/system/commands.py +0 -0
  102. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/system/config.py +0 -0
  103. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/system/inject.py +0 -0
  104. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/system/packages.py +0 -0
  105. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/system/platforms.py +0 -0
  106. {ominfra-0.0.0.dev199/ominfra/tailscale → ominfra-0.0.0.dev200/ominfra/manage/targets}/__init__.py +0 -0
  107. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/targets/bestpython.py +0 -0
  108. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/targets/bestpython.sh +0 -0
  109. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/targets/connection.py +0 -0
  110. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/targets/inject.py +0 -0
  111. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/manage/targets/targets.py +0 -0
  112. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/pyremote.py +0 -0
  113. {ominfra-0.0.0.dev199/ominfra/tools → ominfra-0.0.0.dev200/ominfra/scripts}/__init__.py +0 -0
  114. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/scripts/journald2aws.py +0 -0
  115. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/scripts/manage.py +0 -0
  116. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/scripts/supervisor.py +0 -0
  117. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/ssh.py +0 -0
  118. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/LICENSE.txt +0 -0
  119. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/__init__.py +0 -0
  120. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/__main__.py +0 -0
  121. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/configs.py +0 -0
  122. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/dispatchers.py +0 -0
  123. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/dispatchersimpl.py +0 -0
  124. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/events.py +0 -0
  125. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/exceptions.py +0 -0
  126. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/groups.py +0 -0
  127. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/groupsimpl.py +0 -0
  128. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/http.py +0 -0
  129. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/inject.py +0 -0
  130. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/io.py +0 -0
  131. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/main.py +0 -0
  132. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/pipes.py +0 -0
  133. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/privileges.py +0 -0
  134. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/process.py +0 -0
  135. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/processimpl.py +0 -0
  136. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/setup.py +0 -0
  137. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/setupimpl.py +0 -0
  138. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/signals.py +0 -0
  139. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/spawning.py +0 -0
  140. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/spawningimpl.py +0 -0
  141. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/states.py +0 -0
  142. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/supervisor.py +0 -0
  143. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/types.py +0 -0
  144. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/collections.py +0 -0
  145. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/diag.py +0 -0
  146. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/fds.py +0 -0
  147. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/fs.py +0 -0
  148. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/os.py +0 -0
  149. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/ostypes.py +0 -0
  150. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/signals.py +0 -0
  151. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/strings.py +0 -0
  152. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/supervisor/utils/users.py +0 -0
  153. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/systemd.py +0 -0
  154. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/tailscale/api.py +0 -0
  155. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/tailscale/cli.py +0 -0
  156. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/threadworkers.py +0 -0
  157. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra/tools/listresources.py +0 -0
  158. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra.egg-info/dependency_links.txt +0 -0
  159. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra.egg-info/entry_points.txt +0 -0
  160. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/ominfra.egg-info/top_level.txt +0 -0
  161. {ominfra-0.0.0.dev199 → ominfra-0.0.0.dev200}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: ominfra
3
- Version: 0.0.0.dev199
3
+ Version: 0.0.0.dev200
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,9 +12,9 @@ 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.dev199
16
- Requires-Dist: omlish==0.0.0.dev199
17
- Requires-Dist: omserv==0.0.0.dev199
15
+ Requires-Dist: omdev==0.0.0.dev200
16
+ Requires-Dist: omlish==0.0.0.dev200
17
+ Requires-Dist: omserv==0.0.0.dev200
18
18
  Provides-Extra: all
19
19
  Requires-Dist: paramiko~=3.5; extra == "all"
20
20
  Requires-Dist: asyncssh~=2.18; extra == "all"
@@ -0,0 +1,101 @@
1
+ import dataclasses as dc
2
+ import typing as ta
3
+
4
+ from omlish import check
5
+ from omlish import lang
6
+
7
+
8
+ DateTime = ta.NewType('DateTime', str)
9
+ MillisecondDateTime = ta.NewType('MillisecondDateTime', str)
10
+
11
+ Timestamp = ta.NewType('Timestamp', str)
12
+
13
+
14
+ ##
15
+
16
+
17
+ class TagList:
18
+ pass
19
+
20
+
21
+ ##
22
+
23
+
24
+ class MEMBER_NAME(lang.Marker): # noqa
25
+ pass
26
+
27
+
28
+ class SHAPE_NAME(lang.Marker): # noqa
29
+ pass
30
+
31
+
32
+ ##
33
+
34
+
35
+ def common_metadata(
36
+ *,
37
+ shape_name: str | None = None,
38
+ ) -> dict[ta.Any, ta.Any]:
39
+ md = {}
40
+
41
+ if shape_name is not None:
42
+ md[SHAPE_NAME] = shape_name
43
+
44
+ return md
45
+
46
+
47
+ ##
48
+
49
+
50
+ def shape_metadata(
51
+ **kwargs: ta.Any,
52
+ ) -> dict[ta.Any, ta.Any]:
53
+ md = {**common_metadata(**kwargs)}
54
+
55
+ return md
56
+
57
+
58
+ @dc.dataclass(frozen=True)
59
+ class Shape:
60
+ __shape_metadata__: ta.ClassVar[ta.Mapping[ta.Any, ta.Any]]
61
+
62
+ def __init_subclass__(
63
+ cls,
64
+ *,
65
+ shape_name: str | None = None,
66
+ **kwargs: ta.Any,
67
+ ) -> None:
68
+ super().__init_subclass__(**kwargs)
69
+
70
+ check.state(not hasattr(cls, '__shape_metadata__'))
71
+
72
+ cls.__shape_metadata__ = shape_metadata(**kwargs)
73
+
74
+
75
+ ##
76
+
77
+
78
+ def field_metadata(
79
+ *,
80
+ member_name: str | None = None,
81
+ **kwargs: ta.Any,
82
+ ) -> dict[ta.Any, ta.Any]:
83
+ md = {**common_metadata(**kwargs)}
84
+
85
+ if member_name is not None:
86
+ md[MEMBER_NAME] = member_name
87
+
88
+ return md
89
+
90
+
91
+ ##
92
+
93
+
94
+ @dc.dataclass(frozen=True, eq=False, kw_only=True)
95
+ class Operation:
96
+ name: str
97
+
98
+ input: type[Shape] | None = None
99
+ output: type[Shape] | None = None
100
+
101
+ errors: ta.Sequence[type[Shape]] | None = None
@@ -0,0 +1,4 @@
1
+ if __name__ == '__main__':
2
+ from .cli import _main # noqa
3
+
4
+ _main()
@@ -0,0 +1,130 @@
1
+ import dataclasses as dc
2
+ import os.path
3
+ import sys
4
+ import typing as ta
5
+
6
+ from omlish import lang
7
+ from omlish import marshal as msh
8
+ from omlish.argparse import all as ap
9
+ from omlish.configs import all as configs
10
+
11
+ from .gen import ModelGen
12
+
13
+
14
+ ##
15
+
16
+
17
+ class Cli(ap.Cli):
18
+ def _arg_list(self, s: ta.Iterable[str] | None) -> list[str]:
19
+ return list(lang.flatten(e.split(',') for e in s or []))
20
+
21
+ #
22
+
23
+ def _gen_module(
24
+ self,
25
+ service_name: str,
26
+ *,
27
+ shape_names: ta.Iterable[str] | None = None,
28
+ operation_names: ta.Iterable[str] | None = None,
29
+ ) -> str:
30
+ service_model = ModelGen.load_service_model(service_name)
31
+
32
+ bmg = ModelGen(
33
+ service_model,
34
+ shape_names=ModelGen.get_referenced_shape_names(
35
+ service_model,
36
+ shape_names=shape_names or (),
37
+ operation_names=operation_names or (),
38
+ ),
39
+ operation_names=operation_names or (),
40
+ )
41
+
42
+ return bmg.gen_module()
43
+
44
+ @ap.cmd(
45
+ ap.arg('service'),
46
+ ap.arg('-s', '--shape', action='append'),
47
+ ap.arg('-o', '--operation', action='append'),
48
+ )
49
+ def gen_module(self) -> None:
50
+ mod = self._gen_module(
51
+ self.args.service,
52
+ shape_names=self._arg_list(self.args.shape),
53
+ operation_names=self._arg_list(self.args.operation),
54
+ )
55
+
56
+ sys.stdout.write(mod)
57
+
58
+ #
59
+
60
+ @dc.dataclass(frozen=True)
61
+ class ServicesConfig:
62
+ @dc.dataclass(frozen=True)
63
+ class Service:
64
+ name: str
65
+ shapes: ta.Sequence[str] | None = None
66
+ operations: ta.Sequence[str] | None = None
67
+
68
+ services: ta.Sequence[Service] | None = None
69
+
70
+ def _gen_service(
71
+ self,
72
+ svc: ServicesConfig.Service,
73
+ output_dir: str,
74
+ ) -> None:
75
+ mod = self._gen_module(
76
+ svc.name,
77
+ shape_names=svc.shapes,
78
+ operation_names=svc.operations,
79
+ )
80
+
81
+ output_file = os.path.join(output_dir, f'{svc.name}.py')
82
+ with open(output_file, 'w') as f:
83
+ f.write(mod)
84
+
85
+ @ap.cmd(
86
+ ap.arg('config-file', nargs='?'),
87
+ )
88
+ def gen_services(self) -> None:
89
+ config_file = self.args.config_file
90
+ if config_file is None:
91
+ config_file = os.path.abspath(os.path.join(os.path.dirname(__file__), '../services/services.toml'))
92
+
93
+ cfg_dct = dict(configs.DEFAULT_FILE_LOADER.load_file(config_file).as_map())
94
+ cfg_dct = configs.processing.matched_rewrite(
95
+ configs.processing.build_named_children,
96
+ cfg_dct,
97
+ ('services',),
98
+ )
99
+ cfg: Cli.ServicesConfig = msh.unmarshal(cfg_dct, Cli.ServicesConfig)
100
+
101
+ output_dir = os.path.dirname(os.path.abspath(config_file))
102
+
103
+ for svc in cfg.services or []:
104
+ self._gen_service(svc, output_dir)
105
+
106
+ #
107
+
108
+ @ap.cmd(
109
+ ap.arg('service'),
110
+ )
111
+ def list_shapes(self) -> None:
112
+ service_model = ModelGen.load_service_model(self.args.service)
113
+ for name in sorted(service_model.shape_names):
114
+ print(name)
115
+
116
+ @ap.cmd(
117
+ ap.arg('service'),
118
+ )
119
+ def list_operations(self) -> None:
120
+ service_model = ModelGen.load_service_model(self.args.service)
121
+ for name in sorted(service_model.operation_names):
122
+ print(name)
123
+
124
+
125
+ def _main() -> None:
126
+ Cli().cli_run_and_exit()
127
+
128
+
129
+ if __name__ == '__main__':
130
+ _main()
@@ -0,0 +1,440 @@
1
+ """
2
+ TODO:
3
+ - default values? nullability? maybe a new_default helper?
4
+ - relative import base
5
+ """
6
+ import dataclasses as dc
7
+ import io
8
+ import typing as ta
9
+
10
+ from omlish import check
11
+ from omlish import collections as col
12
+ from omlish import lang
13
+
14
+
15
+ if ta.TYPE_CHECKING:
16
+ import botocore.model
17
+ import botocore.session
18
+ else:
19
+ botocore = lang.proxy_import('botocore', extras=[
20
+ 'model',
21
+ 'session',
22
+ ])
23
+
24
+
25
+ ##
26
+
27
+
28
+ class ModelGen:
29
+ def __init__(
30
+ self,
31
+ service_model: 'botocore.model.ServiceModel',
32
+ *,
33
+ shape_names: ta.Iterable[str] = (),
34
+ operation_names: ta.Iterable[str] = (),
35
+ ) -> None:
36
+ super().__init__()
37
+
38
+ self._service_model = service_model
39
+ self._shape_names = list(check.not_isinstance(shape_names, str))
40
+ self._operation_names = list(check.not_isinstance(operation_names, str))
41
+
42
+ @property
43
+ def service_model(self) -> 'botocore.model.ServiceModel':
44
+ return self._service_model
45
+
46
+ @property
47
+ def shape_names(self) -> ta.Sequence[str]:
48
+ return self._shape_names
49
+
50
+ @property
51
+ def operation_names(self) -> ta.Sequence[str]:
52
+ return self._operation_names
53
+
54
+ #
55
+
56
+ @classmethod
57
+ def load_service_model(
58
+ cls,
59
+ service_name: str,
60
+ *,
61
+ type_name: ta.Literal['service-2', 'paginators-1', 'waiters-2'] = 'service-2',
62
+ api_version: str | None = None,
63
+ ) -> 'botocore.model.ServiceModel':
64
+ session = botocore.session.get_session()
65
+ loader = session.get_component('data_loader')
66
+ json_model = loader.load_service_model(service_name, type_name, api_version=api_version)
67
+ return botocore.model.ServiceModel(json_model, service_name=service_name)
68
+
69
+ @classmethod
70
+ def get_referenced_shape_names(
71
+ cls,
72
+ service_model: 'botocore.model.ServiceModel',
73
+ *,
74
+ shape_names: ta.Iterable[str] = (),
75
+ operation_names: ta.Iterable[str] = (),
76
+ ) -> list[str]:
77
+ todo = set(check.not_isinstance(shape_names, str))
78
+
79
+ for on in operation_names:
80
+ op = service_model.operation_model(on)
81
+ for osh in [
82
+ op.input_shape,
83
+ op.output_shape,
84
+ *op.error_shapes,
85
+ ]:
86
+ if osh is not None:
87
+ todo.add(osh.name)
88
+
89
+ seen = set(cls.BASE_TYPE_ANNS)
90
+
91
+ dct: dict[str, set[str]] = {}
92
+ while todo:
93
+ cur = todo.pop()
94
+ seen.add(cur)
95
+
96
+ shape: botocore.model.Shape = service_model.shape_for(cur)
97
+
98
+ if isinstance(shape, botocore.model.StructureShape):
99
+ deps = {m.name for m in shape.members.values()}
100
+
101
+ elif isinstance(shape, botocore.model.MapShape):
102
+ deps = {shape.key.name, shape.value.name}
103
+
104
+ elif isinstance(shape, botocore.model.ListShape):
105
+ deps = {shape.member.name}
106
+
107
+ else:
108
+ deps = set()
109
+
110
+ dct[shape.name] = deps
111
+ todo.update(deps - seen)
112
+
113
+ return list(lang.flatten(sorted(s - cls.BASE_SHAPE_NAMES) for s in col.mut_toposort(dct)))
114
+
115
+ #
116
+
117
+ BASE_TYPE_ANNS: ta.ClassVar[ta.Mapping[str, str]] = {
118
+ 'Boolean': 'bool',
119
+ 'Integer': 'int',
120
+ 'String': 'str',
121
+ 'DateTime': '_base.DateTime',
122
+ 'MillisecondDateTime': '_base.MillisecondDateTime',
123
+ 'TagList': '_base.TagList',
124
+ }
125
+
126
+ BASE_SHAPE_NAMES: ta.ClassVar[ta.AbstractSet[str]] = set(BASE_TYPE_ANNS)
127
+
128
+ def get_type_ann(
129
+ self,
130
+ name: str,
131
+ *,
132
+ unquoted_names: bool = False,
133
+ ) -> str | None:
134
+ try:
135
+ return self.BASE_TYPE_ANNS[name]
136
+ except KeyError:
137
+ pass
138
+
139
+ if name in self._shape_names:
140
+ if not unquoted_names:
141
+ return f"'{name}'"
142
+ else:
143
+ return name
144
+
145
+ return None
146
+
147
+ #
148
+
149
+ DEMANGLE_PREFIXES: ta.ClassVar[ta.Sequence[str]] = [
150
+ 'AAAA',
151
+ 'ACL',
152
+ 'ACP',
153
+ 'CRC32',
154
+ 'CRC32C',
155
+ 'ETag',
156
+ 'KMS',
157
+ 'MD5',
158
+ 'MFA',
159
+ 'SHA1',
160
+ 'SHA256',
161
+ 'SSE',
162
+ ]
163
+
164
+ def demangle_name(self, n: str) -> str:
165
+ ps: list[str] = []
166
+ while n:
167
+ ms: list[tuple[str, int]] = []
168
+ for pfx in self.DEMANGLE_PREFIXES:
169
+ if (i := n.find(pfx)) >= 0:
170
+ ms.append((pfx, i))
171
+ if not ms:
172
+ ps.append(n)
173
+ break
174
+ if len(ms) > 1:
175
+ m = sorted(ms, key=lambda t: (t[1], -len(t[0])))[0]
176
+ else:
177
+ m = ms[0]
178
+ pfx, i = m
179
+ l, r = n[:i], n[i + len(pfx):]
180
+ if l:
181
+ ps.append(l)
182
+ ps.append(pfx.lower())
183
+ n = r
184
+ return '_'.join(lang.snake_case(p) for p in ps)
185
+
186
+ #
187
+
188
+ PREAMBLE_LINES: ta.Sequence[str] = [
189
+ '# flake8: noqa: E501',
190
+ '# ruff: noqa: S105',
191
+ '# fmt: off',
192
+ 'import dataclasses as _dc # noqa',
193
+ 'import enum as _enum # noqa',
194
+ 'import typing as _ta # noqa',
195
+ '',
196
+ 'from .. import base as _base # noqa',
197
+ '',
198
+ '',
199
+ '##',
200
+ '',
201
+ '',
202
+ ]
203
+
204
+ def gen_preamble(self) -> str:
205
+ return '\n'.join(self.PREAMBLE_LINES)
206
+
207
+ #
208
+
209
+ PRIMITIVE_SHAPE_TYPES: ta.ClassVar[ta.Mapping[str, str]] = {
210
+ 'integer': 'int',
211
+ 'long': 'int',
212
+ 'blob': 'bytes',
213
+ 'boolean': 'bool',
214
+ 'timestamp': '_base.Timestamp',
215
+ }
216
+
217
+ @dc.dataclass(frozen=True)
218
+ class ShapeSrc:
219
+ src: str
220
+
221
+ class_name: str | None = dc.field(default=None, kw_only=True)
222
+ double_space: bool = False
223
+
224
+ def gen_shape(
225
+ self,
226
+ name: str,
227
+ *,
228
+ unquoted_names: bool = False,
229
+ ) -> ShapeSrc:
230
+ shape: botocore.model.Shape = self._service_model.shape_for(name)
231
+
232
+ if isinstance(shape, botocore.model.StructureShape):
233
+ lines: list[str] = []
234
+
235
+ mds = [
236
+ f'shape_name={shape.name!r}',
237
+ ]
238
+
239
+ lines.extend([
240
+ '@_dc.dataclass(frozen=True)',
241
+ f'class {shape.name}(',
242
+ ' _base.Shape,',
243
+ *[f' {dl},' for dl in mds],
244
+ '):',
245
+ ])
246
+
247
+ if not shape.members:
248
+ lines.append(' pass')
249
+
250
+ for mn, ms in shape.members.items():
251
+ fn = self.demangle_name(mn)
252
+ mds = [
253
+ f'member_name={mn!r}',
254
+ f'shape_name={ms.name!r}',
255
+ ]
256
+ ma = self.get_type_ann(
257
+ ms.name,
258
+ unquoted_names=unquoted_names,
259
+ )
260
+ fls = [
261
+ f'{fn}: {ma or ms.name} = _dc.field(metadata=_base.field_metadata(',
262
+ *[f' {dl},' for dl in mds],
263
+ '))',
264
+ ]
265
+ if ma is None:
266
+ fls = ['# ' + fl for fl in fls]
267
+ lines.append('\n'.join(' ' + fl for fl in fls))
268
+
269
+ return self.ShapeSrc(
270
+ '\n'.join(lines),
271
+ class_name=shape.name,
272
+ double_space=True,
273
+ )
274
+
275
+ elif isinstance(shape, botocore.model.ListShape):
276
+ mn = shape.member.name
277
+ ma = self.get_type_ann(
278
+ mn,
279
+ unquoted_names=unquoted_names,
280
+ )
281
+ l = f'{shape.name}: _ta.TypeAlias = _ta.Sequence[{ma or mn}]'
282
+ if ma is None:
283
+ l = '# ' + l
284
+ return self.ShapeSrc(l)
285
+
286
+ elif isinstance(shape, botocore.model.MapShape):
287
+ # shape.key, shape.value
288
+ kn = shape.key.name
289
+ ka = self.get_type_ann(
290
+ kn,
291
+ unquoted_names=unquoted_names,
292
+ )
293
+ vn = shape.key.name
294
+ va = self.get_type_ann(
295
+ vn,
296
+ unquoted_names=unquoted_names,
297
+ )
298
+ l = f'{shape.name}: _ta.TypeAlias = _ta.Mapping[{ka or kn}, {va or vn}]'
299
+ if ka is None or va is None:
300
+ l = '# ' + l
301
+ return self.ShapeSrc(l)
302
+
303
+ elif isinstance(shape, botocore.model.StringShape):
304
+ if shape.enum:
305
+ ls = [
306
+ f'class {shape.name}(_enum.Enum):',
307
+ ]
308
+ for v in shape.enum:
309
+ n = v.upper()
310
+ for c in '.-:':
311
+ n = n.replace(c, '_')
312
+ ls.append(f' {n} = {v!r}')
313
+ return self.ShapeSrc(
314
+ '\n'.join(ls),
315
+ double_space=True,
316
+ )
317
+
318
+ else:
319
+ return self.ShapeSrc(f"{shape.name} = _ta.NewType('{shape.name}', str)")
320
+
321
+ elif (pt := self.PRIMITIVE_SHAPE_TYPES.get(shape.type_name)) is not None:
322
+ return self.ShapeSrc(f"{shape.name} = _ta.NewType('{shape.name}', {pt})")
323
+
324
+ else:
325
+ raise TypeError(shape.type_name)
326
+
327
+ def gen_all_shapes(
328
+ self,
329
+ out: ta.TextIO,
330
+ *,
331
+ unquoted_names: bool = False,
332
+ ) -> None:
333
+ shape_srcs = [
334
+ self.gen_shape(
335
+ shape_name,
336
+ unquoted_names=unquoted_names,
337
+ )
338
+ for shape_name in self.shape_names
339
+ ]
340
+
341
+ all_shapes: list[str] = []
342
+
343
+ prev_shape_src: ModelGen.ShapeSrc | None = None
344
+ for shape_src in shape_srcs:
345
+ if prev_shape_src is not None:
346
+ out.write('\n')
347
+ if shape_src.double_space or prev_shape_src.double_space:
348
+ out.write('\n')
349
+ out.write(shape_src.src)
350
+ out.write('\n')
351
+ if shape_src.class_name is not None:
352
+ all_shapes.append(shape_src.class_name)
353
+ prev_shape_src = shape_src
354
+
355
+ out.write('\n\n')
356
+ out.write('ALL_SHAPES: frozenset[type[_base.Shape]] = frozenset([\n')
357
+ for n in all_shapes:
358
+ out.write(f' {n},\n')
359
+ out.write('])\n')
360
+
361
+ #
362
+
363
+ @dc.dataclass(frozen=True)
364
+ class OperationSrc:
365
+ src: str
366
+ name: str
367
+
368
+ def gen_operation(
369
+ self,
370
+ name: str,
371
+ ) -> OperationSrc:
372
+ operation: botocore.model.OperationModel = self._service_model.operation_model(name)
373
+
374
+ dcn = self.demangle_name(operation.name).upper()
375
+
376
+ fls = [
377
+ f'name={operation.name!r},',
378
+ ]
379
+
380
+ if operation.input_shape is not None:
381
+ fls.append(f'input={operation.input_shape.name},')
382
+ if operation.output_shape is not None:
383
+ fls.append(f'output={operation.output_shape.name},')
384
+
385
+ if operation.error_shapes:
386
+ fls.append('errors=[')
387
+ for osn in [es.name for es in operation.error_shapes]:
388
+ fls.append(f' {osn},')
389
+ fls.append('],')
390
+
391
+ lines = [
392
+ f'{dcn} = _base.Operation(',
393
+ *[f' {fl}' for fl in fls],
394
+ ')',
395
+ ]
396
+
397
+ return self.OperationSrc('\n'.join(lines), dcn)
398
+
399
+ def gen_all_operations(
400
+ self,
401
+ out: ta.TextIO,
402
+ ) -> None:
403
+ all_operations: list[str] = []
404
+
405
+ for i, name in enumerate(sorted(self._operation_names)):
406
+ if i:
407
+ out.write('\n')
408
+ ops = self.gen_operation(
409
+ name,
410
+ )
411
+ all_operations.append(ops.name)
412
+ out.write(ops.src)
413
+ out.write('\n')
414
+ out.write('\n')
415
+
416
+ out.write('\n')
417
+ out.write('ALL_OPERATIONS: frozenset[_base.Operation] = frozenset([\n')
418
+ for n in all_operations:
419
+ out.write(f' {n},\n')
420
+ out.write('])\n')
421
+
422
+ #
423
+
424
+ def gen_module(self) -> str:
425
+ out = io.StringIO()
426
+
427
+ out.write(self.gen_preamble())
428
+ out.write('\n')
429
+
430
+ self.gen_all_shapes(
431
+ out,
432
+ unquoted_names=True,
433
+ )
434
+
435
+ if self._operation_names:
436
+ out.write('\n\n##\n\n\n')
437
+
438
+ self.gen_all_operations(out)
439
+
440
+ return out.getvalue()