nextmv 1.1.3.dev2__tar.gz → 1.2.0.dev1__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 (296) hide show
  1. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/.gitignore +1 -1
  2. {nextmv-1.1.3.dev2/nextmv/cli → nextmv-1.2.0.dev1}/CONTRIBUTING.md +211 -18
  3. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/PKG-INFO +2 -7
  4. nextmv-1.2.0.dev1/nextmv/__about__.py +1 -0
  5. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/__init__.py +2 -0
  6. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/acceptance/delete.py +2 -3
  7. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/account/delete.py +2 -3
  8. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/delete.py +2 -3
  9. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/push.py +4 -5
  10. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/batch/delete.py +2 -3
  11. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/ensemble/delete.py +2 -3
  12. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/input_set/delete.py +2 -3
  13. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/instance/delete.py +2 -3
  14. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/managed_input/delete.py +2 -3
  15. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/subscription/delete.py +2 -3
  16. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/create.py +26 -5
  17. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/scenario/delete.py +2 -3
  18. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/secrets/delete.py +2 -3
  19. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/delete.py +2 -3
  20. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/sso/__init__.py +2 -0
  21. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/sso/delete.py +2 -3
  22. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/sso/disable.py +2 -3
  23. nextmv-1.2.0.dev1/nextmv/cli/cloud/sso/domain/__init__.py +24 -0
  24. nextmv-1.2.0.dev1/nextmv/cli/cloud/sso/domain/delete.py +67 -0
  25. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/sso/enable.py +2 -3
  26. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/delete.py +2 -3
  27. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/version/delete.py +2 -3
  28. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/configuration/config.py +6 -7
  29. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/configuration/delete.py +2 -3
  30. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/delete.py +2 -3
  31. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/sync.py +2 -4
  32. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/main.py +5 -6
  33. nextmv-1.2.0.dev1/nextmv/cli/manifest/__init__.py +21 -0
  34. nextmv-1.2.0.dev1/nextmv/cli/manifest/init.py +104 -0
  35. nextmv-1.2.0.dev1/nextmv/cli/manifest/validate.py +53 -0
  36. nextmv-1.2.0.dev1/nextmv/cli/message.py +316 -0
  37. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_run.py +22 -4
  38. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/client.py +5 -1
  39. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/sso.py +24 -1
  40. nextmv-1.2.0.dev1/nextmv/content_format.py +53 -0
  41. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/input.py +0 -2
  42. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/manifest.py +56 -1
  43. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/run.py +40 -0
  44. nextmv-1.2.0.dev1/nextmv/templates/binary_json_app.yaml +24 -0
  45. nextmv-1.2.0.dev1/nextmv/templates/binary_multi-file_app.yaml +32 -0
  46. nextmv-1.2.0.dev1/nextmv/templates/go_json_app.yaml +24 -0
  47. nextmv-1.2.0.dev1/nextmv/templates/go_multi-file_app.yaml +32 -0
  48. nextmv-1.2.0.dev1/nextmv/templates/java_json_app.yaml +19 -0
  49. nextmv-1.2.0.dev1/nextmv/templates/java_multi-file_app.yaml +27 -0
  50. nextmv-1.2.0.dev1/nextmv/templates/python_json_app.yaml +21 -0
  51. nextmv-1.2.0.dev1/nextmv/templates/python_multi-file_app.yaml +29 -0
  52. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/pyproject.toml +2 -9
  53. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cli/test_configuration.py +1 -1
  54. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/integration/cloud/test_integration_cloud.py +15 -4
  55. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_manifest.py +120 -0
  56. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/uv.lock +35 -305
  57. nextmv-1.1.3.dev2/nextmv/__about__.py +0 -1
  58. nextmv-1.1.3.dev2/nextmv/cli/confirm.py +0 -34
  59. nextmv-1.1.3.dev2/nextmv/cli/mcp/__init__.py +0 -26
  60. nextmv-1.1.3.dev2/nextmv/cli/mcp/serve.py +0 -76
  61. nextmv-1.1.3.dev2/nextmv/cli/mcp/server.py +0 -1927
  62. nextmv-1.1.3.dev2/nextmv/cli/message.py +0 -170
  63. nextmv-1.1.3.dev2/tests/README.md +0 -91
  64. nextmv-1.1.3.dev2/tests/cli/test_mcp.py +0 -622
  65. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/.python-version +0 -0
  66. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/LICENSE +0 -0
  67. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/README.md +0 -0
  68. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/__entrypoint__.py +0 -0
  69. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/_serialization.py +0 -0
  70. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/base_model.py +0 -0
  71. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/__init__.py +0 -0
  72. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/__init__.py +0 -0
  73. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/acceptance/__init__.py +0 -0
  74. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/acceptance/create.py +0 -0
  75. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/acceptance/get.py +0 -0
  76. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/acceptance/list.py +0 -0
  77. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/acceptance/update.py +0 -0
  78. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/account/__init__.py +0 -0
  79. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/account/create.py +0 -0
  80. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/account/get.py +0 -0
  81. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/account/update.py +0 -0
  82. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/__init__.py +0 -0
  83. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/create.py +0 -0
  84. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/exists.py +0 -0
  85. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/get.py +0 -0
  86. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/list.py +0 -0
  87. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/app/update.py +0 -0
  88. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/batch/__init__.py +0 -0
  89. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/batch/create.py +0 -0
  90. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/batch/get.py +0 -0
  91. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/batch/list.py +0 -0
  92. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/batch/metadata.py +0 -0
  93. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/batch/update.py +0 -0
  94. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/data/__init__.py +0 -0
  95. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/data/upload.py +0 -0
  96. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/ensemble/__init__.py +0 -0
  97. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/ensemble/create.py +0 -0
  98. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/ensemble/get.py +0 -0
  99. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/ensemble/list.py +0 -0
  100. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/ensemble/update.py +0 -0
  101. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/input_set/__init__.py +0 -0
  102. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/input_set/create.py +0 -0
  103. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/input_set/get.py +0 -0
  104. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/input_set/list.py +0 -0
  105. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/input_set/update.py +0 -0
  106. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/instance/__init__.py +0 -0
  107. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/instance/create.py +0 -0
  108. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/instance/exists.py +0 -0
  109. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/instance/get.py +0 -0
  110. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/instance/list.py +0 -0
  111. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/instance/update.py +0 -0
  112. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/managed_input/__init__.py +0 -0
  113. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/managed_input/create.py +0 -0
  114. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/managed_input/get.py +0 -0
  115. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/managed_input/list.py +0 -0
  116. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/managed_input/update.py +0 -0
  117. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/__init__.py +0 -0
  118. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/app/__init__.py +0 -0
  119. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/app/create.py +0 -0
  120. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/app/get.py +0 -0
  121. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/app/list.py +0 -0
  122. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/app/update.py +0 -0
  123. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/subscription/__init__.py +0 -0
  124. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/subscription/create.py +0 -0
  125. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/subscription/get.py +0 -0
  126. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/subscription/list.py +0 -0
  127. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/version/__init__.py +0 -0
  128. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/version/create.py +0 -0
  129. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/version/get.py +0 -0
  130. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/version/list.py +0 -0
  131. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/marketplace/version/update.py +0 -0
  132. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/__init__.py +0 -0
  133. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/cancel.py +0 -0
  134. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/get.py +0 -0
  135. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/input.py +0 -0
  136. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/list.py +0 -0
  137. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/logs.py +0 -0
  138. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/metadata.py +0 -0
  139. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/run/track.py +0 -0
  140. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/scenario/__init__.py +0 -0
  141. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/scenario/create.py +0 -0
  142. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/scenario/get.py +0 -0
  143. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/scenario/list.py +0 -0
  144. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/scenario/metadata.py +0 -0
  145. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/scenario/update.py +0 -0
  146. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/secrets/__init__.py +0 -0
  147. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/secrets/create.py +0 -0
  148. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/secrets/get.py +0 -0
  149. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/secrets/list.py +0 -0
  150. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/secrets/update.py +0 -0
  151. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/__init__.py +0 -0
  152. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/create.py +0 -0
  153. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/get.py +0 -0
  154. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/list.py +0 -0
  155. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/metadata.py +0 -0
  156. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/start.py +0 -0
  157. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/stop.py +0 -0
  158. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/shadow/update.py +0 -0
  159. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/sso/create.py +0 -0
  160. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/sso/get.py +0 -0
  161. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/sso/update.py +0 -0
  162. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/__init__.py +0 -0
  163. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/create.py +0 -0
  164. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/get.py +0 -0
  165. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/list.py +0 -0
  166. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/metadata.py +0 -0
  167. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/start.py +0 -0
  168. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/stop.py +0 -0
  169. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/switchback/update.py +0 -0
  170. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/upload/__init__.py +0 -0
  171. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/upload/create.py +0 -0
  172. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/version/__init__.py +0 -0
  173. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/version/create.py +0 -0
  174. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/version/exists.py +0 -0
  175. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/version/get.py +0 -0
  176. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/version/list.py +0 -0
  177. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/cloud/version/update.py +0 -0
  178. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/community/__init__.py +0 -0
  179. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/community/clone.py +0 -0
  180. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/community/list.py +0 -0
  181. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/configuration/__init__.py +0 -0
  182. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/configuration/create.py +0 -0
  183. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/configuration/list.py +0 -0
  184. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/__init__.py +0 -0
  185. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/__init__.py +0 -0
  186. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/get.py +0 -0
  187. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/list.py +0 -0
  188. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/register.py +0 -0
  189. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/registered.py +0 -0
  190. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/app/update.py +0 -0
  191. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/__init__.py +0 -0
  192. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/create.py +0 -0
  193. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/get.py +0 -0
  194. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/input.py +0 -0
  195. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/list.py +0 -0
  196. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/logs.py +0 -0
  197. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/metadata.py +0 -0
  198. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/local/run/visuals.py +0 -0
  199. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/options.py +0 -0
  200. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cli/version.py +0 -0
  201. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/__init__.py +0 -0
  202. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/acceptance_test.py +0 -0
  203. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/account.py +0 -0
  204. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/__init__.py +0 -0
  205. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_acceptance.py +0 -0
  206. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_batch_scenario.py +0 -0
  207. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_ensemble.py +0 -0
  208. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_input_set.py +0 -0
  209. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_instance.py +0 -0
  210. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_managed_input.py +0 -0
  211. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_secrets.py +0 -0
  212. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_shadow.py +0 -0
  213. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_switchback.py +0 -0
  214. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_utils.py +0 -0
  215. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/application/_version.py +0 -0
  216. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/assets.py +0 -0
  217. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/batch_experiment.py +0 -0
  218. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/community.py +0 -0
  219. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/ensemble.py +0 -0
  220. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/input_set.py +0 -0
  221. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/instance.py +0 -0
  222. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/integration.py +0 -0
  223. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/marketplace.py +0 -0
  224. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/package.py +0 -0
  225. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/scenario.py +0 -0
  226. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/secrets.py +0 -0
  227. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/shadow.py +0 -0
  228. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/switchback.py +0 -0
  229. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/url.py +0 -0
  230. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/cloud/version.py +0 -0
  231. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/.gitignore +0 -0
  232. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/README.md +0 -0
  233. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/app.yaml +0 -0
  234. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/input.json +0 -0
  235. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/main.py +0 -0
  236. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/requirements.txt +0 -0
  237. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/src/__init__.py +0 -0
  238. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/default_app/src/visuals.py +0 -0
  239. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/deprecated.py +0 -0
  240. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/__init__.py +0 -0
  241. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/application.py +0 -0
  242. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/executor.py +0 -0
  243. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/geojson_handler.py +0 -0
  244. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/local.py +0 -0
  245. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/plotly_handler.py +0 -0
  246. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/registry.py +0 -0
  247. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/local/runner.py +0 -0
  248. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/logger.py +0 -0
  249. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/model.py +0 -0
  250. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/options.py +0 -0
  251. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/output.py +0 -0
  252. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/polling.py +0 -0
  253. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/safe.py +0 -0
  254. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/nextmv/status.py +0 -0
  255. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/__init__.py +0 -0
  256. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cli/__init__.py +0 -0
  257. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cli/test_main.py +0 -0
  258. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cli/test_version.py +0 -0
  259. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cloud/__init__.py +0 -0
  260. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cloud/app.yaml +0 -0
  261. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cloud/test_client.py +0 -0
  262. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cloud/test_instance.py +0 -0
  263. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cloud/test_package.py +0 -0
  264. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/cloud/test_scenario.py +0 -0
  265. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/integration/__init__.py +0 -0
  266. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/integration/cloud/__init__.py +0 -0
  267. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/integration/cloud/test_integration_marketplace.py +0 -0
  268. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/local/__init__.py +0 -0
  269. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/local/test_application.py +0 -0
  270. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/local/test_executor.py +0 -0
  271. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/local/test_registry.py +0 -0
  272. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/local/test_runner.py +0 -0
  273. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/__init__.py +0 -0
  274. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/options1.py +0 -0
  275. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/options2.py +0 -0
  276. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/options3.py +0 -0
  277. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/options4.py +0 -0
  278. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/options5.py +0 -0
  279. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/options6.py +0 -0
  280. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/scripts/options7.py +0 -0
  281. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_base_model.py +0 -0
  282. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_entrypoint/__init__.py +0 -0
  283. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_entrypoint/test_entrypoint.py +0 -0
  284. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_input.py +0 -0
  285. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_inputs/test_data.csv +0 -0
  286. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_inputs/test_data.json +0 -0
  287. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_inputs/test_data.txt +0 -0
  288. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_logger.py +0 -0
  289. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_model.py +0 -0
  290. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_options.py +0 -0
  291. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_output.py +0 -0
  292. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_polling.py +0 -0
  293. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_run.py +0 -0
  294. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_safe.py +0 -0
  295. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_serialization.py +0 -0
  296. {nextmv-1.1.3.dev2 → nextmv-1.2.0.dev1}/tests/test_version.py +0 -0
@@ -24,7 +24,7 @@ share/python-wheels/
24
24
  *.egg-info/
25
25
  .installed.cfg
26
26
  *.egg
27
- MANIFEST
27
+ # MANIFEST
28
28
 
29
29
  # PyInstaller
30
30
  # Usually these files are written by a python script from a template
@@ -1,9 +1,158 @@
1
- # Contributing to Nextmv CLI
1
+ # Contributing
2
2
 
3
- Hello dear contributor. Thank you for helping out with the CLI 😎. Here are a
4
- few style guidelines to help all of us maintain a high-quality tool, that feels
5
- unified and consistent. You are required to read and understand these
6
- guidelines before submitting a pull request.
3
+ Welcome to `nextmv`, the general Python SDK for the Nextmv Platform. Please
4
+ read this contributing guide to get set up before submitting a pull request.
5
+
6
+ We recommend you open _this_ directory in a standalone window of your editor.
7
+ From now on, all the commands assume that you are standing at the root of
8
+ _this_ library, i.e. the directory where the `pyproject.toml` file is located.
9
+
10
+ ## Prerequisites
11
+
12
+ Make sure you have the following installed:
13
+
14
+ - [Python][python]: Python 3.10 or higher.
15
+ - [`uv`][uv]: Python package and project manager.
16
+
17
+ ## Setup
18
+
19
+ Sync all the dependencies with:
20
+
21
+ ```bash
22
+ uv sync
23
+ ```
24
+
25
+ Repeat this command when there are changes to the `pyproject.toml` or `uv.lock`
26
+ files. Always commit changes to the `pyproject.toml` and `uv.lock` files.
27
+
28
+ ## Adding dependencies
29
+
30
+ - If you need to add a new dependency to the library, add it with:
31
+
32
+ ```bash
33
+ uv add <PACKAGE_NAME>
34
+ ```
35
+
36
+ - If you need to add a new _optional_ dependency to the library, add it with:
37
+
38
+ ```bash
39
+ uv add <PACKAGE_NAME> --optional <EXTRA_NAME>
40
+ ```
41
+
42
+ - If you need to add a _development_ dependency, i.e. a package that is only
43
+ needed for development and testing (like `Nextpipe`, which is used in the
44
+ integration tests), add it with:
45
+
46
+ ```bash
47
+ uv add <PACKAGE_NAME> --dev
48
+ ```
49
+
50
+ ## Linting
51
+
52
+ Run the linter with:
53
+
54
+ ```bash
55
+ uv run ruff check .
56
+ ```
57
+
58
+ ## Unit tests
59
+
60
+ Run unit tests with:
61
+
62
+ ```bash
63
+ uv run pytest --ignore=tests/integration
64
+ ```
65
+
66
+ This will ignore integration tests located in `tests/integration`.
67
+
68
+ ## Integration tests
69
+
70
+ Make sure you have a valid Nextmv Cloud API key set in your environment:
71
+
72
+ ```bash
73
+ export NEXTMV_API_KEY="<YOUR_API_KEY>"
74
+ ```
75
+
76
+ Run integration tests with:
77
+
78
+ ```bash
79
+ uv run pytest tests/integration -s
80
+ ```
81
+
82
+ The integration tests use [Nextpipe][nextpipe] to orchestrate a workflow of
83
+ steps that run both in sequence and in parallel. Here is a mermaid diagram of
84
+ the steps that are run in the integration tests. This diagram was generated at
85
+ the time of writing, and may change as the tests are updated.
86
+
87
+ ```mermaid
88
+ graph LR
89
+ init_app(init_app)
90
+ init_app --> community_push
91
+ init_app --> versions
92
+ init_app --> instances
93
+ init_app --> runs
94
+ init_app --> input_sets
95
+ init_app --> scenario_tests
96
+ init_app --> shadow_tests
97
+ init_app --> switchback_tests
98
+ init_app --> acceptance_tests
99
+ init_app --> secrets
100
+ init_app --> ensembles
101
+ init_app --> cleanup
102
+ community_push(community_push)
103
+ community_push --> versions
104
+ community_push --> secrets
105
+ versions(versions)
106
+ versions --> instances
107
+ versions --> cleanup
108
+ instances(instances)
109
+ instances --> runs
110
+ instances --> input_sets
111
+ instances --> scenario_tests
112
+ instances --> shadow_tests
113
+ instances --> switchback_tests
114
+ instances --> acceptance_tests
115
+ instances --> ensembles
116
+ instances --> cleanup
117
+ runs(runs)
118
+ runs --> input_sets
119
+ runs --> cleanup
120
+ input_sets(input_sets)
121
+ input_sets --> scenario_tests
122
+ input_sets --> acceptance_tests
123
+ input_sets --> cleanup
124
+ scenario_tests(scenario_tests)
125
+ scenario_tests --> cleanup
126
+ shadow_tests(shadow_tests)
127
+ shadow_tests --> switchback_tests
128
+ shadow_tests --> cleanup
129
+ switchback_tests(switchback_tests)
130
+ switchback_tests --> cleanup
131
+ acceptance_tests(acceptance_tests)
132
+ acceptance_tests --> cleanup
133
+ secrets(secrets)
134
+ secrets --> cleanup
135
+ ensembles(ensembles)
136
+ ensembles --> cleanup
137
+ cleanup(cleanup)
138
+ ```
139
+
140
+ ## CLI
141
+
142
+ Whenever you are contributing to the `./nextmv/cli` package, you can run the
143
+ `nextmv` command like this:
144
+
145
+ ```bash
146
+ uv run nextmv <COMMAND>
147
+ ```
148
+
149
+ This will allow you to directly test the changes you are making to the CLI.
150
+
151
+ ### CLI - Style guidelines
152
+
153
+ Here are a few style guidelines to help all of us maintain a high-quality tool,
154
+ that feels unified and consistent. You are required to read and understand
155
+ these guidelines before submitting a pull request.
7
156
 
8
157
  The Nextmv CLI is built using [Typer][typer]. If you don't know Typer, we
9
158
  _strongly encourage_ you to read through the [Typer Learn][typer-learn]
@@ -29,7 +178,7 @@ from the Typer docs:
29
178
  > The best results for your command line application would be achieved
30
179
  > combining both Typer and Rich.
31
180
 
32
- ## Command structure
181
+ #### CLI - Command structure
33
182
 
34
183
  The logic for command tree organization is based on:
35
184
 
@@ -67,7 +216,7 @@ Where:
67
216
  believe a different structure makes more sense, feel free to propose it in
68
217
  your pull request, explaining the reasoning behind it.
69
218
 
70
- ## File organization
219
+ #### CLI - File organization
71
220
 
72
221
  Follow these guidelines when organizing files and directories for commands:
73
222
 
@@ -142,7 +291,7 @@ Follow these guidelines when organizing files and directories for commands:
142
291
  pass
143
292
  ```
144
293
 
145
- ## Printing
294
+ #### CLI - Printing
146
295
 
147
296
  When information to the user, i.e., printing to the console, follow these
148
297
  guidelines:
@@ -160,6 +309,12 @@ guidelines:
160
309
  - `warning`: prints a warning message. Use for non-critical issues.
161
310
  - `error`: prints an error and raises an exception. Use for critical issues
162
311
  and to return early from commands.
312
+ - `confirmation`: prompts the user for a yes/no confirmation. Returns the
313
+ default value in non-interactive sessions.
314
+ - `choice`: prompts the user to select one option from a list of choices.
315
+ Returns the default value in non-interactive sessions.
316
+ - `directory_path`: prompts the user to enter or select a directory path.
317
+ Returns the default value in non-interactive sessions.
163
318
  - For printing `JSON` information, use the `print_json` function in the
164
319
  `message.py` file to print JSON output. This ensures consistent formatting
165
320
  across the CLI.
@@ -191,13 +346,20 @@ guidelines:
191
346
  ] = None,
192
347
  ```
193
348
 
194
- ## Confirmation prompts
349
+ #### CLI - User prompts
350
+
351
+ The `message.py` file provides three interactive prompt functions: `confirmation`,
352
+ `choice`, and `directory_path`. All three handle non-interactive sessions
353
+ gracefully by returning a default value when `stdin` is not a TTY, preventing
354
+ commands from hanging indefinitely.
355
+
356
+ ##### CLI - Confirmation
195
357
 
196
- For destructive actions (like deletions), use the `get_confirmation()` method
197
- to ask for user confirmation before proceeding. The method is available from
198
- the `cli/confirm.py` file. This method already handles sensible values used for
199
- getting a confirmation from a user. Additionally, it handles non-interactive
200
- sessions by defaulting to `False` if no input can be provided.
358
+ For destructive actions (like deletions), use the `confirmation()` function
359
+ from `message.py` to ask for user confirmation before proceeding. This function
360
+ already handles sensible values used for getting a confirmation from a user.
361
+ Additionally, it handles non-interactive sessions by defaulting to `False` if
362
+ no input can be provided.
201
363
 
202
364
  When using confirmation prompts, follow these guidelines:
203
365
 
@@ -211,7 +373,7 @@ Consider the `nextmv cloud app delete` command:
211
373
 
212
374
  ```python
213
375
  if not yes:
214
- confirm = get_confirmation(
376
+ confirm = confirmation(
215
377
  f"Are you sure you want to delete application [magenta]{app_id}[/magenta]? This action cannot be undone.",
216
378
  )
217
379
 
@@ -220,7 +382,35 @@ if not yes:
220
382
  return
221
383
  ```
222
384
 
223
- ## Formatting, colors, and styles
385
+ ##### CLI - Choice
386
+
387
+ Use the `choice()` function when the user must select one option from a
388
+ predefined list. It renders an interactive selection menu and returns the chosen
389
+ value. In non-interactive sessions, the `default` value is returned instead.
390
+
391
+ ```python
392
+ selected = choice(
393
+ "Select an instance to use:",
394
+ choices=["instance-a", "instance-b", "instance-c"],
395
+ default="instance-a",
396
+ )
397
+ ```
398
+
399
+ ##### CLI - Directory path
400
+
401
+ Use the `directory_path()` function when the user must provide or confirm a
402
+ directory path. It renders an interactive path-completion prompt restricted to
403
+ directories. In non-interactive sessions, the `default` value is returned
404
+ instead.
405
+
406
+ ```python
407
+ dirpath = directory_path(
408
+ "Select the output directory:",
409
+ default="./output",
410
+ )
411
+ ```
412
+
413
+ #### CLI - Formatting, colors, and styles
224
414
 
225
415
  Use these Rich markup colors/styles when formatting help text and messages.
226
416
  These are the main colors/styles that can be used for highlighting/contrast (we
@@ -343,7 +533,7 @@ Here are some guidelines for when to use each formatting style.
343
533
  The link provided is <https://github.com/nextmv-io/community-apps>, and it will
344
534
  be applied to the text `nextmv-io/community-apps`.
345
535
 
346
- ## Command documentation
536
+ #### CLI - Command documentation
347
537
 
348
538
  Every command should have good-enough documentation that guides the user on how
349
539
  to use it.
@@ -442,7 +632,7 @@ to use it.
442
632
  --description "An application for routing hares"[/dim]
443
633
  ```
444
634
 
445
- ## Command options
635
+ #### CLI - Command options
446
636
 
447
637
  Consider the following guideline when declaring command options:
448
638
 
@@ -577,6 +767,9 @@ Consider the following guideline when declaring command options:
577
767
  should always be the last option in the command's signature, for consistency
578
768
  across the CLI.
579
769
 
770
+ [uv]: https://docs.astral.sh/uv/
771
+ [python]: https://www.python.org/downloads/
772
+ [nextpipe]: https://github.com/nextmv-io/nextpipe
580
773
  [typer]: https://typer.tiangolo.com
581
774
  [typer-learn]: https://typer.tiangolo.com/tutorial/
582
775
  [rich]: https://rich.readthedocs.io/en/stable/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextmv
3
- Version: 1.1.3.dev2
3
+ Version: 1.2.0.dev1
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/
@@ -223,15 +223,10 @@ Requires-Dist: pip>=26.0
223
223
  Requires-Dist: plotly>=6.0.1
224
224
  Requires-Dist: pydantic>=2.5.2
225
225
  Requires-Dist: pyyaml>=6.0.1
226
+ Requires-Dist: questionary>=2.1.1
226
227
  Requires-Dist: requests>=2.31.0
227
228
  Requires-Dist: typer>=0.20.1
228
229
  Requires-Dist: urllib3>=2.1.0
229
- Provides-Extra: all
230
- Requires-Dist: folium>=0.20.0; extra == 'all'
231
- Requires-Dist: mcp[cli]>=1.0; extra == 'all'
232
- Requires-Dist: plotly>=6.0.1; extra == 'all'
233
- Provides-Extra: mcp
234
- Requires-Dist: mcp[cli]>=1.0; extra == 'mcp'
235
230
  Provides-Extra: notebook
236
231
  Requires-Dist: mlflow>=3.9.0; extra == 'notebook'
237
232
  Description-Content-Type: text/markdown
@@ -0,0 +1 @@
1
+ __version__ = "v1.2.0.dev1"
@@ -3,6 +3,7 @@
3
3
  from .__about__ import __version__
4
4
  from .base_model import BaseModel as BaseModel
5
5
  from .base_model import from_dict as from_dict
6
+ from .content_format import ContentFormat as ContentFormat
6
7
  from .input import DataFile as DataFile
7
8
  from .input import Input as Input
8
9
  from .input import InputFormat as InputFormat
@@ -27,6 +28,7 @@ from .manifest import ManifestRuntime as ManifestRuntime
27
28
  from .manifest import ManifestType as ManifestType
28
29
  from .manifest import default_python_manifest as default_python_manifest
29
30
  from .manifest import find_files as find_files
31
+ from .manifest import initialize_manifest as initialize_manifest
30
32
  from .model import Model as Model
31
33
  from .model import ModelConfiguration as ModelConfiguration
32
34
  from .options import Option as Option
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AcceptanceTestIDOption, AppIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -47,7 +46,7 @@ def delete(
47
46
  """
48
47
 
49
48
  if not yes:
50
- confirm = get_confirmation(
49
+ confirm = confirmation(
51
50
  f"Are you sure you want to delete acceptance test [magenta]{acceptance_test_id}[/magenta] "
52
51
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
53
52
  )
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_account
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AccountIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -46,7 +45,7 @@ def delete(
46
45
  """
47
46
 
48
47
  if not yes:
49
- confirm = get_confirmation(
48
+ confirm = confirmation(
50
49
  f"Are you sure you want to delete account [magenta]{account_id}[/magenta]? This action cannot be undone.",
51
50
  )
52
51
 
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AppIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -44,7 +43,7 @@ def delete(
44
43
  """
45
44
 
46
45
  if not yes:
47
- confirm = get_confirmation(
46
+ confirm = confirmation(
48
47
  f"Are you sure you want to delete application [magenta]{app_id}[/magenta]? This action cannot be undone.",
49
48
  )
50
49
 
@@ -10,8 +10,7 @@ import typer
10
10
  from rich.prompt import Prompt
11
11
 
12
12
  from nextmv.cli.configuration.config import build_cloud_app
13
- from nextmv.cli.confirm import get_confirmation
14
- from nextmv.cli.message import error, in_progress, info, success
13
+ from nextmv.cli.message import confirmation, error, in_progress, info, success
15
14
  from nextmv.cli.options import AppIDOption, ProfileOption
16
15
  from nextmv.cloud.application import Application
17
16
  from nextmv.manifest import Manifest
@@ -256,7 +255,7 @@ def _handle_version_creation(
256
255
 
257
256
  # If we are not auto-confirming version creation, ask the user.
258
257
  if not version_yes:
259
- should_create = get_confirmation(
258
+ should_create = confirmation(
260
259
  msg=f"Do you want to create a new version for application [magenta]{app_id}[/magenta] now?",
261
260
  default=True,
262
261
  )
@@ -327,7 +326,7 @@ def _handle_instance_prompting(
327
326
 
328
327
  # If the instance exists, ask if we want to update it.
329
328
  if exists:
330
- should_update = get_confirmation(
329
+ should_update = confirmation(
331
330
  msg=f"Instance [magenta]{instance_id}[/magenta] exists. "
332
331
  f"Do you want to link it to version [magenta]{version_id}[/magenta]?",
333
332
  default=True,
@@ -347,7 +346,7 @@ def _handle_instance_prompting(
347
346
  return
348
347
 
349
348
  # If the instance does not exist, ask if we want to create it.
350
- should_create = get_confirmation(
349
+ should_create = confirmation(
351
350
  msg=f"Instance [magenta]{instance_id}[/magenta] does not exist. "
352
351
  f"Do you want to create it using version [magenta]{version_id}[/magenta]?",
353
352
  default=True,
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AppIDOption, BatchExperimentIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -47,7 +46,7 @@ def delete(
47
46
  """
48
47
 
49
48
  if not yes:
50
- confirm = get_confirmation(
49
+ confirm = confirmation(
51
50
  f"Are you sure you want to delete batch experiment [magenta]{batch_experiment_id}[/magenta] "
52
51
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
53
52
  )
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AppIDOption, EnsembleDefinitionIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -46,7 +45,7 @@ def delete(
46
45
  """
47
46
 
48
47
  if not yes:
49
- confirm = get_confirmation(
48
+ confirm = confirmation(
50
49
  f"Are you sure you want to delete ensemble definition [magenta]{ensemble_definition_id}[/magenta] "
51
50
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
52
51
  )
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AppIDOption, InputSetIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -47,7 +46,7 @@ def delete(
47
46
  """
48
47
 
49
48
  if not yes:
50
- confirm = get_confirmation(
49
+ confirm = confirmation(
51
50
  f"Are you sure you want to delete input set [magenta]{input_set_id}[/magenta] "
52
51
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
53
52
  )
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AppIDOption, InstanceIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -45,7 +44,7 @@ def delete(
45
44
  """
46
45
 
47
46
  if not yes:
48
- confirm = get_confirmation(
47
+ confirm = confirmation(
49
48
  f"Are you sure you want to delete instance [magenta]{instance_id}[/magenta] "
50
49
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
51
50
  )
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AppIDOption, ManagedInputIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -47,7 +46,7 @@ def delete(
47
46
  """
48
47
 
49
48
  if not yes:
50
- confirm = get_confirmation(
49
+ confirm = confirmation(
51
50
  f"Are you sure you want to delete managed input [magenta]{managed_input_id}[/magenta] "
52
51
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
53
52
  )
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_marketplace_subscription
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import MarketplaceSubscriptionIDOption, ProfileOption
13
12
 
14
13
  # Set up subcommand application.
@@ -44,7 +43,7 @@ def delete(
44
43
  """
45
44
 
46
45
  if not yes:
47
- confirm = get_confirmation(
46
+ confirm = confirmation(
48
47
  f"Are you sure you want to delete subscription with ID [magenta]{subscription_id}[/magenta]?",
49
48
  )
50
49
 
@@ -40,6 +40,17 @@ def create(
40
40
  rich_help_panel="Input control",
41
41
  ),
42
42
  ] = None,
43
+ managed_input_id: Annotated[
44
+ str | None,
45
+ typer.Option(
46
+ "--managed-input-id",
47
+ "-m",
48
+ help="The Nextmv Cloud managed input ID to use as the input for the run.",
49
+ envvar="NEXTMV_MANAGED_INPUT_ID",
50
+ metavar="MANAGED_INPUT_ID",
51
+ rich_help_panel="Input control",
52
+ ),
53
+ ] = None,
43
54
  # Options for controlling output.
44
55
  logs: Annotated[
45
56
  str | None,
@@ -209,9 +220,9 @@ def create(
209
220
  """
210
221
  Create a new Nextmv Cloud application run.
211
222
 
212
- Input for the run should be given through [magenta]stdin[/magenta] or the
213
- --input flag. When using the --input flag, the value can be one of the
214
- following:
223
+ Input for the run should be given through [magenta]stdin[/magenta], the --input flag,
224
+ or a Nextmv managed input by passing its ID into the --managed-input-id flag.
225
+ When using the --input flag, the value can be one of the following:
215
226
 
216
227
  - [yellow]<FILE_PATH>[/yellow]: path to a [magenta]file[/magenta] containing
217
228
  the input data. Use with the [magenta]json[/magenta], and
@@ -297,12 +308,17 @@ def create(
297
308
  submit a run to an app with ID [magenta]hare-app[/magenta], using the [magenta]burrow[/magenta] instance.
298
309
  Wait for the run to complete and download the result files to an [magenta]outputs[/magenta] directory.
299
310
  $ [dim]nextmv cloud run create --app-id hare-app --input inputs --instance-id burrow --output outputs[/dim]
311
+
312
+ - Set the run to use a [magenta]Nextmv managed[/magenta] input with ID [magenta]carrot-input[/magenta],
313
+ and submit a run to an app with ID [magenta]hare-app[/magenta], using the [magenta]latest[/magenta] instance.
314
+ Wait for the run to complete and download the result files to an [magenta]outputs[/magenta] directory.
315
+ $ [dim]nextmv cloud run create --app-id hare-app --managed-input-id carrot-input --output outputs[/dim]
300
316
  """
301
317
 
302
318
  # Validate that input is provided.
303
319
  stdin = sys.stdin.read().strip() if sys.stdin.isatty() is False else None
304
- if stdin is None and (input is None or input == ""):
305
- error("Input data must be provided via the --input flag or [magenta]stdin[/magenta].")
320
+ if stdin is None and (input is None or input == "") and (managed_input_id is None or managed_input_id == ""):
321
+ error("Input data must be provided via the --input or --managed_input_id flags, or [magenta]stdin[/magenta].")
306
322
 
307
323
  # Instantiate the basic requirements to start a new run.
308
324
  cloud_app = build_cloud_app(app_id=app_id, profile=profile)
@@ -322,6 +338,7 @@ def create(
322
338
  input_kwarg = resolve_input_kwarg(
323
339
  stdin=stdin,
324
340
  input=input,
341
+ managed_input_id=managed_input_id,
325
342
  cloud_app=cloud_app,
326
343
  )
327
344
  run_id = cloud_app.new_run(
@@ -470,6 +487,7 @@ def build_run_options(options: list[str] | None) -> dict[str, str]:
470
487
  def resolve_input_kwarg(
471
488
  stdin: str | None,
472
489
  input: str | None,
490
+ managed_input_id: str | None,
473
491
  cloud_app: Application,
474
492
  ) -> dict[str, Any]:
475
493
  """
@@ -501,6 +519,9 @@ def resolve_input_kwarg(
501
519
 
502
520
  return {"input": input_data}
503
521
 
522
+ if managed_input_id is not None and managed_input_id != "":
523
+ return {"managed_input_id": managed_input_id}
524
+
504
525
  input_path = Path(input)
505
526
 
506
527
  # If the input is a file, we need to determine if it is a tar file or
@@ -7,8 +7,7 @@ from typing import Annotated
7
7
  import typer
8
8
 
9
9
  from nextmv.cli.configuration.config import build_cloud_app
10
- from nextmv.cli.confirm import get_confirmation
11
- from nextmv.cli.message import info, success
10
+ from nextmv.cli.message import confirmation, info, success
12
11
  from nextmv.cli.options import AppIDOption, ProfileOption, ScenarioTestIDOption
13
12
 
14
13
  # Set up subcommand application.
@@ -47,7 +46,7 @@ def delete(
47
46
  """
48
47
 
49
48
  if not yes:
50
- confirm = get_confirmation(
49
+ confirm = confirmation(
51
50
  f"Are you sure you want to delete scenario test [magenta]{scenario_test_id}[/magenta] "
52
51
  f"from application [magenta]{app_id}[/magenta]? This action cannot be undone.",
53
52
  )