omdev 0.0.0.dev213__tar.gz → 0.0.0.dev214__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (229) hide show
  1. {omdev-0.0.0.dev213/omdev.egg-info → omdev-0.0.0.dev214}/PKG-INFO +2 -2
  2. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/.manifests.json +1 -1
  3. omdev-0.0.0.dev214/omdev/ci/cache.py +147 -0
  4. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/ci.py +120 -118
  5. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/cli.py +50 -24
  6. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/compose.py +1 -8
  7. omdev-0.0.0.dev214/omdev/ci/consts.py +1 -0
  8. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/docker.py +4 -6
  9. omdev-0.0.0.dev213/omdev/ci/github/cacheapi.py → omdev-0.0.0.dev214/omdev/ci/github/api.py +0 -1
  10. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/github/bootstrap.py +8 -1
  11. omdev-0.0.0.dev214/omdev/ci/github/cache.py +71 -0
  12. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/github/cli.py +9 -5
  13. omdev-0.0.0.dev214/omdev/ci/github/client.py +492 -0
  14. omdev-0.0.0.dev214/omdev/ci/github/env.py +21 -0
  15. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/requirements.py +0 -1
  16. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/shell.py +0 -1
  17. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/utils.py +2 -14
  18. omdev-0.0.0.dev214/omdev/pyproject/__init__.py +1 -0
  19. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/ci.py +1149 -922
  20. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/docker.py +6 -0
  21. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214/omdev.egg-info}/PKG-INFO +2 -2
  22. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev.egg-info/SOURCES.txt +4 -2
  23. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev.egg-info/requires.txt +1 -1
  24. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/pyproject.toml +2 -2
  25. omdev-0.0.0.dev213/omdev/ci/cache.py +0 -168
  26. omdev-0.0.0.dev213/omdev/ci/github/cache.py +0 -324
  27. omdev-0.0.0.dev213/omdev/ci/github/curl.py +0 -209
  28. omdev-0.0.0.dev213/omdev/tools/pawk/__init__.py +0 -0
  29. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/LICENSE +0 -0
  30. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/MANIFEST.in +0 -0
  31. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/README.rst +0 -0
  32. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/__about__.py +0 -0
  33. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/__init__.py +0 -0
  34. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/__init__.py +0 -0
  35. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/__main__.py +0 -0
  36. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/gen.py +0 -0
  37. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/imports.py +0 -0
  38. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/main.py +0 -0
  39. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/manifests.py +0 -0
  40. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/resources.py +0 -0
  41. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/srcfiles.py +0 -0
  42. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/strip.py +0 -0
  43. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/types.py +0 -0
  44. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/amalg/typing.py +0 -0
  45. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/antlr/__init__.py +0 -0
  46. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/antlr/consts.py +0 -0
  47. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/antlr/gen.py +0 -0
  48. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/bracepy.py +0 -0
  49. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/__init__.py +0 -0
  50. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/__init__.py +0 -0
  51. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/cache.py +0 -0
  52. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/contexts.py +0 -0
  53. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/currents.py +0 -0
  54. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/fns.py +0 -0
  55. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/resolvers.py +0 -0
  56. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/storage.py +0 -0
  57. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/compute/types.py +0 -0
  58. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/data/__init__.py +0 -0
  59. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/data/actions.py +0 -0
  60. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/data/cache.py +0 -0
  61. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/data/consts.py +0 -0
  62. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/data/defaults.py +0 -0
  63. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/data/manifests.py +0 -0
  64. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cache/data/specs.py +0 -0
  65. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cc/__init__.py +0 -0
  66. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cc/__main__.py +0 -0
  67. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cc/cdeps.py +0 -0
  68. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cc/cdeps.toml +0 -0
  69. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cc/cli.py +0 -0
  70. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/__init__.py +0 -0
  71. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_boilerplate.cc +0 -0
  72. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/LICENSE +0 -0
  73. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/__init__.py +0 -0
  74. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/build_ext.py +0 -0
  75. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
  76. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
  77. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/compilers/options.py +0 -0
  78. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
  79. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/dir_util.py +0 -0
  80. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/errors.py +0 -0
  81. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/extension.py +0 -0
  82. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/file_util.py +0 -0
  83. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/modified.py +0 -0
  84. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/spawn.py +0 -0
  85. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/sysconfig.py +0 -0
  86. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/util.py +0 -0
  87. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/_distutils/version.py +0 -0
  88. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/build.py +0 -0
  89. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/cmake.py +0 -0
  90. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/importhook.py +0 -0
  91. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/magic.py +0 -0
  92. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cexts/scan.py +0 -0
  93. {omdev-0.0.0.dev213/omdev/interp → omdev-0.0.0.dev214/omdev/ci}/__init__.py +0 -0
  94. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ci/__main__.py +0 -0
  95. {omdev-0.0.0.dev213/omdev/ci → omdev-0.0.0.dev214/omdev/ci/github}/__init__.py +0 -0
  96. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/classdot.py +0 -0
  97. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/__init__.py +0 -0
  98. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/__main__.py +0 -0
  99. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/_pathhack.py +0 -0
  100. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/clicli.py +0 -0
  101. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/install.py +0 -0
  102. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/main.py +0 -0
  103. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/managers.py +0 -0
  104. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cli/types.py +0 -0
  105. {omdev-0.0.0.dev213/omdev/ci/github → omdev-0.0.0.dev214/omdev/clipboard}/__init__.py +0 -0
  106. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/clipboard/clipboard.py +0 -0
  107. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/clipboard/darwin_cf.py +0 -0
  108. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/clipboard/linux_x11.py +0 -0
  109. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/cmake.py +0 -0
  110. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/findimports.py +0 -0
  111. {omdev-0.0.0.dev213/omdev/clipboard → omdev-0.0.0.dev214/omdev/git}/__init__.py +0 -0
  112. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/git/revisions.py +0 -0
  113. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/git/shallow.py +0 -0
  114. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/git/status.py +0 -0
  115. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/imgur.py +0 -0
  116. {omdev-0.0.0.dev213/omdev/manifests → omdev-0.0.0.dev214/omdev/interp}/__init__.py +0 -0
  117. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/__main__.py +0 -0
  118. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/cli.py +0 -0
  119. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/default.py +0 -0
  120. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/inject.py +0 -0
  121. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/inspect.py +0 -0
  122. {omdev-0.0.0.dev213/omdev/git → omdev-0.0.0.dev214/omdev/interp/providers}/__init__.py +0 -0
  123. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/providers/base.py +0 -0
  124. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/providers/inject.py +0 -0
  125. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/providers/running.py +0 -0
  126. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/providers/standalone.py +0 -0
  127. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/providers/system.py +0 -0
  128. {omdev-0.0.0.dev213/omdev/interp/providers → omdev-0.0.0.dev214/omdev/interp/pyenv}/__init__.py +0 -0
  129. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/pyenv/inject.py +0 -0
  130. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/pyenv/install.py +0 -0
  131. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/pyenv/provider.py +0 -0
  132. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/pyenv/pyenv.py +0 -0
  133. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/resolvers.py +0 -0
  134. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/types.py +0 -0
  135. {omdev-0.0.0.dev213/omdev/interp/pyenv → omdev-0.0.0.dev214/omdev/interp/uv}/__init__.py +0 -0
  136. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/uv/inject.py +0 -0
  137. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/uv/provider.py +0 -0
  138. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/uv/uv.py +0 -0
  139. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/interp/venvs.py +0 -0
  140. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/magic/__init__.py +0 -0
  141. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/magic/__main__.py +0 -0
  142. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/magic/cli.py +0 -0
  143. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/magic/find.py +0 -0
  144. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/magic/magic.py +0 -0
  145. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/magic/prepare.py +0 -0
  146. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/magic/styles.py +0 -0
  147. {omdev-0.0.0.dev213/omdev/pyproject → omdev-0.0.0.dev214/omdev/manifests}/__init__.py +0 -0
  148. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/manifests/__main__.py +0 -0
  149. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/manifests/build.py +0 -0
  150. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/manifests/main.py +0 -0
  151. {omdev-0.0.0.dev213/omdev/interp/uv → omdev-0.0.0.dev214/omdev/mypy}/__init__.py +0 -0
  152. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/mypy/debug.py +0 -0
  153. {omdev-0.0.0.dev213/omdev/mypy → omdev-0.0.0.dev214/omdev/packaging}/__init__.py +0 -0
  154. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/packaging/marshal.py +0 -0
  155. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/packaging/names.py +0 -0
  156. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/packaging/requires.py +0 -0
  157. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/packaging/specifiers.py +0 -0
  158. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/packaging/versions.py +0 -0
  159. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pip.py +0 -0
  160. {omdev-0.0.0.dev213/omdev/packaging → omdev-0.0.0.dev214/omdev/precheck}/__init__.py +0 -0
  161. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/precheck/__main__.py +0 -0
  162. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/precheck/base.py +0 -0
  163. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/precheck/git.py +0 -0
  164. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/precheck/lite.py +0 -0
  165. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/precheck/main.py +0 -0
  166. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/precheck/manifests.py +0 -0
  167. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/precheck/scripts.py +0 -0
  168. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ptk/__init__.py +0 -0
  169. {omdev-0.0.0.dev213/omdev/precheck → omdev-0.0.0.dev214/omdev/ptk/apps}/__init__.py +0 -0
  170. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/ptk/apps/ncdu.py +0 -0
  171. {omdev-0.0.0.dev213/omdev/ptk/apps → omdev-0.0.0.dev214/omdev/pycharm}/__init__.py +0 -0
  172. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pycharm/__main__.py +0 -0
  173. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pycharm/cli.py +0 -0
  174. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/__main__.py +0 -0
  175. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/cexts.py +0 -0
  176. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/cli.py +0 -0
  177. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/configs.py +0 -0
  178. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/inject.py +0 -0
  179. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/pkg.py +0 -0
  180. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/reqs.py +0 -0
  181. {omdev-0.0.0.dev213/omdev/pycharm → omdev-0.0.0.dev214/omdev/pyproject/resources}/__init__.py +0 -0
  182. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/resources/docker-dev.sh +0 -0
  183. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/resources/python.sh +0 -0
  184. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/pyproject/venvs.py +0 -0
  185. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/revisions.py +0 -0
  186. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/__init__.py +0 -0
  187. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/bumpversion.py +0 -0
  188. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/execrss.py +0 -0
  189. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/exectime.py +0 -0
  190. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/importtrace.py +0 -0
  191. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/interp.py +0 -0
  192. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/pyproject.py +0 -0
  193. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/slowcat.py +0 -0
  194. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/scripts/tmpexec.py +0 -0
  195. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/secrets.py +0 -0
  196. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tagstrings.py +0 -0
  197. {omdev-0.0.0.dev213/omdev/pyproject/resources → omdev-0.0.0.dev214/omdev/tokens}/__init__.py +0 -0
  198. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tokens/all.py +0 -0
  199. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tokens/tokenizert.py +0 -0
  200. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tokens/utils.py +0 -0
  201. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/__init__.py +0 -0
  202. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/cloc.py +0 -0
  203. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/doc.py +0 -0
  204. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/git.py +0 -0
  205. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/importscan.py +0 -0
  206. {omdev-0.0.0.dev213/omdev/tokens → omdev-0.0.0.dev214/omdev/tools/json}/__init__.py +0 -0
  207. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/json/__main__.py +0 -0
  208. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/json/cli.py +0 -0
  209. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/json/formats.py +0 -0
  210. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/json/io.py +0 -0
  211. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/json/parsing.py +0 -0
  212. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/json/processing.py +0 -0
  213. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/json/rendering.py +0 -0
  214. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/linehisto.py +0 -0
  215. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/mkenv.py +0 -0
  216. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/mkrelimp.py +0 -0
  217. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/notebook.py +0 -0
  218. {omdev-0.0.0.dev213/omdev/tools/json → omdev-0.0.0.dev214/omdev/tools/pawk}/__init__.py +0 -0
  219. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/pawk/__main__.py +0 -0
  220. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/pawk/pawk.py +0 -0
  221. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/pip.py +0 -0
  222. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/prof.py +0 -0
  223. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/qr.py +0 -0
  224. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/tools/sqlrepl.py +0 -0
  225. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev/wheelfile.py +0 -0
  226. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev.egg-info/dependency_links.txt +0 -0
  227. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev.egg-info/entry_points.txt +0 -0
  228. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/omdev.egg-info/top_level.txt +0 -0
  229. {omdev-0.0.0.dev213 → omdev-0.0.0.dev214}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: omdev
3
- Version: 0.0.0.dev213
3
+ Version: 0.0.0.dev214
4
4
  Summary: omdev
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,7 +12,7 @@ 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: omlish==0.0.0.dev213
15
+ Requires-Dist: omlish==0.0.0.dev214
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black~=24.10; extra == "all"
18
18
  Requires-Dist: pycparser~=2.22; extra == "all"
@@ -267,7 +267,7 @@
267
267
  "module": ".tools.docker",
268
268
  "attr": "_CLI_MODULE",
269
269
  "file": "omdev/tools/docker.py",
270
- "line": 258,
270
+ "line": 264,
271
271
  "value": {
272
272
  "$.cli.types.CliModule": {
273
273
  "cmd_name": "docker",
@@ -0,0 +1,147 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import abc
3
+ import os.path
4
+ import shutil
5
+ import typing as ta
6
+
7
+ from omlish.lite.cached import cached_nullary
8
+ from omlish.lite.check import check
9
+ from omlish.lite.logs import log
10
+
11
+ from .consts import CI_CACHE_VERSION
12
+
13
+
14
+ ##
15
+
16
+
17
+ @abc.abstractmethod
18
+ class FileCache(abc.ABC):
19
+ def __init__(
20
+ self,
21
+ *,
22
+ version: int = CI_CACHE_VERSION,
23
+ ) -> None:
24
+ super().__init__()
25
+
26
+ check.isinstance(version, int)
27
+ check.arg(version >= 0)
28
+ self._version = version
29
+
30
+ @property
31
+ def version(self) -> int:
32
+ return self._version
33
+
34
+ #
35
+
36
+ @abc.abstractmethod
37
+ def get_file(self, key: str) -> ta.Awaitable[ta.Optional[str]]:
38
+ raise NotImplementedError
39
+
40
+ @abc.abstractmethod
41
+ def put_file(
42
+ self,
43
+ key: str,
44
+ file_path: str,
45
+ *,
46
+ steal: bool = False,
47
+ ) -> ta.Awaitable[str]:
48
+ raise NotImplementedError
49
+
50
+
51
+ #
52
+
53
+
54
+ class DirectoryFileCache(FileCache):
55
+ def __init__(
56
+ self,
57
+ dir: str, # noqa
58
+ *,
59
+ no_create: bool = False,
60
+ no_purge: bool = False,
61
+ **kwargs: ta.Any,
62
+ ) -> None: # noqa
63
+ super().__init__(**kwargs)
64
+
65
+ self._dir = dir
66
+ self._no_create = no_create
67
+ self._no_purge = no_purge
68
+
69
+ #
70
+
71
+ VERSION_FILE_NAME = '.ci-cache-version'
72
+
73
+ @cached_nullary
74
+ def setup_dir(self) -> None:
75
+ version_file = os.path.join(self._dir, self.VERSION_FILE_NAME)
76
+
77
+ if self._no_create:
78
+ check.state(os.path.isdir(self._dir))
79
+
80
+ elif not os.path.isdir(self._dir):
81
+ os.makedirs(self._dir)
82
+ with open(version_file, 'w') as f:
83
+ f.write(str(self._version))
84
+ return
85
+
86
+ with open(version_file) as f:
87
+ dir_version = int(f.read().strip())
88
+
89
+ if dir_version == self._version:
90
+ return
91
+
92
+ if self._no_purge:
93
+ raise RuntimeError(f'{dir_version=} != {self._version=}')
94
+
95
+ dirs = [n for n in sorted(os.listdir(self._dir)) if os.path.isdir(os.path.join(self._dir, n))]
96
+ if dirs:
97
+ raise RuntimeError(
98
+ f'Refusing to remove stale cache dir {self._dir!r} '
99
+ f'due to present directories: {", ".join(dirs)}',
100
+ )
101
+
102
+ for n in sorted(os.listdir(self._dir)):
103
+ if n.startswith('.'):
104
+ continue
105
+ fp = os.path.join(self._dir, n)
106
+ check.state(os.path.isfile(fp))
107
+ log.debug('Purging stale cache file: %s', fp)
108
+ os.unlink(fp)
109
+
110
+ os.unlink(version_file)
111
+
112
+ with open(version_file, 'w') as f:
113
+ f.write(str(self._version))
114
+
115
+ #
116
+
117
+ def get_cache_file_path(
118
+ self,
119
+ key: str,
120
+ ) -> str:
121
+ self.setup_dir()
122
+ return os.path.join(self._dir, key)
123
+
124
+ def format_incomplete_file(self, f: str) -> str:
125
+ return os.path.join(os.path.dirname(f), f'_{os.path.basename(f)}.incomplete')
126
+
127
+ #
128
+
129
+ async def get_file(self, key: str) -> ta.Optional[str]:
130
+ cache_file_path = self.get_cache_file_path(key)
131
+ if not os.path.exists(cache_file_path):
132
+ return None
133
+ return cache_file_path
134
+
135
+ async def put_file(
136
+ self,
137
+ key: str,
138
+ file_path: str,
139
+ *,
140
+ steal: bool = False,
141
+ ) -> str:
142
+ cache_file_path = self.get_cache_file_path(key)
143
+ if steal:
144
+ shutil.move(file_path, cache_file_path)
145
+ else:
146
+ shutil.copyfile(file_path, cache_file_path)
147
+ return cache_file_path
@@ -1,20 +1,15 @@
1
1
  # ruff: noqa: UP006 UP007
2
- # @omlish-lite
3
2
  import dataclasses as dc
4
3
  import os.path
5
- import shutil
6
- import tarfile
7
- import tempfile
8
4
  import typing as ta
9
5
 
10
6
  from omlish.lite.cached import async_cached_nullary
11
7
  from omlish.lite.cached import cached_nullary
12
8
  from omlish.lite.check import check
13
9
  from omlish.lite.contextmanagers import AsyncExitStacked
14
- from omlish.lite.contextmanagers import defer
10
+ from omlish.os.temp import temp_file_context
15
11
 
16
12
  from .cache import FileCache
17
- from .cache import ShellCache
18
13
  from .compose import DockerComposeRun
19
14
  from .compose import get_compose_service_dependencies
20
15
  from .docker import build_docker_file_hash
@@ -25,13 +20,12 @@ from .docker import pull_docker_image
25
20
  from .docker import save_docker_tar_cmd
26
21
  from .docker import tag_docker_image
27
22
  from .requirements import build_requirements_hash
28
- from .requirements import download_requirements
29
23
  from .shell import ShellCmd
30
24
  from .utils import log_timing_context
31
25
 
32
26
 
33
27
  class Ci(AsyncExitStacked):
34
- FILE_NAME_HASH_LEN = 16
28
+ KEY_HASH_LEN = 16
35
29
 
36
30
  @dc.dataclass(frozen=True)
37
31
  class Config:
@@ -44,6 +38,8 @@ class Ci(AsyncExitStacked):
44
38
 
45
39
  cmd: ShellCmd
46
40
 
41
+ #
42
+
47
43
  requirements_txts: ta.Optional[ta.Sequence[str]] = None
48
44
 
49
45
  always_pull: bool = False
@@ -51,6 +47,10 @@ class Ci(AsyncExitStacked):
51
47
 
52
48
  no_dependencies: bool = False
53
49
 
50
+ run_options: ta.Optional[ta.Sequence[str]] = None
51
+
52
+ #
53
+
54
54
  def __post_init__(self) -> None:
55
55
  check.not_isinstance(self.requirements_txts, str)
56
56
 
@@ -58,42 +58,15 @@ class Ci(AsyncExitStacked):
58
58
  self,
59
59
  cfg: Config,
60
60
  *,
61
- shell_cache: ta.Optional[ShellCache] = None,
62
61
  file_cache: ta.Optional[FileCache] = None,
63
62
  ) -> None:
64
63
  super().__init__()
65
64
 
66
65
  self._cfg = cfg
67
- self._shell_cache = shell_cache
68
66
  self._file_cache = file_cache
69
67
 
70
68
  #
71
69
 
72
- async def _load_cache_docker_image(self, key: str) -> ta.Optional[str]:
73
- if self._shell_cache is None:
74
- return None
75
-
76
- get_cache_cmd = self._shell_cache.get_file_cmd(key)
77
- if get_cache_cmd is None:
78
- return None
79
-
80
- get_cache_cmd = dc.replace(get_cache_cmd, s=f'{get_cache_cmd.s} | zstd -cd --long') # noqa
81
-
82
- return await load_docker_tar_cmd(get_cache_cmd)
83
-
84
- async def _save_cache_docker_image(self, key: str, image: str) -> None:
85
- if self._shell_cache is None:
86
- return
87
-
88
- with self._shell_cache.put_file_cmd(key) as put_cache:
89
- put_cache_cmd = put_cache.cmd
90
-
91
- put_cache_cmd = dc.replace(put_cache_cmd, s=f'zstd | {put_cache_cmd.s}')
92
-
93
- await save_docker_tar_cmd(image, put_cache_cmd)
94
-
95
- #
96
-
97
70
  async def _load_docker_image(self, image: str) -> None:
98
71
  if not self._cfg.always_pull and (await is_docker_image_present(image)):
99
72
  return
@@ -114,24 +87,38 @@ class Ci(AsyncExitStacked):
114
87
  with log_timing_context(f'Load docker image: {image}'):
115
88
  await self._load_docker_image(image)
116
89
 
117
- @async_cached_nullary
118
- async def load_compose_service_dependencies(self) -> None:
119
- deps = get_compose_service_dependencies(
120
- self._cfg.compose_file,
121
- self._cfg.service,
122
- )
90
+ #
123
91
 
124
- for dep_image in deps.values():
125
- await self.load_docker_image(dep_image)
92
+ async def _load_cache_docker_image(self, key: str) -> ta.Optional[str]:
93
+ if self._file_cache is None:
94
+ return None
126
95
 
127
- #
96
+ cache_file = await self._file_cache.get_file(key)
97
+ if cache_file is None:
98
+ return None
128
99
 
129
- @cached_nullary
130
- def docker_file_hash(self) -> str:
131
- return build_docker_file_hash(self._cfg.docker_file)[:self.FILE_NAME_HASH_LEN]
100
+ get_cache_cmd = ShellCmd(f'cat {cache_file} | zstd -cd --long')
132
101
 
133
- async def _resolve_ci_image(self) -> str:
134
- cache_key = f'ci-{self.docker_file_hash()}'
102
+ return await load_docker_tar_cmd(get_cache_cmd)
103
+
104
+ async def _save_cache_docker_image(self, key: str, image: str) -> None:
105
+ if self._file_cache is None:
106
+ return
107
+
108
+ with temp_file_context() as tmp_file:
109
+ write_tmp_cmd = ShellCmd(f'zstd > {tmp_file}')
110
+
111
+ await save_docker_tar_cmd(image, write_tmp_cmd)
112
+
113
+ await self._file_cache.put_file(key, tmp_file, steal=True)
114
+
115
+ #
116
+
117
+ async def _resolve_docker_image(
118
+ self,
119
+ cache_key: str,
120
+ build_and_tag: ta.Callable[[str], ta.Awaitable[str]],
121
+ ) -> str:
135
122
  image_tag = f'{self._cfg.service}:{cache_key}'
136
123
 
137
124
  if not self._cfg.always_build and (await is_docker_image_present(image_tag)):
@@ -144,21 +131,35 @@ class Ci(AsyncExitStacked):
144
131
  )
145
132
  return image_tag
146
133
 
147
- image_id = await build_docker_image(
148
- self._cfg.docker_file,
149
- tag=image_tag,
150
- cwd=self._cfg.project_dir,
151
- )
134
+ image_id = await build_and_tag(image_tag)
152
135
 
153
136
  await self._save_cache_docker_image(cache_key, image_id)
154
137
 
155
138
  return image_tag
156
139
 
140
+ #
141
+
142
+ @cached_nullary
143
+ def docker_file_hash(self) -> str:
144
+ return build_docker_file_hash(self._cfg.docker_file)[:self.KEY_HASH_LEN]
145
+
146
+ async def _resolve_ci_base_image(self) -> str:
147
+ async def build_and_tag(image_tag: str) -> str:
148
+ return await build_docker_image(
149
+ self._cfg.docker_file,
150
+ tag=image_tag,
151
+ cwd=self._cfg.project_dir,
152
+ )
153
+
154
+ cache_key = f'ci-base-{self.docker_file_hash()}'
155
+
156
+ return await self._resolve_docker_image(cache_key, build_and_tag)
157
+
157
158
  @async_cached_nullary
158
- async def resolve_ci_image(self) -> str:
159
- with log_timing_context('Resolve ci image') as ltc:
160
- image_id = await self._resolve_ci_image()
161
- ltc.set_description(f'Resolve ci image: {image_id}')
159
+ async def resolve_ci_base_image(self) -> str:
160
+ with log_timing_context('Resolve ci base image') as ltc:
161
+ image_id = await self._resolve_ci_base_image()
162
+ ltc.set_description(f'Resolve ci base image: {image_id}')
162
163
  return image_id
163
164
 
164
165
  #
@@ -172,82 +173,85 @@ class Ci(AsyncExitStacked):
172
173
 
173
174
  @cached_nullary
174
175
  def requirements_hash(self) -> str:
175
- return build_requirements_hash(self.requirements_txts())[:self.FILE_NAME_HASH_LEN]
176
-
177
- async def _resolve_requirements_dir(self) -> str:
178
- tar_file_key = f'requirements-{self.docker_file_hash()}-{self.requirements_hash()}'
179
- tar_file_name = f'{tar_file_key}.tar'
180
-
181
- temp_dir = tempfile.mkdtemp()
182
- self._enter_context(defer(lambda: shutil.rmtree(temp_dir))) # noqa
176
+ return build_requirements_hash(self.requirements_txts())[:self.KEY_HASH_LEN]
183
177
 
184
- if self._file_cache is not None and (cache_tar_file := self._file_cache.get_file(tar_file_key)):
185
- with tarfile.open(cache_tar_file) as tar:
186
- tar.extractall(path=temp_dir) # noqa
178
+ async def _resolve_ci_image(self) -> str:
179
+ async def build_and_tag(image_tag: str) -> str:
180
+ base_image = await self.resolve_ci_base_image()
181
+
182
+ setup_cmds = [
183
+ ' '.join([
184
+ 'pip install',
185
+ '--no-cache-dir',
186
+ '--root-user-action ignore',
187
+ 'uv',
188
+ ]),
189
+ ' '.join([
190
+ 'uv pip install',
191
+ '--no-cache',
192
+ '--index-strategy unsafe-best-match',
193
+ '--system',
194
+ *[f'-r /project/{rf}' for rf in self._cfg.requirements_txts or []],
195
+ ]),
196
+ ]
197
+ setup_cmd = ' && '.join(setup_cmds)
198
+
199
+ docker_file_lines = [
200
+ f'FROM {base_image}',
201
+ 'RUN mkdir /project',
202
+ *[f'COPY {rf} /project/{rf}' for rf in self._cfg.requirements_txts or []],
203
+ f'RUN {setup_cmd}',
204
+ 'RUN rm /project/*',
205
+ 'WORKDIR /project',
206
+ ]
207
+
208
+ with temp_file_context() as docker_file:
209
+ with open(docker_file, 'w') as f: # noqa
210
+ f.write('\n'.join(docker_file_lines))
211
+
212
+ return await build_docker_image(
213
+ docker_file,
214
+ tag=image_tag,
215
+ cwd=self._cfg.project_dir,
216
+ )
217
+
218
+ cache_key = f'ci-{self.docker_file_hash()}-{self.requirements_hash()}'
219
+
220
+ return await self._resolve_docker_image(cache_key, build_and_tag)
187
221
 
188
- return temp_dir
222
+ @async_cached_nullary
223
+ async def resolve_ci_image(self) -> str:
224
+ with log_timing_context('Resolve ci image') as ltc:
225
+ image_id = await self._resolve_ci_image()
226
+ ltc.set_description(f'Resolve ci image: {image_id}')
227
+ return image_id
189
228
 
190
- temp_requirements_dir = os.path.join(temp_dir, 'requirements')
191
- os.makedirs(temp_requirements_dir)
229
+ #
192
230
 
193
- download_requirements(
194
- await self.resolve_ci_image(),
195
- temp_requirements_dir,
196
- self.requirements_txts(),
231
+ @async_cached_nullary
232
+ async def load_dependencies(self) -> None:
233
+ deps = get_compose_service_dependencies(
234
+ self._cfg.compose_file,
235
+ self._cfg.service,
197
236
  )
198
237
 
199
- if self._file_cache is not None:
200
- temp_tar_file = os.path.join(temp_dir, tar_file_name)
201
-
202
- with tarfile.open(temp_tar_file, 'w') as tar:
203
- for requirement_file in os.listdir(temp_requirements_dir):
204
- tar.add(
205
- os.path.join(temp_requirements_dir, requirement_file),
206
- arcname=requirement_file,
207
- )
208
-
209
- self._file_cache.put_file(os.path.basename(tar_file_key), temp_tar_file)
210
-
211
- return temp_requirements_dir
212
-
213
- @async_cached_nullary
214
- async def resolve_requirements_dir(self) -> str:
215
- with log_timing_context('Resolve requirements dir') as ltc:
216
- requirements_dir = await self._resolve_requirements_dir()
217
- ltc.set_description(f'Resolve requirements dir: {requirements_dir}')
218
- return requirements_dir
238
+ for dep_image in deps.values():
239
+ await self.load_docker_image(dep_image)
219
240
 
220
241
  #
221
242
 
222
243
  async def _run_compose_(self) -> None:
223
- setup_cmds = [
224
- 'pip install --root-user-action ignore --find-links /requirements --no-index uv',
225
- (
226
- 'uv pip install --system --find-links /requirements ' +
227
- ' '.join(f'-r /project/{rf}' for rf in self._cfg.requirements_txts or [])
228
- ),
229
- ]
230
-
231
- #
232
-
233
- ci_cmd = dc.replace(self._cfg.cmd, s=' && '.join([
234
- *setup_cmds,
235
- f'({self._cfg.cmd.s})',
236
- ]))
237
-
238
- #
239
-
240
244
  async with DockerComposeRun(DockerComposeRun.Config(
241
245
  compose_file=self._cfg.compose_file,
242
246
  service=self._cfg.service,
243
247
 
244
248
  image=await self.resolve_ci_image(),
245
249
 
246
- cmd=ci_cmd,
250
+ cmd=self._cfg.cmd,
247
251
 
248
252
  run_options=[
249
253
  '-v', f'{os.path.abspath(self._cfg.project_dir)}:/project',
250
- '-v', f'{os.path.abspath(await self.resolve_requirements_dir())}:/requirements',
254
+ *(self._cfg.run_options or []),
251
255
  ],
252
256
 
253
257
  cwd=self._cfg.project_dir,
@@ -263,10 +267,8 @@ class Ci(AsyncExitStacked):
263
267
  #
264
268
 
265
269
  async def run(self) -> None:
266
- await self.load_compose_service_dependencies()
267
-
268
270
  await self.resolve_ci_image()
269
271
 
270
- await self.resolve_requirements_dir()
272
+ await self.load_dependencies()
271
273
 
272
274
  await self._run_compose()
@@ -1,6 +1,5 @@
1
1
  # @omlish-amalg ../scripts/ci.py
2
2
  # ruff: noqa: UP006 UP007
3
- # @omlish-lite
4
3
  """
5
4
  Inputs:
6
5
  - requirements.txt
@@ -9,9 +8,11 @@ Inputs:
9
8
 
10
9
  ==
11
10
 
12
- ./python -m ci run --cache-dir ci/cache ci/project omlish-ci
11
+ ./python -m omdev.ci run --cache-dir omdev/ci/tests/cache omdev/ci/tests/project omlish-ci
13
12
  """
13
+ import argparse
14
14
  import asyncio
15
+ import itertools
15
16
  import os.path
16
17
  import sys
17
18
  import typing as ta
@@ -20,15 +21,15 @@ from omlish.argparse.cli import ArgparseCli
20
21
  from omlish.argparse.cli import argparse_arg
21
22
  from omlish.argparse.cli import argparse_cmd
22
23
  from omlish.lite.check import check
24
+ from omlish.lite.logs import log
23
25
  from omlish.logs.standard import configure_standard_logging
24
26
 
25
27
  from .cache import DirectoryFileCache
26
- from .cache import DirectoryShellCache
27
28
  from .cache import FileCache
28
- from .cache import ShellCache
29
29
  from .ci import Ci
30
30
  from .compose import get_compose_service_dependencies
31
- from .github.cache import GithubShellCache
31
+ from .github.bootstrap import is_in_github_actions
32
+ from .github.cache import GithubFileCache
32
33
  from .github.cli import GithubCli
33
34
  from .requirements import build_requirements_hash
34
35
  from .shell import ShellCmd
@@ -65,8 +66,8 @@ class CiCli(ArgparseCli):
65
66
  @argparse_cmd(
66
67
  accepts_unknown=True,
67
68
  )
68
- def github(self) -> ta.Optional[int]:
69
- return GithubCli(self.unknown_args).cli_run()
69
+ async def github(self) -> ta.Optional[int]:
70
+ return await GithubCli(self.unknown_args).async_cli_run()
70
71
 
71
72
  #
72
73
 
@@ -77,13 +78,20 @@ class CiCli(ArgparseCli):
77
78
  argparse_arg('--compose-file'),
78
79
  argparse_arg('-r', '--requirements-txt', action='append'),
79
80
 
80
- argparse_arg('--github-cache', action='store_true'),
81
81
  argparse_arg('--cache-dir'),
82
82
 
83
+ argparse_arg('--github', action='store_true'),
84
+ argparse_arg('--github-detect', action='store_true'),
85
+
83
86
  argparse_arg('--always-pull', action='store_true'),
84
87
  argparse_arg('--always-build', action='store_true'),
85
88
 
86
89
  argparse_arg('--no-dependencies', action='store_true'),
90
+
91
+ argparse_arg('-e', '--env', action='append'),
92
+ argparse_arg('-v', '--volume', action='append'),
93
+
94
+ argparse_arg('cmd', nargs=argparse.REMAINDER),
87
95
  )
88
96
  async def run(self) -> None:
89
97
  project_dir = self.args.project_dir
@@ -94,6 +102,11 @@ class CiCli(ArgparseCli):
94
102
 
95
103
  #
96
104
 
105
+ cmd = ' '.join(self.args.cmd)
106
+ check.non_empty_str(cmd)
107
+
108
+ #
109
+
97
110
  check.state(os.path.isdir(project_dir))
98
111
 
99
112
  #
@@ -102,6 +115,7 @@ class CiCli(ArgparseCli):
102
115
  for alt in alts:
103
116
  alt_file = os.path.abspath(os.path.join(project_dir, alt))
104
117
  if os.path.isfile(alt_file):
118
+ log.debug('Using %s', alt_file)
105
119
  return alt_file
106
120
  return None
107
121
 
@@ -135,6 +149,7 @@ class CiCli(ArgparseCli):
135
149
  'requirements-ci.txt',
136
150
  ]:
137
151
  if os.path.exists(os.path.join(project_dir, rf)):
152
+ log.debug('Using %s', rf)
138
153
  requirements_txts.append(rf)
139
154
  else:
140
155
  for rf in requirements_txts:
@@ -142,21 +157,34 @@ class CiCli(ArgparseCli):
142
157
 
143
158
  #
144
159
 
145
- shell_cache: ta.Optional[ShellCache] = None
160
+ github = self.args.github
161
+ if not github and self.args.github_detect:
162
+ github = is_in_github_actions()
163
+ if github:
164
+ log.debug('Github detected')
165
+
166
+ #
167
+
146
168
  file_cache: ta.Optional[FileCache] = None
147
169
  if cache_dir is not None:
148
- if not os.path.exists(cache_dir):
149
- os.makedirs(cache_dir)
150
- check.state(os.path.isdir(cache_dir))
151
-
152
- directory_file_cache = DirectoryFileCache(cache_dir)
170
+ cache_dir = os.path.abspath(cache_dir)
171
+ log.debug('Using cache dir %s', cache_dir)
172
+ if github:
173
+ file_cache = GithubFileCache(cache_dir)
174
+ else:
175
+ file_cache = DirectoryFileCache(cache_dir)
153
176
 
154
- file_cache = directory_file_cache
177
+ #
155
178
 
156
- if self.args.github_cache:
157
- shell_cache = GithubShellCache(cache_dir)
158
- else:
159
- shell_cache = DirectoryShellCache(directory_file_cache)
179
+ run_options: ta.List[str] = []
180
+ for run_arg, run_arg_vals in [
181
+ ('-e', self.args.env or []),
182
+ ('-v', self.args.volume or []),
183
+ ]:
184
+ run_options.extend(itertools.chain.from_iterable(
185
+ [run_arg, run_arg_val]
186
+ for run_arg_val in run_arg_vals
187
+ ))
160
188
 
161
189
  #
162
190
 
@@ -171,18 +199,16 @@ class CiCli(ArgparseCli):
171
199
 
172
200
  requirements_txts=requirements_txts,
173
201
 
174
- cmd=ShellCmd(' && '.join([
175
- 'cd /project',
176
- 'python3 -m pytest -svv test.py',
177
- ])),
202
+ cmd=ShellCmd(cmd),
178
203
 
179
204
  always_pull=self.args.always_pull,
180
205
  always_build=self.args.always_build,
181
206
 
182
207
  no_dependencies=self.args.no_dependencies,
208
+
209
+ run_options=run_options,
183
210
  ),
184
211
  file_cache=file_cache,
185
- shell_cache=shell_cache,
186
212
  ) as ci:
187
213
  await ci.run()
188
214