nextmv 1.7.4.dev4__tar.gz → 1.8.0.dev0__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 (415) hide show
  1. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/PKG-INFO +1 -1
  2. nextmv-1.8.0.dev0/nextmv/__about__.py +1 -0
  3. nextmv-1.8.0.dev0/nextmv/cache.py +420 -0
  4. nextmv-1.8.0.dev0/nextmv/cli/cache/__init__.py +21 -0
  5. nextmv-1.8.0.dev0/nextmv/cli/cache/delete.py +48 -0
  6. nextmv-1.8.0.dev0/nextmv/cli/cache/get.py +27 -0
  7. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/push.py +13 -0
  8. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/main.py +2 -0
  9. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/__init__.py +20 -4
  10. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/client.py +29 -4
  11. nextmv-1.8.0.dev0/nextmv/cloud/package.py +1246 -0
  12. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/executor.py +7 -12
  13. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/manifest.py +14 -7
  14. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/polling.py +8 -5
  15. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/test_configuration.py +0 -5
  16. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cloud/test_client.py +91 -0
  17. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cloud/test_package.py +7 -7
  18. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/local/test_application.py +3 -3
  19. nextmv-1.8.0.dev0/tests/test_cache.py +411 -0
  20. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_manifest.py +3 -3
  21. nextmv-1.7.4.dev4/nextmv/__about__.py +0 -1
  22. nextmv-1.7.4.dev4/nextmv/cloud/package.py +0 -349
  23. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/.gitignore +0 -0
  24. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/.python-version +0 -0
  25. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/CONTRIBUTING.md +0 -0
  26. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/LICENSE +0 -0
  27. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/README.md +0 -0
  28. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/__entrypoint__.py +0 -0
  29. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/__init__.py +0 -0
  30. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/_serialization.py +0 -0
  31. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/account.py +0 -0
  32. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/base_model.py +0 -0
  33. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/__init__.py +0 -0
  34. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/__init__.py +0 -0
  35. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/acceptance/__init__.py +0 -0
  36. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/acceptance/create.py +0 -0
  37. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/acceptance/delete.py +0 -0
  38. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/acceptance/get.py +0 -0
  39. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/acceptance/list.py +0 -0
  40. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/acceptance/update.py +0 -0
  41. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/account/__init__.py +0 -0
  42. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/account/create.py +0 -0
  43. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/account/delete.py +0 -0
  44. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/account/get.py +0 -0
  45. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/account/update.py +0 -0
  46. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/__init__.py +0 -0
  47. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/create.py +0 -0
  48. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/delete.py +0 -0
  49. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/exists.py +0 -0
  50. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/get.py +0 -0
  51. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/list.py +0 -0
  52. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/app/update.py +0 -0
  53. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/batch/__init__.py +0 -0
  54. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/batch/create.py +0 -0
  55. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/batch/delete.py +0 -0
  56. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/batch/get.py +0 -0
  57. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/batch/list.py +0 -0
  58. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/batch/metadata.py +0 -0
  59. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/batch/update.py +0 -0
  60. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/data/__init__.py +0 -0
  61. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/data/upload.py +0 -0
  62. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/ensemble/__init__.py +0 -0
  63. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/ensemble/create.py +0 -0
  64. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/ensemble/delete.py +0 -0
  65. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/ensemble/get.py +0 -0
  66. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/ensemble/list.py +0 -0
  67. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/ensemble/update.py +0 -0
  68. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/input_set/__init__.py +0 -0
  69. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/input_set/create.py +0 -0
  70. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/input_set/delete.py +0 -0
  71. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/input_set/get.py +0 -0
  72. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/input_set/list.py +0 -0
  73. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/input_set/update.py +0 -0
  74. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/instance/__init__.py +0 -0
  75. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/instance/create.py +0 -0
  76. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/instance/delete.py +0 -0
  77. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/instance/exists.py +0 -0
  78. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/instance/get.py +0 -0
  79. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/instance/list.py +0 -0
  80. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/instance/update.py +0 -0
  81. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/managed_input/__init__.py +0 -0
  82. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/managed_input/create.py +0 -0
  83. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/managed_input/delete.py +0 -0
  84. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/managed_input/get.py +0 -0
  85. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/managed_input/list.py +0 -0
  86. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/managed_input/update.py +0 -0
  87. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/__init__.py +0 -0
  88. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/app/__init__.py +0 -0
  89. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/app/create.py +0 -0
  90. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/app/get.py +0 -0
  91. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/app/list.py +0 -0
  92. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/app/update.py +0 -0
  93. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/subscription/__init__.py +0 -0
  94. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/subscription/create.py +0 -0
  95. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/subscription/delete.py +0 -0
  96. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/subscription/get.py +0 -0
  97. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/subscription/list.py +0 -0
  98. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/version/__init__.py +0 -0
  99. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/version/create.py +0 -0
  100. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/version/get.py +0 -0
  101. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/version/list.py +0 -0
  102. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/marketplace/version/update.py +0 -0
  103. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/__init__.py +0 -0
  104. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/cancel.py +0 -0
  105. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/create.py +0 -0
  106. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/delete.py +0 -0
  107. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/get.py +0 -0
  108. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/input.py +0 -0
  109. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/list.py +0 -0
  110. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/logs.py +0 -0
  111. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/metadata.py +0 -0
  112. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/run/track.py +0 -0
  113. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/scenario/__init__.py +0 -0
  114. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/scenario/create.py +0 -0
  115. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/scenario/delete.py +0 -0
  116. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/scenario/get.py +0 -0
  117. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/scenario/list.py +0 -0
  118. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/scenario/metadata.py +0 -0
  119. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/scenario/update.py +0 -0
  120. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/secrets/__init__.py +0 -0
  121. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/secrets/create.py +0 -0
  122. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/secrets/delete.py +0 -0
  123. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/secrets/get.py +0 -0
  124. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/secrets/list.py +0 -0
  125. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/secrets/update.py +0 -0
  126. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/__init__.py +0 -0
  127. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/create.py +0 -0
  128. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/delete.py +0 -0
  129. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/get.py +0 -0
  130. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/list.py +0 -0
  131. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/metadata.py +0 -0
  132. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/start.py +0 -0
  133. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/stop.py +0 -0
  134. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/shadow/update.py +0 -0
  135. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/__init__.py +0 -0
  136. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/create.py +0 -0
  137. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/delete.py +0 -0
  138. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/disable.py +0 -0
  139. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/domain/__init__.py +0 -0
  140. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/domain/delete.py +0 -0
  141. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/enable.py +0 -0
  142. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/get.py +0 -0
  143. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/sso/update.py +0 -0
  144. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/__init__.py +0 -0
  145. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/create.py +0 -0
  146. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/delete.py +0 -0
  147. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/get.py +0 -0
  148. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/list.py +0 -0
  149. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/metadata.py +0 -0
  150. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/start.py +0 -0
  151. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/stop.py +0 -0
  152. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/switchback/update.py +0 -0
  153. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/upload/__init__.py +0 -0
  154. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/upload/create.py +0 -0
  155. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/version/__init__.py +0 -0
  156. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/version/create.py +0 -0
  157. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/version/delete.py +0 -0
  158. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/version/exists.py +0 -0
  159. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/version/get.py +0 -0
  160. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/version/list.py +0 -0
  161. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/cloud/version/update.py +0 -0
  162. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/community/__init__.py +0 -0
  163. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/community/clone.py +0 -0
  164. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/community/list.py +0 -0
  165. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/configuration/__init__.py +0 -0
  166. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/configuration/config.py +0 -0
  167. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/configuration/create.py +0 -0
  168. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/configuration/delete.py +0 -0
  169. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/configuration/list.py +0 -0
  170. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/init.py +0 -0
  171. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/__init__.py +0 -0
  172. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/__init__.py +0 -0
  173. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/delete.py +0 -0
  174. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/get.py +0 -0
  175. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/list.py +0 -0
  176. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/register.py +0 -0
  177. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/registered.py +0 -0
  178. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/sync.py +0 -0
  179. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/app/update.py +0 -0
  180. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/__init__.py +0 -0
  181. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/create.py +0 -0
  182. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/get.py +0 -0
  183. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/input.py +0 -0
  184. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/list.py +0 -0
  185. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/logs.py +0 -0
  186. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/metadata.py +0 -0
  187. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/local/run/visuals.py +0 -0
  188. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/manifest/__init__.py +0 -0
  189. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/manifest/init.py +0 -0
  190. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/manifest/validate.py +0 -0
  191. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/__init__.py +0 -0
  192. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/serve.py +0 -0
  193. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/server.py +0 -0
  194. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/WORKFLOW.md +0 -0
  195. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/__init__.py +0 -0
  196. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/_helpers.py +0 -0
  197. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/acceptance.py +0 -0
  198. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/account.py +0 -0
  199. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/app.py +0 -0
  200. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/batch.py +0 -0
  201. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/community.py +0 -0
  202. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/ensemble.py +0 -0
  203. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/guide.py +0 -0
  204. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/input_set.py +0 -0
  205. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/instance.py +0 -0
  206. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/local.py +0 -0
  207. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/managed_input.py +0 -0
  208. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/profile.py +0 -0
  209. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/run.py +0 -0
  210. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/scenario.py +0 -0
  211. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/secrets.py +0 -0
  212. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/shadow.py +0 -0
  213. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/sso.py +0 -0
  214. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/switchback.py +0 -0
  215. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/mcp/tools/version.py +0 -0
  216. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/message.py +0 -0
  217. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/options.py +0 -0
  218. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cli/version.py +0 -0
  219. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/__init__.py +0 -0
  220. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/acceptance_test.py +0 -0
  221. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/account.py +0 -0
  222. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_acceptance.py +0 -0
  223. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_batch_scenario.py +0 -0
  224. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_ensemble.py +0 -0
  225. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_input_set.py +0 -0
  226. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_instance.py +0 -0
  227. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_managed_input.py +0 -0
  228. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_run.py +0 -0
  229. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_secrets.py +0 -0
  230. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_shadow.py +0 -0
  231. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_switchback.py +0 -0
  232. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_utils.py +0 -0
  233. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/application/_version.py +0 -0
  234. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/assets.py +0 -0
  235. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/batch_experiment.py +0 -0
  236. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/community.py +0 -0
  237. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/ensemble.py +0 -0
  238. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/input_set.py +0 -0
  239. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/instance.py +0 -0
  240. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/integration.py +0 -0
  241. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/marketplace.py +0 -0
  242. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/scenario.py +0 -0
  243. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/secrets.py +0 -0
  244. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/shadow.py +0 -0
  245. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/sso.py +0 -0
  246. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/switchback.py +0 -0
  247. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/url.py +0 -0
  248. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/cloud/version.py +0 -0
  249. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/content_format.py +0 -0
  250. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/deprecated.py +0 -0
  251. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/input.py +0 -0
  252. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/__init__.py +0 -0
  253. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/application.py +0 -0
  254. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/geojson_handler.py +0 -0
  255. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/local.py +0 -0
  256. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/plotly_handler.py +0 -0
  257. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/registry.py +0 -0
  258. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/local/runner.py +0 -0
  259. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/logger.py +0 -0
  260. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/model.py +0 -0
  261. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/options.py +0 -0
  262. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/output.py +0 -0
  263. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/run.py +0 -0
  264. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/safe.py +0 -0
  265. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/status.py +0 -0
  266. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/binary_json.yaml +0 -0
  267. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/binary_json_opt.yaml +0 -0
  268. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/binary_multi-file.yaml +0 -0
  269. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/binary_multi-file_opt.yaml +0 -0
  270. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json.yaml +0 -0
  271. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json_hello-world/.gitignore +0 -0
  272. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json_hello-world/README.md +0 -0
  273. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json_hello-world/app.yaml +0 -0
  274. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json_hello-world/go.mod +0 -0
  275. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json_hello-world/input.json +0 -0
  276. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json_hello-world/main.go +0 -0
  277. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_json_opt.yaml +0 -0
  278. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file.yaml +0 -0
  279. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file_hello-world/.gitignore +0 -0
  280. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file_hello-world/README.md +0 -0
  281. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file_hello-world/app.yaml +0 -0
  282. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file_hello-world/go.mod +0 -0
  283. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file_hello-world/inputs/input.json +0 -0
  284. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file_hello-world/main.go +0 -0
  285. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/go_multi-file_opt.yaml +0 -0
  286. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json.yaml +0 -0
  287. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json_hello-world/.gitignore +0 -0
  288. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json_hello-world/Main.java +0 -0
  289. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json_hello-world/README.md +0 -0
  290. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json_hello-world/app.yaml +0 -0
  291. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json_hello-world/input.json +0 -0
  292. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json_hello-world/pom.xml +0 -0
  293. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_json_opt.yaml +0 -0
  294. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file.yaml +0 -0
  295. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file_hello-world/.gitignore +0 -0
  296. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file_hello-world/Main.java +0 -0
  297. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file_hello-world/README.md +0 -0
  298. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file_hello-world/app.yaml +0 -0
  299. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file_hello-world/inputs/input.json +0 -0
  300. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file_hello-world/pom.xml +0 -0
  301. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/java_multi-file_opt.yaml +0 -0
  302. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json.yaml +0 -0
  303. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/.gitignore +0 -0
  304. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/README.md +0 -0
  305. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/app.yaml +0 -0
  306. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/input.json +0 -0
  307. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/main.py +0 -0
  308. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/pyproject.toml +0 -0
  309. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/uv.lock +0 -0
  310. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_class-assign/visualizations.py +0 -0
  311. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/.gitignore +0 -0
  312. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/README.md +0 -0
  313. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/allocation/README.md +0 -0
  314. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/allocation/app.yaml +0 -0
  315. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/allocation/input.json +0 -0
  316. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/allocation/main.py +0 -0
  317. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/allocation/pyproject.toml +0 -0
  318. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/allocation/uv.lock +0 -0
  319. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/allocation/visuals.py +0 -0
  320. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/workflow/README.md +0 -0
  321. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/workflow/app.yaml +0 -0
  322. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/workflow/input.json +0 -0
  323. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/workflow/main.py +0 -0
  324. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/workflow/pyproject.toml +0 -0
  325. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/workflow/uv.lock +0 -0
  326. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_demand-alloc/workflow/visuals.py +0 -0
  327. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_hello-world/.gitignore +0 -0
  328. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_hello-world/README.md +0 -0
  329. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_hello-world/app.yaml +0 -0
  330. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_hello-world/input.json +0 -0
  331. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_hello-world/main.py +0 -0
  332. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_hello-world/pyproject.toml +0 -0
  333. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_hello-world/uv.lock +0 -0
  334. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_json_opt.yaml +0 -0
  335. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file.yaml +0 -0
  336. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/.gitignore +0 -0
  337. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/README.md +0 -0
  338. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/app.yaml +0 -0
  339. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/inputs/input.json +0 -0
  340. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/main.py +0 -0
  341. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/pyproject.toml +0 -0
  342. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/uv.lock +0 -0
  343. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_class-assign/visualizations.py +0 -0
  344. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/README.md +0 -0
  345. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/README.md +0 -0
  346. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/app.yaml +0 -0
  347. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/input.json +0 -0
  348. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/main.py +0 -0
  349. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/pyproject.toml +0 -0
  350. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/uv.lock +0 -0
  351. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/visuals.py +0 -0
  352. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/.gitignore +0 -0
  353. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/README.md +0 -0
  354. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/app.yaml +0 -0
  355. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/inputs/input.json +0 -0
  356. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/main.py +0 -0
  357. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/pyproject.toml +0 -0
  358. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/uv.lock +0 -0
  359. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/visuals.py +0 -0
  360. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_hello-world/.gitignore +0 -0
  361. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_hello-world/README.md +0 -0
  362. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_hello-world/app.yaml +0 -0
  363. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_hello-world/inputs/input.json +0 -0
  364. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_hello-world/main.py +0 -0
  365. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_hello-world/pyproject.toml +0 -0
  366. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_hello-world/uv.lock +0 -0
  367. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/templates/python_multi-file_opt.yaml +0 -0
  368. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/nextmv/uv_handler.py +0 -0
  369. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/pyproject.toml +0 -0
  370. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/__init__.py +0 -0
  371. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/__init__.py +0 -0
  372. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/manifest/__init__.py +0 -0
  373. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/manifest/test_init.py +0 -0
  374. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/test_init_cli_call.py +0 -0
  375. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/test_main.py +0 -0
  376. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/test_mcp.py +0 -0
  377. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cli/test_version.py +0 -0
  378. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cloud/__init__.py +0 -0
  379. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cloud/app.yaml +0 -0
  380. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cloud/test_instance.py +0 -0
  381. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/cloud/test_scenario.py +0 -0
  382. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/integration/__init__.py +0 -0
  383. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/integration/cloud/__init__.py +0 -0
  384. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/integration/cloud/test_integration_cloud.py +0 -0
  385. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/integration/cloud/test_integration_marketplace.py +0 -0
  386. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/local/__init__.py +0 -0
  387. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/local/test_executor.py +0 -0
  388. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/local/test_registry.py +0 -0
  389. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/local/test_runner.py +0 -0
  390. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/__init__.py +0 -0
  391. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/options1.py +0 -0
  392. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/options2.py +0 -0
  393. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/options3.py +0 -0
  394. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/options4.py +0 -0
  395. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/options5.py +0 -0
  396. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/options6.py +0 -0
  397. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/scripts/options7.py +0 -0
  398. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_base_model.py +0 -0
  399. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_entrypoint/__init__.py +0 -0
  400. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_entrypoint/test_entrypoint.py +0 -0
  401. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_input.py +0 -0
  402. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_inputs/test_data.csv +0 -0
  403. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_inputs/test_data.json +0 -0
  404. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_inputs/test_data.txt +0 -0
  405. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_logger.py +0 -0
  406. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_model.py +0 -0
  407. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_options.py +0 -0
  408. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_output.py +0 -0
  409. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_polling.py +0 -0
  410. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_run.py +0 -0
  411. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_safe.py +0 -0
  412. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_serialization.py +0 -0
  413. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_uv_handler.py +0 -0
  414. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/tests/test_version.py +0 -0
  415. {nextmv-1.7.4.dev4 → nextmv-1.8.0.dev0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextmv
3
- Version: 1.7.4.dev4
3
+ Version: 1.8.0.dev0
4
4
  Summary: The all-purpose Python SDK for Nextmv
5
5
  Project-URL: Homepage, https://www.nextmv.io
6
6
  Project-URL: Documentation, https://nextmv-py.docs.nextmv.io/en/latest/nextmv/
@@ -0,0 +1 @@
1
+ __version__ = "v1.8.0.dev0"
@@ -0,0 +1,420 @@
1
+ """
2
+ Module with the cache interface and operations for working with dependencies.
3
+
4
+ Functions
5
+ ---------
6
+ get_cache
7
+ Get general information about the cache, including number of dependencies and total size.
8
+ clear_cache
9
+ Delete the entire cache directory and recreate it empty.
10
+ dep_cache_key
11
+ Return a SHA-256 hex digest that uniquely identifies a single package.
12
+ get_cached_dep
13
+ Return the path to the cached per-package `installed.tar.gz` on a hit.
14
+ store_dep
15
+ Store a per-package `installed.tar.gz` into the cache and run LRU eviction.
16
+ format_bytes
17
+ Return a human-friendly string representation of a byte count.
18
+ """
19
+
20
+ import hashlib
21
+ import json
22
+ import os
23
+ import re
24
+ import shutil
25
+ import tempfile
26
+ from datetime import datetime, timezone
27
+ from pathlib import Path
28
+ from typing import Any
29
+
30
+ _CACHE_DIR = Path.home() / ".nextmv" / "cache"
31
+ """Root directory for all Nextmv cache data."""
32
+ _DEPS_CACHE_DIR = _CACHE_DIR / "deps"
33
+ """Directory storing per-package dependency tarballs."""
34
+ _CACHE_INFO_FILE = "cache_info.json"
35
+ """Name of the metadata file stored alongside each cached entry."""
36
+ _MAX_DEPS = 2000
37
+ """Maximum number of individual package tarballs to keep in the cache."""
38
+ _MAX_DEP_BYTES = 5 * 1024**3
39
+ """Maximum total cache size in bytes (5 GiB)."""
40
+
41
+
42
+ def get_cache() -> dict[str, Any]:
43
+ """
44
+ Gets general information about the cache.
45
+
46
+ Returns
47
+ -------
48
+ dict[str, Any]
49
+ A dictionary containing information about the cache, such as the number of
50
+ dependencies cached and the total size of the cache in bytes.
51
+ """
52
+
53
+ num_deps, total_bytes = _cache_stats()
54
+
55
+ dependencies = []
56
+ if _DEPS_CACHE_DIR.is_dir():
57
+ for entry_dir in _DEPS_CACHE_DIR.iterdir():
58
+ if not entry_dir.is_dir():
59
+ continue
60
+
61
+ info_file = entry_dir / _CACHE_INFO_FILE
62
+ try:
63
+ with open(info_file) as f:
64
+ info = json.load(f)
65
+
66
+ dependencies.append(
67
+ {
68
+ "key": entry_dir.name,
69
+ "name": info.get("name", ""),
70
+ "version": info.get("version", ""),
71
+ "last_used_at": info.get("last_used_at", ""),
72
+ "python_version": info.get("python_version", ""),
73
+ "platform": info.get("platform", ""),
74
+ }
75
+ )
76
+ except Exception:
77
+ pass
78
+
79
+ if dependencies:
80
+ dependencies.sort(key=lambda d: (d["last_used_at"], d["name"], d["version"]))
81
+
82
+ return {
83
+ "num_dependencies": num_deps,
84
+ "total_size": format_bytes(total_bytes),
85
+ "dependencies": dependencies,
86
+ }
87
+
88
+
89
+ def clear_cache() -> tuple[int, int]:
90
+ """
91
+ Delete the entire cache directory and recreate it empty.
92
+
93
+ Returns
94
+ -------
95
+ tuple[int, int]
96
+ A tuple of (num_deps_deleted, total_bytes_deleted).
97
+ """
98
+
99
+ if not _CACHE_DIR.exists():
100
+ return 0, 0
101
+
102
+ num_deps, total_bytes = _cache_stats()
103
+
104
+ if _CACHE_DIR.exists():
105
+ shutil.rmtree(str(_CACHE_DIR))
106
+
107
+ _create_cache()
108
+
109
+ return num_deps, total_bytes
110
+
111
+
112
+ def dep_cache_key(name: str, version: str, python_version: str, platform: str) -> str:
113
+ """
114
+ Return a SHA-256 hex digest that uniquely identifies a single package wheel.
115
+
116
+ The key is derived from the normalised package name, version, target Python
117
+ version, and platform. Name normalisation follows PEP 503 so that
118
+ `pydantic-core` and `pydantic_core` map to the same key.
119
+
120
+ Parameters
121
+ ----------
122
+ name : str
123
+ The package name as it appears in the lockfile or wheel filename.
124
+ version : str
125
+ The pinned version string (e.g. `"2.23.4"`).
126
+ python_version : str
127
+ The target Python version string (e.g. `"3.11"`).
128
+ platform : str
129
+ The target platform string (e.g. `"aarch64-unknown-linux-gnu"`).
130
+
131
+ Returns
132
+ -------
133
+ str
134
+ A 64-character lowercase hex SHA-256 digest.
135
+ """
136
+
137
+ normalized = re.sub(r"[-_.]+", "_", name.lower())
138
+ raw = f"{normalized}=={version}|{python_version}|{platform}"
139
+
140
+ return hashlib.sha256(raw.encode()).hexdigest()
141
+
142
+
143
+ def get_cached_dep(pkg_key: str) -> Path | None:
144
+ """
145
+ Return the path to the cached `installed.tar.gz` for *pkg_key*, or `None`
146
+ on a miss.
147
+
148
+ The tarball contains the installed files for a single package archived under
149
+ `.nextmv/python/deps/`, ready to be concatenated with other per-package
150
+ tarballs to form the final `deps.tar.gz` (valid per RFC 1952).
151
+
152
+ On a cache hit `last_used_at` in the entry's `cache_info.json` is
153
+ updated to the current UTC time for LRU tracking.
154
+
155
+ Parameters
156
+ ----------
157
+ pkg_key : str
158
+ The cache key returned by :func:`dep_cache_key`.
159
+
160
+ Returns
161
+ -------
162
+ Path or None
163
+ Path to the `installed.tar.gz` file, or `None` when no entry exists.
164
+ """
165
+
166
+ entry_dir = _DEPS_CACHE_DIR / pkg_key
167
+ info_file = entry_dir / _CACHE_INFO_FILE
168
+ installed_tar = entry_dir / "installed.tar.gz"
169
+
170
+ if not installed_tar.is_file() or not info_file.is_file():
171
+ return None
172
+
173
+ # Update last_used_at for true LRU tracking.
174
+ try:
175
+ with open(info_file) as f:
176
+ info = json.load(f)
177
+
178
+ info["last_used_at"] = _now_iso()
179
+ _write_json_atomic(path=info_file, data=info)
180
+ except Exception:
181
+ pass
182
+
183
+ return installed_tar
184
+
185
+
186
+ def store_dep(
187
+ pkg_key: str,
188
+ tar_path: Path,
189
+ name: str,
190
+ version: str,
191
+ python_version: str,
192
+ platform: str,
193
+ max_entries: int = _MAX_DEPS,
194
+ max_bytes: int = _MAX_DEP_BYTES,
195
+ ) -> None:
196
+ """
197
+ Store a per-package `installed.tar.gz` in the cache and run LRU eviction.
198
+
199
+ The tarball must contain the installed files for a single package archived
200
+ under `.nextmv/python/deps/`. The copy is performed atomically via a
201
+ sibling temporary directory followed by a rename.
202
+
203
+ Parameters
204
+ ----------
205
+ pkg_key : str
206
+ The cache key returned by :func:`dep_cache_key`.
207
+ tar_path : Path
208
+ Path to the `installed.tar.gz` to cache.
209
+ name : str
210
+ The package name (e.g. `"pydantic-core"`).
211
+ version : str
212
+ The pinned version string (e.g. `"2.23.4"`).
213
+ python_version : str
214
+ The target Python version string (e.g. `"3.11"`).
215
+ platform : str
216
+ The target platform string (e.g. `"aarch64-unknown-linux-gnu"`).
217
+ max_entries : int, optional
218
+ Maximum number of package tarball entries to retain.
219
+ max_bytes : int, optional
220
+ Maximum total cache size in bytes.
221
+ """
222
+
223
+ _create_cache()
224
+ entry_dir = _DEPS_CACHE_DIR / pkg_key
225
+
226
+ with tempfile.TemporaryDirectory(dir=_DEPS_CACHE_DIR, prefix=f"{pkg_key}-tmp-", ignore_cleanup_errors=True) as _tmp:
227
+ tmp_entry = Path(_tmp)
228
+ shutil.copy2(str(tar_path), tmp_entry / "installed.tar.gz")
229
+ now = _now_iso()
230
+ info = {
231
+ "created_at": now,
232
+ "last_used_at": now,
233
+ "name": name,
234
+ "version": version,
235
+ "python_version": python_version,
236
+ "platform": platform,
237
+ }
238
+ _write_json_atomic(path=tmp_entry / _CACHE_INFO_FILE, data=info)
239
+
240
+ # Rename into place; if the key already exists (race), keep existing.
241
+ if not entry_dir.exists():
242
+ tmp_entry.rename(entry_dir)
243
+
244
+ _evict_lru(max_entries=max_entries, max_bytes=max_bytes)
245
+
246
+
247
+ def format_bytes(size: int) -> str:
248
+ """
249
+ Return a human-friendly string representation of a byte count.
250
+
251
+ Parameters
252
+ ----------
253
+ size : int
254
+ The size in bytes to format.
255
+
256
+ Returns
257
+ -------
258
+ str
259
+ A human-friendly string using B, KiB, MiB, or GiB units.
260
+ """
261
+
262
+ if size < 1024:
263
+ return f"{size} B"
264
+ elif size < 1024 * 1024:
265
+ return f"{size / 1024:.2f} KiB"
266
+ elif size < 1024 * 1024 * 1024:
267
+ return f"{size / (1024 * 1024):.2f} MiB"
268
+ else:
269
+ return f"{size / (1024 * 1024 * 1024):.2f} GiB"
270
+
271
+
272
+ def _cache_stats() -> tuple[int, int]:
273
+ """
274
+ Return the number of cached dependency entries and their total size in bytes.
275
+
276
+ Returns
277
+ -------
278
+ tuple[int, int]
279
+ A tuple of (num_deps, total_bytes).
280
+ """
281
+
282
+ num_deps = 0
283
+ total_bytes = 0
284
+
285
+ if not _DEPS_CACHE_DIR.is_dir():
286
+ return num_deps, total_bytes
287
+
288
+ for entry_dir in _DEPS_CACHE_DIR.iterdir():
289
+ if entry_dir.is_dir():
290
+ num_deps += 1
291
+ total_bytes += _dir_size(entry_dir)
292
+
293
+ return num_deps, total_bytes
294
+
295
+
296
+ def _create_cache() -> None:
297
+ """
298
+ Create the cache directories if they do not already exist.
299
+ """
300
+
301
+ _DEPS_CACHE_DIR.mkdir(parents=True, exist_ok=True)
302
+
303
+
304
+ def _evict_lru(max_entries: int = _MAX_DEPS, max_bytes: int = _MAX_DEP_BYTES) -> int:
305
+ """
306
+ Remove the least-recently-used per-package tarball cache entries until both
307
+ caps are satisfied.
308
+
309
+ Parameters
310
+ ----------
311
+ max_entries : int, optional
312
+ Maximum number of package tarball entries to retain.
313
+ max_bytes : int, optional
314
+ Maximum total cache size in bytes.
315
+
316
+ Returns
317
+ -------
318
+ int
319
+ The number of entries that were removed.
320
+ """
321
+
322
+ if not _DEPS_CACHE_DIR.is_dir():
323
+ return 0
324
+
325
+ entries = []
326
+ for entry_dir in _DEPS_CACHE_DIR.iterdir():
327
+ if not entry_dir.is_dir():
328
+ continue
329
+
330
+ info_file = entry_dir / _CACHE_INFO_FILE
331
+ # If the info file has problems, treat the entry as very old.
332
+ try:
333
+ with open(info_file) as f:
334
+ info = json.load(f)
335
+
336
+ last_used = datetime.fromisoformat(info["last_used_at"])
337
+ except Exception:
338
+ last_used = datetime.min.replace(tzinfo=timezone.utc)
339
+
340
+ entries.append(
341
+ {
342
+ "last_used": last_used,
343
+ "dir": entry_dir,
344
+ "size": _dir_size(entry_dir),
345
+ }
346
+ )
347
+
348
+ entries.sort(key=lambda e: e["last_used"])
349
+
350
+ total = sum(e["size"] for e in entries)
351
+ evicted = 0
352
+ while entries and (len(entries) > max_entries or total > max_bytes):
353
+ oldest = entries.pop(0)
354
+ shutil.rmtree(str(oldest["dir"]), ignore_errors=True)
355
+ total -= oldest["size"]
356
+ evicted += 1
357
+
358
+ return evicted
359
+
360
+
361
+ def _now_iso() -> str:
362
+ """
363
+ Return the current UTC time as an ISO-8601 string.
364
+
365
+ Returns
366
+ -------
367
+ str
368
+ Current UTC time as an ISO-8601 string.
369
+ """
370
+
371
+ return datetime.now(tz=timezone.utc).isoformat()
372
+
373
+
374
+ def _dir_size(path: Path) -> int:
375
+ """
376
+ Return the total size in bytes of all files under path.
377
+
378
+ Parameters
379
+ ----------
380
+ path : Path
381
+ The directory path to calculate the size of.
382
+
383
+ Returns
384
+ -------
385
+ int
386
+ Total size in bytes of all files under path.
387
+ """
388
+
389
+ total = 0
390
+ for root, _, files in os.walk(path):
391
+ for fname in files:
392
+ try:
393
+ total += os.path.getsize(os.path.join(root, fname))
394
+ except OSError:
395
+ pass
396
+
397
+ return total
398
+
399
+
400
+ def _write_json_atomic(path: Path, data: dict) -> None:
401
+ """
402
+ Write data as JSON to path atomically via a sibling temporary file.
403
+
404
+ Parameters
405
+ ----------
406
+ path : Path
407
+ The path to write the JSON data to.
408
+ data : dict
409
+ The data to write as JSON.
410
+ """
411
+
412
+ with tempfile.NamedTemporaryFile(mode="w", dir=path.parent, prefix=".tmp-", delete=False) as f:
413
+ json.dump(data, f, indent=2)
414
+ tmp = Path(f.name)
415
+
416
+ try:
417
+ tmp.rename(path)
418
+ except Exception as e:
419
+ tmp.unlink(missing_ok=True)
420
+ raise e
@@ -0,0 +1,21 @@
1
+ """
2
+ This module defines the cache command tree for the Nextmv CLI.
3
+ """
4
+
5
+ import typer
6
+
7
+ from nextmv.cli.cache.delete import app as delete_app
8
+ from nextmv.cli.cache.get import app as get_app
9
+
10
+ # Set up subcommand application.
11
+ app = typer.Typer()
12
+ app.add_typer(delete_app)
13
+ app.add_typer(get_app)
14
+
15
+
16
+ @app.callback()
17
+ def callback() -> None:
18
+ """
19
+ Manage the cache used for Nextmv operations.
20
+ """
21
+ pass
@@ -0,0 +1,48 @@
1
+ """
2
+ This module defines the cache delete command for the Nextmv CLI.
3
+ """
4
+
5
+ import typer
6
+
7
+ from nextmv.cache import clear_cache, format_bytes
8
+ from nextmv.cli.message import confirmation, info, success
9
+ from nextmv.cli.options import YesOption
10
+
11
+ # Set up subcommand application.
12
+ app = typer.Typer()
13
+
14
+
15
+ @app.command()
16
+ def delete(yes: YesOption = False) -> None:
17
+ """
18
+ Deletes the Nextmv cache and resets it to an empty state.
19
+
20
+ This action is permanent and cannot be undone. Use the --yes flag to skip
21
+ the confirmation prompt.
22
+
23
+ [bold][underline]Examples[/underline][/bold]
24
+
25
+ - Delete the Nextmv cache.
26
+ $ [dim]nextmv cache delete[/dim]
27
+
28
+ - Delete the Nextmv cache without confirmation prompt.
29
+ $ [dim]nextmv cache delete --yes[/dim]
30
+ """
31
+
32
+ deps, bytes_deleted = clear_cache()
33
+ if deps == 0 and bytes_deleted == 0:
34
+ info("Nothing to delete: cache is already empty.")
35
+ return
36
+
37
+ if not yes:
38
+ confirm = confirmation(
39
+ "Are you sure you want to delete the Nextmv cache? This action cannot be undone.",
40
+ )
41
+
42
+ if not confirm:
43
+ info("The Nextmv cache will not be deleted.")
44
+ return
45
+
46
+ size_str = format_bytes(bytes_deleted)
47
+ dep_label = "dependency" if deps == 1 else "dependencies"
48
+ success(f"Deleted [magenta]{deps}[/magenta] {dep_label} ([magenta]{size_str}[/magenta]) from the cache.")
@@ -0,0 +1,27 @@
1
+ """
2
+ This module defines the cache get command for the Nextmv CLI.
3
+ """
4
+
5
+ import typer
6
+
7
+ from nextmv.cache import get_cache
8
+ from nextmv.cli.message import print_json, success
9
+
10
+ # Set up subcommand application.
11
+ app = typer.Typer()
12
+
13
+
14
+ @app.command()
15
+ def get() -> None:
16
+ """
17
+ Gets general information about the Nextmv cache.
18
+
19
+ [bold][underline]Examples[/underline][/bold]
20
+
21
+ - Get cache information.
22
+ $ [dim]nextmv cache get[/dim]
23
+ """
24
+
25
+ info = get_cache()
26
+ success("Cache information retrieved successfully.")
27
+ print_json(info)
@@ -40,6 +40,13 @@ def push(
40
40
  metavar="MANIFEST_PATH",
41
41
  ),
42
42
  ] = None,
43
+ no_cache: Annotated[
44
+ bool,
45
+ typer.Option(
46
+ "--no-cache",
47
+ help="Do not read from or write to the Nextmv dependency cache for [magenta]Python[/magenta] applications.",
48
+ ),
49
+ ] = False,
43
50
  # Options for version control.
44
51
  version_id: Annotated[
45
52
  str | None,
@@ -184,6 +191,7 @@ def push(
184
191
  update_instance_id=update_instance_id,
185
192
  create_defined=create_defined,
186
193
  create_instance_id=create_instance_id,
194
+ no_cache=no_cache,
187
195
  )
188
196
 
189
197
 
@@ -199,6 +207,7 @@ def handle_push(
199
207
  update_instance_id: str | None,
200
208
  create_defined: bool,
201
209
  create_instance_id: str | None,
210
+ no_cache: bool = False,
202
211
  ) -> str:
203
212
  """
204
213
  Handle the core push flow: push the application, create a version, and link it to an instance.
@@ -227,6 +236,9 @@ def handle_push(
227
236
  Whether --create-instance-id was provided.
228
237
  create_instance_id : str | None
229
238
  The instance ID to create.
239
+ no_cache : bool
240
+ Whether to disable the dependency cache when packaging Python
241
+ applications.
230
242
 
231
243
  Returns
232
244
  -------
@@ -242,6 +254,7 @@ def handle_push(
242
254
  app_dir=app_dir,
243
255
  verbose=True,
244
256
  rich_print=True,
257
+ no_cache=no_cache,
245
258
  )
246
259
 
247
260
  now = datetime.now(timezone.utc)
@@ -23,6 +23,7 @@ import rich
23
23
  import typer
24
24
  from typer import rich_utils
25
25
 
26
+ from nextmv.cli.cache import app as cache_app
26
27
  from nextmv.cli.cloud import app as cloud_app
27
28
  from nextmv.cli.community import app as community_app
28
29
  from nextmv.cli.configuration import app as configuration_app
@@ -52,6 +53,7 @@ app = typer.Typer(
52
53
 
53
54
  # Register subcommands. The `name` parameter is required when the subcommand
54
55
  # module has a callback function defined.
56
+ app.add_typer(cache_app, name="cache")
55
57
  app.add_typer(cloud_app, name="cloud")
56
58
  app.add_typer(community_app, name="community")
57
59
  app.add_typer(configuration_app, name="configuration")
@@ -414,7 +414,7 @@ class Application(
414
414
  # Re-throw the exception if it is not the expected 404 error.
415
415
  raise e from None
416
416
 
417
- def push( # noqa: C901
417
+ def push(
418
418
  self,
419
419
  manifest: Manifest | None = None,
420
420
  app_dir: str | None = None,
@@ -422,6 +422,7 @@ class Application(
422
422
  model: Model | None = None,
423
423
  model_configuration: ModelConfiguration | None = None,
424
424
  rich_print: bool = False,
425
+ no_cache: bool = False,
425
426
  ) -> None:
426
427
  """
427
428
  Push an app to Nextmv Cloud.
@@ -457,6 +458,13 @@ class Application(
457
458
  with `model`.
458
459
  rich_print : bool, default=False
459
460
  Whether to use rich printing when verbose output is enabled.
461
+ no_cache : bool, default=False
462
+ When working with Python, dependencies are cached to speed up
463
+ subsequent pushes. Setting no_cache to True will skip using the
464
+ cache and force a fresh build of all dependencies. This is useful
465
+ when you want to ensure that you are pushing the most up-to-date
466
+ versions of your dependencies, or if you are encountering issues
467
+ with the cache and want to rule it out as a potential cause.
460
468
 
461
469
  Raises
462
470
  ------
@@ -550,9 +558,17 @@ class Application(
550
558
  if (model is None and model_configuration is not None) or (model is not None and model_configuration is None):
551
559
  raise ValueError("model and model_configuration must be provided together")
552
560
 
553
- package._run_build_command(app_dir, manifest.build, verbose, rich_print)
554
- package._run_pre_push_command(app_dir, manifest.pre_push, verbose, rich_print)
555
- tar_file, output_dir = package._package(app_dir, manifest, model, model_configuration, verbose, rich_print)
561
+ package.run_build_command(app_dir, manifest.build, verbose, rich_print)
562
+ package.run_pre_push_command(app_dir, manifest.pre_push, verbose, rich_print)
563
+ tar_file, output_dir = package.package(
564
+ app_dir,
565
+ manifest,
566
+ model,
567
+ model_configuration,
568
+ verbose,
569
+ rich_print,
570
+ no_cache,
571
+ )
556
572
  self.__update_app_binary(tar_file, manifest, verbose, rich_print)
557
573
 
558
574
  try:
@@ -276,7 +276,7 @@ class Client:
276
276
  reason="`Client.configuration_file` is deprecated, use `Client.profile` to work with another profile",
277
277
  )
278
278
 
279
- def request(
279
+ def request( # noqa: C901
280
280
  self,
281
281
  method: str,
282
282
  endpoint: str,
@@ -428,7 +428,19 @@ class Client:
428
428
  if query_params is not None:
429
429
  kwargs["params"] = query_params
430
430
 
431
- response = session.request(method=method, **kwargs)
431
+ try:
432
+ response = session.request(method=method, **kwargs)
433
+ except requests.exceptions.ConnectionError as e:
434
+ raise requests.exceptions.ConnectionError(
435
+ f"could not connect to {self.url}: the server may be unreachable. "
436
+ "Check your network connectivity and verify the endpoint URL is correct."
437
+ ) from e
438
+ except requests.exceptions.Timeout as e:
439
+ raise requests.exceptions.Timeout(
440
+ f"request to {endpoint} timed out after {self.timeout}s waiting for {self.url}. "
441
+ "The server may be unreachable or under heavy load. "
442
+ "Consider increasing the `timeout` attribute on the Client."
443
+ ) from e
432
444
 
433
445
  try:
434
446
  response.raise_for_status()
@@ -534,11 +546,24 @@ class Client:
534
546
  elif tar_file is not None and tar_file != "":
535
547
  if not os.path.exists(tar_file):
536
548
  raise ValueError(f"tar_file {tar_file} does not exist")
537
- kwargs["data"] = open(tar_file, "rb")
549
+ with open(tar_file, "rb") as f:
550
+ kwargs["data"] = f.read()
538
551
  else:
539
552
  raise ValueError("either data or tar_file must be provided")
540
553
 
541
- response = session.put(**kwargs)
554
+ try:
555
+ response = session.put(**kwargs)
556
+ except requests.exceptions.ConnectionError as e:
557
+ raise requests.exceptions.ConnectionError(
558
+ "could not connect to upload URL: the server may be unreachable. "
559
+ "Check your network connectivity and verify the URL is correct."
560
+ ) from e
561
+ except requests.exceptions.Timeout as e:
562
+ raise requests.exceptions.Timeout(
563
+ f"upload request timed out after {self.timeout}s. "
564
+ "The server may be unreachable or under heavy load. "
565
+ "Consider increasing the `timeout` attribute on the Client."
566
+ ) from e
542
567
 
543
568
  try:
544
569
  response.raise_for_status()