omdev 0.0.0.dev290__tar.gz → 0.0.0.dev292__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (280) hide show
  1. {omdev-0.0.0.dev290/omdev.egg-info → omdev-0.0.0.dev292}/PKG-INFO +2 -2
  2. omdev-0.0.0.dev292/README.md +31 -0
  3. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/.manifests.json +1 -1
  4. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/compose.py +1 -1
  5. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/clients.py +25 -5
  6. omdev-0.0.0.dev292/omdev/ci/github/api/v2/azure.py +185 -0
  7. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/v2/client.py +37 -2
  8. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/clicli.py +6 -1
  9. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/pkg.py +5 -2
  10. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/scripts/ci.py +243 -11
  11. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/scripts/pyproject.py +5 -2
  12. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292/omdev.egg-info}/PKG-INFO +2 -2
  13. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev.egg-info/SOURCES.txt +2 -1
  14. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev.egg-info/requires.txt +1 -1
  15. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/pyproject.toml +2 -2
  16. omdev-0.0.0.dev290/README.rst +0 -38
  17. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/LICENSE +0 -0
  18. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/MANIFEST.in +0 -0
  19. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/__about__.py +0 -0
  20. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/__init__.py +0 -0
  21. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/__init__.py +0 -0
  22. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/__main__.py +0 -0
  23. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/gen.py +0 -0
  24. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/imports.py +0 -0
  25. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/main.py +0 -0
  26. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/manifests.py +0 -0
  27. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/resources.py +0 -0
  28. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/srcfiles.py +0 -0
  29. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/strip.py +0 -0
  30. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/types.py +0 -0
  31. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/amalg/typing.py +0 -0
  32. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/antlr/__init__.py +0 -0
  33. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/antlr/consts.py +0 -0
  34. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/antlr/gen.py +0 -0
  35. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/__init__.py +0 -0
  36. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/__init__.py +0 -0
  37. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/cache.py +0 -0
  38. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/contexts.py +0 -0
  39. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/currents.py +0 -0
  40. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/fns.py +0 -0
  41. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/resolvers.py +0 -0
  42. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/storage.py +0 -0
  43. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/compute/types.py +0 -0
  44. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/data/__init__.py +0 -0
  45. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/data/actions.py +0 -0
  46. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/data/cache.py +0 -0
  47. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/data/consts.py +0 -0
  48. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/data/defaults.py +0 -0
  49. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/data/manifests.py +0 -0
  50. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cache/data/specs.py +0 -0
  51. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cc/__init__.py +0 -0
  52. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cc/__main__.py +0 -0
  53. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cc/cdeps.py +0 -0
  54. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cc/cdeps.toml +0 -0
  55. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cc/cli.py +0 -0
  56. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/__init__.py +0 -0
  57. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_boilerplate.cc +0 -0
  58. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/LICENSE +0 -0
  59. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/__init__.py +0 -0
  60. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/build_ext.py +0 -0
  61. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/compilers/__init__.py +0 -0
  62. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/compilers/ccompiler.py +0 -0
  63. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/compilers/options.py +0 -0
  64. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/compilers/unixccompiler.py +0 -0
  65. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/dir_util.py +0 -0
  66. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/errors.py +0 -0
  67. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/extension.py +0 -0
  68. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/file_util.py +0 -0
  69. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/modified.py +0 -0
  70. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/spawn.py +0 -0
  71. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/sysconfig.py +0 -0
  72. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/util.py +0 -0
  73. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/_distutils/version.py +0 -0
  74. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/build.py +0 -0
  75. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/cmake.py +0 -0
  76. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/importhook.py +0 -0
  77. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/magic.py +0 -0
  78. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cexts/scan.py +0 -0
  79. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/__init__.py +0 -0
  80. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/__main__.py +0 -0
  81. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/cache.py +0 -0
  82. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/ci.py +0 -0
  83. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/cli.py +0 -0
  84. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/consts.py +0 -0
  85. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/__init__.py +0 -0
  86. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/buildcaching.py +0 -0
  87. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/cache.py +0 -0
  88. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/cacheserved/__init__.py +0 -0
  89. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/cacheserved/cache.py +0 -0
  90. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/cacheserved/manifests.py +0 -0
  91. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/cmds.py +0 -0
  92. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/dataserver.py +0 -0
  93. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/imagepulling.py +0 -0
  94. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/inject.py +0 -0
  95. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/packing.py +0 -0
  96. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/repositories.py +0 -0
  97. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/docker/utils.py +0 -0
  98. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/__init__.py +0 -0
  99. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/__init__.py +0 -0
  100. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/v1/__init__.py +0 -0
  101. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/v1/api.py +0 -0
  102. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/v1/client.py +0 -0
  103. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/v2/__init__.py +0 -0
  104. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/api/v2/api.py +0 -0
  105. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/bootstrap.py +0 -0
  106. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/cache.py +0 -0
  107. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/cli.py +0 -0
  108. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/env.py +0 -0
  109. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/github/inject.py +0 -0
  110. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/inject.py +0 -0
  111. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/requirements.py +0 -0
  112. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/shell.py +0 -0
  113. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ci/utils.py +0 -0
  114. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/__init__.py +0 -0
  115. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/__main__.py +0 -0
  116. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/_pathhack.py +0 -0
  117. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/install.py +0 -0
  118. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/main.py +0 -0
  119. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/managers.py +0 -0
  120. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cli/types.py +0 -0
  121. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/clipboard/__init__.py +0 -0
  122. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/clipboard/clipboard.py +0 -0
  123. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/clipboard/darwin_cf.py +0 -0
  124. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/clipboard/linux_x11.py +0 -0
  125. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/cmake.py +0 -0
  126. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/dataserver/__init__.py +0 -0
  127. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/dataserver/handlers.py +0 -0
  128. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/dataserver/http.py +0 -0
  129. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/dataserver/routes.py +0 -0
  130. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/dataserver/server.py +0 -0
  131. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/dataserver/targets.py +0 -0
  132. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/git/__init__.py +0 -0
  133. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/git/magic.py +0 -0
  134. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/git/revisions.py +0 -0
  135. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/git/shallow.py +0 -0
  136. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/git/status.py +0 -0
  137. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/home/__init__.py +0 -0
  138. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/home/paths.py +0 -0
  139. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/home/secrets.py +0 -0
  140. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/home/shadow.py +0 -0
  141. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/imgur.py +0 -0
  142. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/__init__.py +0 -0
  143. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/__main__.py +0 -0
  144. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/cli.py +0 -0
  145. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/default.py +0 -0
  146. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/inject.py +0 -0
  147. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/inspect.py +0 -0
  148. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/providers/__init__.py +0 -0
  149. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/providers/base.py +0 -0
  150. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/providers/inject.py +0 -0
  151. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/providers/running.py +0 -0
  152. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/providers/standalone.py +0 -0
  153. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/providers/system.py +0 -0
  154. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/pyenv/__init__.py +0 -0
  155. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/pyenv/inject.py +0 -0
  156. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/pyenv/install.py +0 -0
  157. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/pyenv/provider.py +0 -0
  158. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/pyenv/pyenv.py +0 -0
  159. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/resolvers.py +0 -0
  160. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/types.py +0 -0
  161. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/uv/__init__.py +0 -0
  162. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/uv/inject.py +0 -0
  163. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/uv/provider.py +0 -0
  164. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/uv/uv.py +0 -0
  165. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/interp/venvs.py +0 -0
  166. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/magic/__init__.py +0 -0
  167. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/magic/__main__.py +0 -0
  168. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/magic/cli.py +0 -0
  169. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/magic/find.py +0 -0
  170. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/magic/magic.py +0 -0
  171. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/magic/prepare.py +0 -0
  172. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/magic/styles.py +0 -0
  173. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/manifests/__init__.py +0 -0
  174. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/manifests/__main__.py +0 -0
  175. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/manifests/build.py +0 -0
  176. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/manifests/dumping.py +0 -0
  177. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/manifests/main.py +0 -0
  178. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/mypy/__init__.py +0 -0
  179. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/mypy/debug.py +0 -0
  180. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/__init__.py +0 -0
  181. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/building.py +0 -0
  182. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/compression.py +0 -0
  183. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/data.py +0 -0
  184. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/datarefs.py +0 -0
  185. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/dataserver.py +0 -0
  186. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/loading.py +0 -0
  187. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/media.py +0 -0
  188. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/pack/__init__.py +0 -0
  189. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/pack/packing.py +0 -0
  190. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/pack/repositories.py +0 -0
  191. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/pack/unpacking.py +0 -0
  192. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/repositories.py +0 -0
  193. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/oci/tars.py +0 -0
  194. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/__init__.py +0 -0
  195. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/marshal.py +0 -0
  196. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/names.py +0 -0
  197. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/requires.py +0 -0
  198. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/revisions.py +0 -0
  199. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/specifiers.py +0 -0
  200. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/versions.py +0 -0
  201. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/packaging/wheelfile.py +0 -0
  202. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pip.py +0 -0
  203. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/__init__.py +0 -0
  204. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/__main__.py +0 -0
  205. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/base.py +0 -0
  206. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/git.py +0 -0
  207. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/lite.py +0 -0
  208. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/main.py +0 -0
  209. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/manifests.py +0 -0
  210. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/precheck/scripts.py +0 -0
  211. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ptk/__init__.py +0 -0
  212. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ptk/apps/__init__.py +0 -0
  213. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/ptk/apps/ncdu.py +0 -0
  214. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/__init__.py +0 -0
  215. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/attrdocs.py +0 -0
  216. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/bracepy.py +0 -0
  217. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/classdot.py +0 -0
  218. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/findimports.py +0 -0
  219. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/scripts/__init__.py +0 -0
  220. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/scripts/bumpversion.py +0 -0
  221. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/scripts/execstat.py +0 -0
  222. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/scripts/importtrace.py +0 -0
  223. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/srcheaders.py +0 -0
  224. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/tools/__init__.py +0 -0
  225. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/tools/importscan.py +0 -0
  226. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/py/tools/mkrelimp.py +0 -0
  227. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/__init__.py +0 -0
  228. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/__main__.py +0 -0
  229. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/cexts.py +0 -0
  230. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/cli.py +0 -0
  231. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/configs.py +0 -0
  232. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/inject.py +0 -0
  233. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/reqs.py +0 -0
  234. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/resources/__init__.py +0 -0
  235. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/resources/docker-dev.sh +0 -0
  236. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/resources/python.sh +0 -0
  237. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/pyproject/venvs.py +0 -0
  238. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/scripts/__init__.py +0 -0
  239. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/scripts/interp.py +0 -0
  240. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/scripts/slowcat.py +0 -0
  241. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/scripts/tmpexec.py +0 -0
  242. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tagstrings.py +0 -0
  243. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tokens/__init__.py +0 -0
  244. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tokens/all.py +0 -0
  245. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tokens/tokenizert.py +0 -0
  246. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tokens/utils.py +0 -0
  247. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/__init__.py +0 -0
  248. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/cloc.py +0 -0
  249. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/diff.py +0 -0
  250. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/doc.py +0 -0
  251. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/docker.py +0 -0
  252. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/git/__init__.py +0 -0
  253. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/git/__main__.py +0 -0
  254. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/git/cli.py +0 -0
  255. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/git/consts.py +0 -0
  256. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/git/messages.py +0 -0
  257. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/intellij.py +0 -0
  258. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/__init__.py +0 -0
  259. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/__main__.py +0 -0
  260. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/cli.py +0 -0
  261. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/formats.py +0 -0
  262. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/io.py +0 -0
  263. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/parsing.py +0 -0
  264. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/processing.py +0 -0
  265. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/json/rendering.py +0 -0
  266. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/linehisto.py +0 -0
  267. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/mkenv.py +0 -0
  268. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/notebook.py +0 -0
  269. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/pawk/__init__.py +0 -0
  270. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/pawk/__main__.py +0 -0
  271. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/pawk/pawk.py +0 -0
  272. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/pip.py +0 -0
  273. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/prof.py +0 -0
  274. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/qr.py +0 -0
  275. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/shadow.py +0 -0
  276. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev/tools/sqlrepl.py +0 -0
  277. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev.egg-info/dependency_links.txt +0 -0
  278. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev.egg-info/entry_points.txt +0 -0
  279. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/omdev.egg-info/top_level.txt +0 -0
  280. {omdev-0.0.0.dev290 → omdev-0.0.0.dev292}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omdev
3
- Version: 0.0.0.dev290
3
+ Version: 0.0.0.dev292
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.dev290
15
+ Requires-Dist: omlish==0.0.0.dev292
16
16
  Provides-Extra: all
17
17
  Requires-Dist: black~=25.1; extra == "all"
18
18
  Requires-Dist: pycparser~=2.22; extra == "all"
@@ -0,0 +1,31 @@
1
+ It's like my previous python monorepo-ey thing [`omnibus`](https://github.com/wrmsr/omnibus/tree/wrmsr_exp_split)... ish.
2
+
3
+ Core packages begin with `om`, scratch app is in `app`, temp / dump code is in `x`.
4
+
5
+ ----
6
+
7
+ The core packages are:
8
+
9
+ - **omlish**: core foundational code
10
+ - **omdev**: development utilities
11
+ - **omserv**: production web server
12
+ - **ominfra**: infrastructure and cloud code
13
+ - **ommlx**: ml / ai code
14
+
15
+ ----
16
+
17
+ Core packages installable from pypi, or from git via:
18
+
19
+ ```bash
20
+ pip install 'git+https://github.com/wrmsr/omlish@master#subdirectory=.pkg/<pkg>'
21
+ ```
22
+
23
+ Core packages have no required dependencies, but numerous optional ones - see their respective `pyproject.toml` files for details.
24
+
25
+ The CLI is installable through uvx or pipx via:
26
+
27
+ ```bash
28
+ curl -LsSf 'https://raw.githubusercontent.com/wrmsr/omlish/master/omdev/cli/install.py' | python3 -
29
+ ```
30
+
31
+ Additional deps to be injected may be appended to the command.
@@ -39,7 +39,7 @@
39
39
  "module": ".cli.clicli",
40
40
  "attr": "_CLI_MODULE",
41
41
  "file": "omdev/cli/clicli.py",
42
- "line": 168,
42
+ "line": 173,
43
43
  "value": {
44
44
  "$.cli.types.CliModule": {
45
45
  "cmd_name": "cli",
@@ -155,7 +155,7 @@ class DockerComposeRun(AsyncExitStacked):
155
155
 
156
156
  async with contextlib.AsyncExitStack() as es:
157
157
  if not (self._cfg.no_dependencies or self._cfg.no_dependency_cleanup):
158
- await es.enter_async_context(adefer(self._cleanup_dependencies)) # noqa
158
+ await es.enter_async_context(adefer(self._cleanup_dependencies())) # noqa
159
159
 
160
160
  sh_cmd = ' '.join([
161
161
  'docker',
@@ -430,7 +430,7 @@ class BaseGithubCacheClient(GithubCacheClient, abc.ABC):
430
430
  ):
431
431
  await self._upload_file_chunk_(chunk)
432
432
 
433
- async def _upload_file_chunks(
433
+ def _generate_file_upload_chunks(
434
434
  self,
435
435
  *,
436
436
  in_file: str,
@@ -438,7 +438,7 @@ class BaseGithubCacheClient(GithubCacheClient, abc.ABC):
438
438
  key: str,
439
439
 
440
440
  file_size: ta.Optional[int] = None,
441
- ) -> None:
441
+ ) -> ta.List[_UploadChunk]:
442
442
  check.state(os.path.isfile(in_file))
443
443
 
444
444
  if file_size is None:
@@ -446,17 +446,37 @@ class BaseGithubCacheClient(GithubCacheClient, abc.ABC):
446
446
 
447
447
  #
448
448
 
449
- upload_tasks = []
449
+ upload_chunks: ta.List[BaseGithubCacheClient._UploadChunk] = []
450
450
  chunk_size = self._chunk_size
451
451
  for i in range((file_size // chunk_size) + (1 if file_size % chunk_size else 0)):
452
452
  offset = i * chunk_size
453
453
  size = min(chunk_size, file_size - offset)
454
- upload_tasks.append(self._upload_file_chunk(self._UploadChunk(
454
+ upload_chunks.append(self._UploadChunk(
455
455
  url=url,
456
456
  key=key,
457
457
  in_file=in_file,
458
458
  offset=offset,
459
459
  size=size,
460
- )))
460
+ ))
461
+
462
+ return upload_chunks
463
+
464
+ async def _upload_file_chunks(
465
+ self,
466
+ *,
467
+ in_file: str,
468
+ url: str,
469
+ key: str,
470
+
471
+ file_size: ta.Optional[int] = None,
472
+ ) -> None:
473
+ upload_tasks = []
474
+ for chunk in self._generate_file_upload_chunks(
475
+ in_file=in_file,
476
+ url=url,
477
+ key=key,
478
+ file_size=file_size,
479
+ ):
480
+ upload_tasks.append(self._upload_file_chunk(chunk))
461
481
 
462
482
  await asyncio_wait_concurrent(upload_tasks, self._concurrency)
@@ -0,0 +1,185 @@
1
+ # ruff: noqa: UP006 UP007
2
+ # @omlish-lite
3
+ """
4
+ TODO:
5
+ - ominfra? no, circdep
6
+ """
7
+ import base64
8
+ import dataclasses as dc
9
+ import datetime
10
+ import typing as ta
11
+ import urllib.parse
12
+ import xml.etree.ElementTree as ET
13
+
14
+ from omlish.asyncs.asyncio.utils import asyncio_wait_concurrent
15
+ from omlish.lite.check import check
16
+ from omlish.lite.logs import log
17
+ from omlish.lite.timing import log_timing_context
18
+
19
+
20
+ ##
21
+
22
+
23
+ class AzureBlockBlobUploader:
24
+ """
25
+ https://learn.microsoft.com/en-us/rest/api/storageservices/put-block
26
+ https://learn.microsoft.com/en-us/rest/api/storageservices/put-block-list
27
+ """
28
+
29
+ DEFAULT_CONCURRENCY = 4
30
+
31
+ @dc.dataclass(frozen=True)
32
+ class Request:
33
+ method: str
34
+ url: str
35
+ headers: ta.Optional[ta.Dict[str, str]] = None
36
+ body: ta.Optional[bytes] = None
37
+
38
+ @dc.dataclass(frozen=True)
39
+ class Response:
40
+ status: int
41
+ headers: ta.Optional[ta.Mapping[str, str]] = None
42
+ data: ta.Optional[bytes] = None
43
+
44
+ def get_header(self, name: str) -> ta.Optional[str]:
45
+ for k, v in (self.headers or {}).items():
46
+ if k.lower() == name.lower():
47
+ return v
48
+ return None
49
+
50
+ def __init__(
51
+ self,
52
+ blob_url_with_sas: str,
53
+ make_request: ta.Callable[[Request], ta.Awaitable[Response]],
54
+ *,
55
+ api_version: str = '2020-10-02',
56
+ concurrency: int = DEFAULT_CONCURRENCY,
57
+ ) -> None:
58
+ """
59
+ blob_url_with_sas should be of the form:
60
+ https://<account>.blob.core.windows.net/<container>/<blob>?<SAS-token>
61
+ """
62
+
63
+ super().__init__()
64
+
65
+ self._make_request = make_request
66
+ self._api_version = api_version
67
+ check.arg(concurrency >= 1)
68
+ self._concurrency = concurrency
69
+
70
+ parsed = urllib.parse.urlparse(blob_url_with_sas)
71
+ self._base_url = f'{parsed.scheme}://{parsed.netloc}'
72
+ parts = parsed.path.lstrip('/').split('/', 1)
73
+ self._container = parts[0]
74
+ self._blob_name = parts[1]
75
+ self._sas = parsed.query
76
+
77
+ def _headers(self) -> ta.Dict[str, str]:
78
+ """Standard headers for Azure Blob REST calls."""
79
+
80
+ now = datetime.datetime.now(datetime.UTC).strftime('%a, %d %b %Y %H:%M:%S GMT')
81
+ return {
82
+ 'x-ms-date': now,
83
+ 'x-ms-version': self._api_version,
84
+ }
85
+
86
+ @dc.dataclass(frozen=True)
87
+ class FileChunk:
88
+ in_file: str
89
+ offset: int
90
+ size: int
91
+
92
+ async def _upload_file_chunk_(
93
+ self,
94
+ block_id: str,
95
+ chunk: FileChunk,
96
+ ) -> None:
97
+ with open(chunk.in_file, 'rb') as f: # noqa
98
+ f.seek(chunk.offset)
99
+ data = f.read(chunk.size)
100
+
101
+ check.equal(len(data), chunk.size)
102
+
103
+ params = {
104
+ 'comp': 'block',
105
+ 'blockid': block_id,
106
+ }
107
+ query = self._sas + '&' + urllib.parse.urlencode(params)
108
+ url = f'{self._base_url}/{self._container}/{self._blob_name}?{query}'
109
+
110
+ log.debug(f'Uploading azure blob chunk {chunk} with block id {block_id}') # noqa
111
+
112
+ resp = await self._make_request(self.Request(
113
+ 'PUT',
114
+ url,
115
+ headers=self._headers(),
116
+ body=data,
117
+ ))
118
+ if resp.status not in (201, 202):
119
+ raise RuntimeError(f'Put Block failed: {block_id=} {resp.status=}')
120
+
121
+ async def _upload_file_chunk(
122
+ self,
123
+ block_id: str,
124
+ chunk: FileChunk,
125
+ ) -> None:
126
+ with log_timing_context(f'Uploading azure blob chunk {chunk} with block id {block_id}'):
127
+ await self._upload_file_chunk_(
128
+ block_id,
129
+ chunk,
130
+ )
131
+
132
+ async def upload_file(
133
+ self,
134
+ chunks: ta.List[FileChunk],
135
+ ) -> ta.Dict[str, ta.Any]:
136
+ block_ids = []
137
+
138
+ # 1) Stage each block
139
+ upload_tasks = []
140
+ for idx, chunk in enumerate(chunks):
141
+ # Generate a predictable block ID (must be URL-safe base64)
142
+ raw_id = f'{idx:08d}'.encode()
143
+ block_id = base64.b64encode(raw_id).decode('utf-8')
144
+ block_ids.append(block_id)
145
+
146
+ upload_tasks.append(self._upload_file_chunk(
147
+ block_id,
148
+ chunk,
149
+ ))
150
+
151
+ await asyncio_wait_concurrent(upload_tasks, self._concurrency)
152
+
153
+ # 2) Commit block list
154
+ root = ET.Element('BlockList')
155
+ for bid in block_ids:
156
+ elm = ET.SubElement(root, 'Latest')
157
+ elm.text = bid
158
+ body = ET.tostring(root, encoding='utf-8', method='xml')
159
+
160
+ params = {'comp': 'blocklist'}
161
+ query = self._sas + '&' + urllib.parse.urlencode(params)
162
+ url = f'{self._base_url}/{self._container}/{self._blob_name}?{query}'
163
+
164
+ log.debug(f'Putting azure blob chunk list block ids {block_ids}') # noqa
165
+
166
+ resp = await self._make_request(self.Request(
167
+ 'PUT',
168
+ url,
169
+ headers={
170
+ **self._headers(),
171
+ 'Content-Type': 'application/xml',
172
+ },
173
+ body=body,
174
+ ))
175
+ if resp.status not in (200, 201):
176
+ raise RuntimeError(f'Put Block List failed: {resp.status} {resp.data!r}')
177
+
178
+ ret = {
179
+ 'status_code': resp.status,
180
+ 'etag': resp.get_header('ETag'),
181
+ }
182
+
183
+ log.debug(f'Uploaded azure blob chunk {ret}') # noqa
184
+
185
+ return ret
@@ -2,6 +2,7 @@
2
2
  import dataclasses as dc
3
3
  import os
4
4
  import typing as ta
5
+ import urllib.request
5
6
 
6
7
  from omlish.lite.check import check
7
8
  from omlish.lite.logs import log
@@ -13,6 +14,7 @@ from ..clients import GithubCacheClient
13
14
  from .api import GithubCacheServiceV2
14
15
  from .api import GithubCacheServiceV2RequestT
15
16
  from .api import GithubCacheServiceV2ResponseT
17
+ from .azure import AzureBlockBlobUploader
16
18
 
17
19
 
18
20
  ##
@@ -137,19 +139,52 @@ class GithubCacheServiceV2Client(BaseGithubCacheClient):
137
139
 
138
140
  #
139
141
 
140
- await self._upload_file_chunks(
142
+ upload_chunks = self._generate_file_upload_chunks(
141
143
  in_file=in_file,
142
144
  url=reserve_resp.signed_upload_url,
143
145
  key=fixed_key,
144
146
  file_size=file_size,
145
147
  )
146
148
 
149
+ az_chunks = [
150
+ AzureBlockBlobUploader.FileChunk(
151
+ in_file=in_file,
152
+ offset=c.offset,
153
+ size=c.size,
154
+ )
155
+ for c in upload_chunks
156
+ ]
157
+
158
+ async def az_make_request(req: AzureBlockBlobUploader.Request) -> AzureBlockBlobUploader.Response:
159
+ u_req = urllib.request.Request( # noqa
160
+ req.url,
161
+ method=req.method,
162
+ headers=req.headers or {},
163
+ data=req.body,
164
+ )
165
+
166
+ u_resp, u_body = await self._send_urllib_request(u_req)
167
+
168
+ return AzureBlockBlobUploader.Response(
169
+ status=u_resp.status,
170
+ headers=dict(u_resp.headers),
171
+ data=u_body,
172
+ )
173
+
174
+ az_uploader = AzureBlockBlobUploader(
175
+ reserve_resp.signed_upload_url,
176
+ az_make_request,
177
+ concurrency=self._concurrency,
178
+ )
179
+
180
+ await az_uploader.upload_file(az_chunks)
181
+
147
182
  #
148
183
 
149
184
  commit_resp = check.not_none(await self._send_method_request(
150
185
  GithubCacheServiceV2.FINALIZE_CACHE_ENTRY_METHOD, # type: ignore[arg-type]
151
186
  GithubCacheServiceV2.FinalizeCacheEntryUploadRequest(
152
- key=key,
187
+ key=fixed_key,
153
188
  size_bytes=file_size,
154
189
  version=version,
155
190
  ),
@@ -1,5 +1,6 @@
1
1
  import inspect
2
2
  import os
3
+ import shlex
3
4
  import subprocess
4
5
  import sys
5
6
  import typing as ta
@@ -76,6 +77,7 @@ class CliCli(ap.Cli):
76
77
  ap.arg('--url', default=DEFAULT_REINSTALL_URL),
77
78
  ap.arg('--local', action='store_true'),
78
79
  ap.arg('--no-deps', action='store_true'),
80
+ ap.arg('--dry-run', action='store_true'),
79
81
  ap.arg('extra_deps', nargs='*'),
80
82
  )
81
83
  def reinstall(self) -> None:
@@ -147,7 +149,7 @@ class CliCli(ap.Cli):
147
149
 
148
150
  reco_cmd = ' '.join([
149
151
  'curl -LsSf',
150
- url,
152
+ f"'{url}'" if (qu := shlex.quote(url)) == url else qu,
151
153
  '| python3 -',
152
154
  *deps,
153
155
  ])
@@ -156,6 +158,9 @@ class CliCli(ap.Cli):
156
158
  with urllib.request.urlopen(urllib.request.Request(url)) as resp: # noqa
157
159
  install_src = resp.read().decode('utf-8')
158
160
 
161
+ if self.args.dry_run:
162
+ return
163
+
159
164
  os.execl(
160
165
  sys.executable,
161
166
  sys.executable,
@@ -175,8 +175,11 @@ class BasePyprojectPackageGenerator(abc.ABC):
175
175
  #
176
176
 
177
177
  _STANDARD_FILES: ta.Sequence[str] = [
178
- 'LICENSE',
179
- 'README.rst',
178
+ *[
179
+ ''.join([n, x])
180
+ for n in ('LICENSE', 'README')
181
+ for x in ('', '.txt', '.md', '.rst')
182
+ ],
180
183
  ]
181
184
 
182
185
  def _symlink_standard_files(self) -> None: