nextmv 1.7.2__tar.gz → 1.7.3.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 (391) hide show
  1. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/PKG-INFO +1 -1
  2. nextmv-1.7.3.dev0/nextmv/__about__.py +1 -0
  3. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/init.py +22 -5
  4. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/package.py +2 -0
  5. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/executor.py +19 -14
  6. nextmv-1.7.3.dev0/tests/cli/test_init_cli_call.py +109 -0
  7. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/local/test_executor.py +115 -0
  8. nextmv-1.7.2/nextmv/__about__.py +0 -1
  9. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/.gitignore +0 -0
  10. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/.python-version +0 -0
  11. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/CONTRIBUTING.md +0 -0
  12. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/LICENSE +0 -0
  13. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/README.md +0 -0
  14. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/__entrypoint__.py +0 -0
  15. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/__init__.py +0 -0
  16. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/_serialization.py +0 -0
  17. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/account.py +0 -0
  18. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/base_model.py +0 -0
  19. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/__init__.py +0 -0
  20. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/__init__.py +0 -0
  21. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/acceptance/__init__.py +0 -0
  22. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/acceptance/create.py +0 -0
  23. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/acceptance/delete.py +0 -0
  24. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/acceptance/get.py +0 -0
  25. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/acceptance/list.py +0 -0
  26. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/acceptance/update.py +0 -0
  27. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/account/__init__.py +0 -0
  28. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/account/create.py +0 -0
  29. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/account/delete.py +0 -0
  30. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/account/get.py +0 -0
  31. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/account/update.py +0 -0
  32. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/__init__.py +0 -0
  33. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/create.py +0 -0
  34. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/delete.py +0 -0
  35. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/exists.py +0 -0
  36. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/get.py +0 -0
  37. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/list.py +0 -0
  38. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/push.py +0 -0
  39. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/app/update.py +0 -0
  40. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/batch/__init__.py +0 -0
  41. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/batch/create.py +0 -0
  42. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/batch/delete.py +0 -0
  43. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/batch/get.py +0 -0
  44. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/batch/list.py +0 -0
  45. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/batch/metadata.py +0 -0
  46. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/batch/update.py +0 -0
  47. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/data/__init__.py +0 -0
  48. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/data/upload.py +0 -0
  49. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/ensemble/__init__.py +0 -0
  50. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/ensemble/create.py +0 -0
  51. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/ensemble/delete.py +0 -0
  52. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/ensemble/get.py +0 -0
  53. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/ensemble/list.py +0 -0
  54. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/ensemble/update.py +0 -0
  55. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/input_set/__init__.py +0 -0
  56. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/input_set/create.py +0 -0
  57. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/input_set/delete.py +0 -0
  58. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/input_set/get.py +0 -0
  59. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/input_set/list.py +0 -0
  60. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/input_set/update.py +0 -0
  61. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/instance/__init__.py +0 -0
  62. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/instance/create.py +0 -0
  63. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/instance/delete.py +0 -0
  64. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/instance/exists.py +0 -0
  65. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/instance/get.py +0 -0
  66. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/instance/list.py +0 -0
  67. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/instance/update.py +0 -0
  68. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/managed_input/__init__.py +0 -0
  69. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/managed_input/create.py +0 -0
  70. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/managed_input/delete.py +0 -0
  71. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/managed_input/get.py +0 -0
  72. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/managed_input/list.py +0 -0
  73. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/managed_input/update.py +0 -0
  74. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/__init__.py +0 -0
  75. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/app/__init__.py +0 -0
  76. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/app/create.py +0 -0
  77. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/app/get.py +0 -0
  78. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/app/list.py +0 -0
  79. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/app/update.py +0 -0
  80. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/subscription/__init__.py +0 -0
  81. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/subscription/create.py +0 -0
  82. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/subscription/delete.py +0 -0
  83. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/subscription/get.py +0 -0
  84. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/subscription/list.py +0 -0
  85. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/version/__init__.py +0 -0
  86. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/version/create.py +0 -0
  87. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/version/get.py +0 -0
  88. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/version/list.py +0 -0
  89. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/marketplace/version/update.py +0 -0
  90. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/__init__.py +0 -0
  91. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/cancel.py +0 -0
  92. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/create.py +0 -0
  93. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/delete.py +0 -0
  94. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/get.py +0 -0
  95. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/input.py +0 -0
  96. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/list.py +0 -0
  97. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/logs.py +0 -0
  98. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/metadata.py +0 -0
  99. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/run/track.py +0 -0
  100. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/scenario/__init__.py +0 -0
  101. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/scenario/create.py +0 -0
  102. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/scenario/delete.py +0 -0
  103. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/scenario/get.py +0 -0
  104. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/scenario/list.py +0 -0
  105. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/scenario/metadata.py +0 -0
  106. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/scenario/update.py +0 -0
  107. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/secrets/__init__.py +0 -0
  108. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/secrets/create.py +0 -0
  109. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/secrets/delete.py +0 -0
  110. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/secrets/get.py +0 -0
  111. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/secrets/list.py +0 -0
  112. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/secrets/update.py +0 -0
  113. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/__init__.py +0 -0
  114. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/create.py +0 -0
  115. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/delete.py +0 -0
  116. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/get.py +0 -0
  117. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/list.py +0 -0
  118. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/metadata.py +0 -0
  119. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/start.py +0 -0
  120. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/stop.py +0 -0
  121. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/shadow/update.py +0 -0
  122. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/__init__.py +0 -0
  123. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/create.py +0 -0
  124. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/delete.py +0 -0
  125. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/disable.py +0 -0
  126. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/domain/__init__.py +0 -0
  127. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/domain/delete.py +0 -0
  128. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/enable.py +0 -0
  129. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/get.py +0 -0
  130. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/sso/update.py +0 -0
  131. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/__init__.py +0 -0
  132. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/create.py +0 -0
  133. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/delete.py +0 -0
  134. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/get.py +0 -0
  135. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/list.py +0 -0
  136. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/metadata.py +0 -0
  137. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/start.py +0 -0
  138. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/stop.py +0 -0
  139. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/switchback/update.py +0 -0
  140. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/upload/__init__.py +0 -0
  141. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/upload/create.py +0 -0
  142. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/version/__init__.py +0 -0
  143. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/version/create.py +0 -0
  144. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/version/delete.py +0 -0
  145. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/version/exists.py +0 -0
  146. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/version/get.py +0 -0
  147. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/version/list.py +0 -0
  148. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/cloud/version/update.py +0 -0
  149. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/community/__init__.py +0 -0
  150. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/community/clone.py +0 -0
  151. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/community/list.py +0 -0
  152. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/configuration/__init__.py +0 -0
  153. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/configuration/config.py +0 -0
  154. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/configuration/create.py +0 -0
  155. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/configuration/delete.py +0 -0
  156. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/configuration/list.py +0 -0
  157. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/__init__.py +0 -0
  158. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/__init__.py +0 -0
  159. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/delete.py +0 -0
  160. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/get.py +0 -0
  161. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/list.py +0 -0
  162. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/register.py +0 -0
  163. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/registered.py +0 -0
  164. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/sync.py +0 -0
  165. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/app/update.py +0 -0
  166. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/__init__.py +0 -0
  167. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/create.py +0 -0
  168. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/get.py +0 -0
  169. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/input.py +0 -0
  170. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/list.py +0 -0
  171. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/logs.py +0 -0
  172. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/metadata.py +0 -0
  173. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/local/run/visuals.py +0 -0
  174. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/main.py +0 -0
  175. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/manifest/__init__.py +0 -0
  176. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/manifest/init.py +0 -0
  177. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/manifest/validate.py +0 -0
  178. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/__init__.py +0 -0
  179. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/serve.py +0 -0
  180. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/server.py +0 -0
  181. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/WORKFLOW.md +0 -0
  182. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/__init__.py +0 -0
  183. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/_helpers.py +0 -0
  184. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/acceptance.py +0 -0
  185. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/account.py +0 -0
  186. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/app.py +0 -0
  187. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/batch.py +0 -0
  188. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/community.py +0 -0
  189. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/ensemble.py +0 -0
  190. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/guide.py +0 -0
  191. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/input_set.py +0 -0
  192. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/instance.py +0 -0
  193. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/local.py +0 -0
  194. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/managed_input.py +0 -0
  195. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/profile.py +0 -0
  196. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/run.py +0 -0
  197. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/scenario.py +0 -0
  198. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/secrets.py +0 -0
  199. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/shadow.py +0 -0
  200. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/sso.py +0 -0
  201. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/switchback.py +0 -0
  202. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/mcp/tools/version.py +0 -0
  203. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/message.py +0 -0
  204. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/options.py +0 -0
  205. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cli/version.py +0 -0
  206. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/__init__.py +0 -0
  207. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/acceptance_test.py +0 -0
  208. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/account.py +0 -0
  209. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/__init__.py +0 -0
  210. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_acceptance.py +0 -0
  211. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_batch_scenario.py +0 -0
  212. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_ensemble.py +0 -0
  213. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_input_set.py +0 -0
  214. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_instance.py +0 -0
  215. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_managed_input.py +0 -0
  216. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_run.py +0 -0
  217. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_secrets.py +0 -0
  218. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_shadow.py +0 -0
  219. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_switchback.py +0 -0
  220. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_utils.py +0 -0
  221. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/application/_version.py +0 -0
  222. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/assets.py +0 -0
  223. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/batch_experiment.py +0 -0
  224. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/client.py +0 -0
  225. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/community.py +0 -0
  226. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/ensemble.py +0 -0
  227. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/input_set.py +0 -0
  228. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/instance.py +0 -0
  229. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/integration.py +0 -0
  230. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/marketplace.py +0 -0
  231. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/scenario.py +0 -0
  232. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/secrets.py +0 -0
  233. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/shadow.py +0 -0
  234. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/sso.py +0 -0
  235. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/switchback.py +0 -0
  236. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/url.py +0 -0
  237. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/cloud/version.py +0 -0
  238. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/content_format.py +0 -0
  239. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/deprecated.py +0 -0
  240. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/input.py +0 -0
  241. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/__init__.py +0 -0
  242. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/application.py +0 -0
  243. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/geojson_handler.py +0 -0
  244. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/local.py +0 -0
  245. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/plotly_handler.py +0 -0
  246. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/registry.py +0 -0
  247. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/runner.py +0 -0
  248. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/local/uv_handler.py +0 -0
  249. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/logger.py +0 -0
  250. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/manifest.py +0 -0
  251. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/model.py +0 -0
  252. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/options.py +0 -0
  253. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/output.py +0 -0
  254. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/polling.py +0 -0
  255. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/run.py +0 -0
  256. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/safe.py +0 -0
  257. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/status.py +0 -0
  258. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/binary_json_app.yaml +0 -0
  259. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/binary_multi-file_app.yaml +0 -0
  260. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_json_app.yaml +0 -0
  261. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_json_hello-world/.gitignore +0 -0
  262. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_json_hello-world/README.md +0 -0
  263. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_json_hello-world/app.yaml +0 -0
  264. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_json_hello-world/go.mod +0 -0
  265. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_json_hello-world/input.json +0 -0
  266. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_json_hello-world/main.go +0 -0
  267. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_multi-file_app.yaml +0 -0
  268. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_multi-file_hello-world/.gitignore +0 -0
  269. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_multi-file_hello-world/README.md +0 -0
  270. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_multi-file_hello-world/app.yaml +0 -0
  271. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_multi-file_hello-world/go.mod +0 -0
  272. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_multi-file_hello-world/inputs/input.json +0 -0
  273. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/go_multi-file_hello-world/main.go +0 -0
  274. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_json_app.yaml +0 -0
  275. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_json_hello-world/.gitignore +0 -0
  276. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_json_hello-world/Main.java +0 -0
  277. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_json_hello-world/README.md +0 -0
  278. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_json_hello-world/app.yaml +0 -0
  279. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_json_hello-world/input.json +0 -0
  280. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_json_hello-world/pom.xml +0 -0
  281. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_multi-file_app.yaml +0 -0
  282. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_multi-file_hello-world/.gitignore +0 -0
  283. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_multi-file_hello-world/Main.java +0 -0
  284. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_multi-file_hello-world/README.md +0 -0
  285. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_multi-file_hello-world/app.yaml +0 -0
  286. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_multi-file_hello-world/inputs/input.json +0 -0
  287. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/java_multi-file_hello-world/pom.xml +0 -0
  288. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_app.yaml +0 -0
  289. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_class-assign/.gitignore +0 -0
  290. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_class-assign/README.md +0 -0
  291. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_class-assign/app.yaml +0 -0
  292. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_class-assign/input.json +0 -0
  293. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_class-assign/main.py +0 -0
  294. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_class-assign/requirements.txt +0 -0
  295. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_class-assign/visualizations.py +0 -0
  296. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/.gitignore +0 -0
  297. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/README.md +0 -0
  298. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/allocation/README.md +0 -0
  299. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/allocation/app.yaml +0 -0
  300. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/allocation/input.json +0 -0
  301. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/allocation/main.py +0 -0
  302. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/allocation/requirements.txt +0 -0
  303. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/allocation/visuals.py +0 -0
  304. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/workflow/README.md +0 -0
  305. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/workflow/app.yaml +0 -0
  306. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/workflow/input.json +0 -0
  307. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/workflow/main.py +0 -0
  308. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/workflow/requirements.txt +0 -0
  309. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_demand-alloc/workflow/visuals.py +0 -0
  310. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_hello-world/.gitignore +0 -0
  311. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_hello-world/README.md +0 -0
  312. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_hello-world/app.yaml +0 -0
  313. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_hello-world/input.json +0 -0
  314. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_hello-world/main.py +0 -0
  315. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_json_hello-world/requirements.txt +0 -0
  316. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_app.yaml +0 -0
  317. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_class-assign/.gitignore +0 -0
  318. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_class-assign/README.md +0 -0
  319. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_class-assign/app.yaml +0 -0
  320. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_class-assign/inputs/input.json +0 -0
  321. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_class-assign/main.py +0 -0
  322. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_class-assign/requirements.txt +0 -0
  323. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_class-assign/visualizations.py +0 -0
  324. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/README.md +0 -0
  325. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/README.md +0 -0
  326. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/app.yaml +0 -0
  327. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/input.json +0 -0
  328. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/main.py +0 -0
  329. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/requirements.txt +0 -0
  330. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/allocation/visuals.py +0 -0
  331. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/.gitignore +0 -0
  332. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/README.md +0 -0
  333. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/app.yaml +0 -0
  334. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/inputs/input.json +0 -0
  335. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/main.py +0 -0
  336. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/requirements.txt +0 -0
  337. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_demand-alloc/workflow/visuals.py +0 -0
  338. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_hello-world/.gitignore +0 -0
  339. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_hello-world/README.md +0 -0
  340. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_hello-world/app.yaml +0 -0
  341. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_hello-world/inputs/input.json +0 -0
  342. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_hello-world/main.py +0 -0
  343. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/nextmv/templates/python_multi-file_hello-world/requirements.txt +0 -0
  344. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/pyproject.toml +0 -0
  345. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/__init__.py +0 -0
  346. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cli/__init__.py +0 -0
  347. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cli/test_configuration.py +0 -0
  348. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cli/test_main.py +0 -0
  349. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cli/test_mcp.py +0 -0
  350. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cli/test_version.py +0 -0
  351. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cloud/__init__.py +0 -0
  352. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cloud/app.yaml +0 -0
  353. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cloud/test_client.py +0 -0
  354. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cloud/test_instance.py +0 -0
  355. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cloud/test_package.py +0 -0
  356. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/cloud/test_scenario.py +0 -0
  357. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/integration/__init__.py +0 -0
  358. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/integration/cloud/__init__.py +0 -0
  359. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/integration/cloud/test_integration_cloud.py +0 -0
  360. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/integration/cloud/test_integration_marketplace.py +0 -0
  361. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/local/__init__.py +0 -0
  362. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/local/test_application.py +0 -0
  363. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/local/test_registry.py +0 -0
  364. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/local/test_runner.py +0 -0
  365. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/local/test_uv_handler.py +0 -0
  366. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/__init__.py +0 -0
  367. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/options1.py +0 -0
  368. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/options2.py +0 -0
  369. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/options3.py +0 -0
  370. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/options4.py +0 -0
  371. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/options5.py +0 -0
  372. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/options6.py +0 -0
  373. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/scripts/options7.py +0 -0
  374. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_base_model.py +0 -0
  375. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_entrypoint/__init__.py +0 -0
  376. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_entrypoint/test_entrypoint.py +0 -0
  377. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_input.py +0 -0
  378. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_inputs/test_data.csv +0 -0
  379. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_inputs/test_data.json +0 -0
  380. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_inputs/test_data.txt +0 -0
  381. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_logger.py +0 -0
  382. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_manifest.py +0 -0
  383. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_model.py +0 -0
  384. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_options.py +0 -0
  385. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_output.py +0 -0
  386. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_polling.py +0 -0
  387. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_run.py +0 -0
  388. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_safe.py +0 -0
  389. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_serialization.py +0 -0
  390. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/tests/test_version.py +0 -0
  391. {nextmv-1.7.2 → nextmv-1.7.3.dev0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextmv
3
- Version: 1.7.2
3
+ Version: 1.7.3.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.7.3.dev0"
@@ -927,26 +927,38 @@ def _cli_call(command: list[str]) -> subprocess.CompletedProcess:
927
927
  """
928
928
 
929
929
  try:
930
+ # Use binary mode so we can apply different decoding strategies to each
931
+ # stream: stdout is machine-readable (JSON) and must be decoded strictly
932
+ # so corruption surfaces as a clear UnicodeDecodeError rather than a
933
+ # confusing JSONDecodeError; stderr is human-facing and uses
934
+ # errors="replace" so stray non-UTF-8 bytes (common on Windows with
935
+ # codepage cp1252) never crash the thread.
930
936
  process = subprocess.Popen(
931
937
  command,
932
938
  env=os.environ,
933
- text=True,
934
939
  stdout=subprocess.PIPE,
935
940
  stderr=subprocess.PIPE,
936
941
  )
937
942
 
938
943
  stdout_lines = []
939
944
  stderr_lines = []
945
+ stdout_exc: list[BaseException] = []
940
946
 
941
947
  def stream_stderr():
942
- for line in process.stderr:
948
+ for raw_line in process.stderr:
949
+ line = raw_line.decode("utf-8", errors="replace")
943
950
  rich.print(line, end="", file=sys.stderr)
944
951
  stderr_lines.append(line)
945
952
 
946
953
  def stream_stdout():
947
- for line in process.stdout:
948
- rich.print(line, end="")
949
- stdout_lines.append(line)
954
+ try:
955
+ for raw_line in process.stdout:
956
+ line = raw_line.decode("utf-8")
957
+ rich.print(line, end="")
958
+ stdout_lines.append(line)
959
+ except Exception as exc:
960
+ # Capture so we can re-raise on the main thread after joining.
961
+ stdout_exc.append(exc)
950
962
 
951
963
  # Use threads to read both streams concurrently without deadlocking
952
964
  stderr_thread = threading.Thread(target=stream_stderr)
@@ -959,6 +971,11 @@ def _cli_call(command: list[str]) -> subprocess.CompletedProcess:
959
971
  stdout_thread.join()
960
972
  process.wait()
961
973
 
974
+ # Re-raise any decoding error from stdout on the calling thread so it
975
+ # surfaces as a clear UnicodeDecodeError rather than being swallowed.
976
+ if stdout_exc:
977
+ raise stdout_exc[0]
978
+
962
979
  result = subprocess.CompletedProcess(
963
980
  args=command,
964
981
  returncode=process.returncode,
@@ -325,6 +325,8 @@ def __run_command(binary: str, dir: str, redirect_out_err: bool, *arguments: str
325
325
  stdout=subprocess.PIPE if redirect_out_err else None,
326
326
  stderr=subprocess.PIPE if redirect_out_err else None,
327
327
  text=True,
328
+ encoding="utf-8",
329
+ errors="replace",
328
330
  )
329
331
 
330
332
  if redirect_out_err:
@@ -146,7 +146,7 @@ def execute_run(
146
146
 
147
147
  # Set the run status to running.
148
148
  info_file = os.path.join(run_dir, f"{run_id}.json")
149
- with open(info_file, "r+") as f:
149
+ with open(info_file, "r+", encoding="utf-8") as f:
150
150
  info = json.load(f)
151
151
  info["metadata"]["status_v2"] = "running"
152
152
  f.seek(0)
@@ -173,9 +173,12 @@ def execute_run(
173
173
  stderr_lines: list[str] = []
174
174
 
175
175
  # Force unbuffered stdout/stderr in child processes so both
176
- # streams are written to the log file in real time.
176
+ # streams are written to the log file in real time. Also force
177
+ # UTF-8 encoding for all stdio so Windows codepage mismatches
178
+ # (e.g. cp1252) do not cause UnicodeDecodeError.
177
179
  child_env = os.environ.copy()
178
180
  child_env["PYTHONUNBUFFERED"] = "1"
181
+ child_env["PYTHONIOENCODING"] = "utf-8"
179
182
 
180
183
  # This is the process that actually executes the entrypoint script.
181
184
  # We use subprocess.Popen instead of subprocess.run because we need
@@ -185,6 +188,8 @@ def execute_run(
185
188
  args,
186
189
  env=child_env,
187
190
  text=True,
191
+ encoding="utf-8",
192
+ errors="replace",
188
193
  stdin=subprocess.PIPE,
189
194
  stdout=subprocess.PIPE,
190
195
  stderr=subprocess.PIPE,
@@ -199,7 +204,7 @@ def execute_run(
199
204
  # A lock to serialize writes from the stdout and stderr threads so log
200
205
  # lines are never interleaved in the log file.
201
206
  log_lock = threading.Lock()
202
- log_f = open(log_file_path, "a")
207
+ log_f = open(log_file_path, "a", encoding="utf-8")
203
208
 
204
209
  def stream_stderr() -> None:
205
210
  # Stderr is always streamed live to the log file so errors appear
@@ -263,12 +268,12 @@ def execute_run(
263
268
 
264
269
  except Exception as e:
265
270
  # If we encounter an exception, we log it to the stderr log file.
266
- with open(os.path.join(logs_dir, LOGS_FILE), "a") as f:
271
+ with open(os.path.join(logs_dir, LOGS_FILE), "a", encoding="utf-8") as f:
267
272
  f.write(f"\nException during run execution: {str(e)}\n")
268
273
 
269
274
  # Also, we update the run information file to set the status to failed.
270
275
  info_file = os.path.join(run_dir, f"{run_id}.json")
271
- with open(info_file, "r+") as f:
276
+ with open(info_file, "r+", encoding="utf-8") as f:
272
277
  info = json.load(f)
273
278
  info["metadata"]["status_v2"] = "failed"
274
279
  info["metadata"]["error"] = "Run failed, please check logs for details."
@@ -483,7 +488,7 @@ def _process_run_information(run_id: str, run_dir: str, result: subprocess.Compl
483
488
 
484
489
  info_file = os.path.join(run_dir, f"{run_id}.json")
485
490
 
486
- with open(info_file) as f:
491
+ with open(info_file, encoding="utf-8") as f:
487
492
  info = json.load(f)
488
493
 
489
494
  # Calculate duration.
@@ -505,7 +510,7 @@ def _process_run_information(run_id: str, run_dir: str, result: subprocess.Compl
505
510
  info["metadata"]["status_v2"] = status
506
511
  info["metadata"]["error"] = error
507
512
 
508
- with open(info_file, "w") as f:
513
+ with open(info_file, "w", encoding="utf-8") as f:
509
514
  json.dump(info, f, indent=2)
510
515
 
511
516
 
@@ -569,7 +574,7 @@ def _process_run_metrics(
569
574
  if METRICS_KEY not in stdout_output:
570
575
  return
571
576
 
572
- with open(metrics_dst, "w") as f:
577
+ with open(metrics_dst, "w", encoding="utf-8") as f:
573
578
  metrics = {METRICS_KEY: stdout_output[METRICS_KEY]}
574
579
  json.dump(metrics, f, indent=2)
575
580
 
@@ -637,7 +642,7 @@ def _process_run_statistics(
637
642
  if STATISTICS_KEY not in stdout_output:
638
643
  return
639
644
 
640
- with open(stats_dst, "w") as f:
645
+ with open(stats_dst, "w", encoding="utf-8") as f:
641
646
  stats = {STATISTICS_KEY: stdout_output[STATISTICS_KEY]}
642
647
  json.dump(stats, f, indent=2)
643
648
 
@@ -702,7 +707,7 @@ def _process_run_assets(
702
707
  if ASSETS_KEY not in stdout_output:
703
708
  return
704
709
 
705
- with open(assets_dst, "w") as f:
710
+ with open(assets_dst, "w", encoding="utf-8") as f:
706
711
  assets = {ASSETS_KEY: stdout_output[ASSETS_KEY]}
707
712
  json.dump(assets, f, indent=2)
708
713
 
@@ -753,7 +758,7 @@ def _process_run_solutions(
753
758
 
754
759
  info_file = os.path.join(run_dir, f"{run_id}.json")
755
760
 
756
- with open(info_file) as f:
761
+ with open(info_file, encoding="utf-8") as f:
757
762
  info = json.load(f)
758
763
 
759
764
  solutions_dst = os.path.join(outputs_dir, SOLUTIONS_KEY)
@@ -786,7 +791,7 @@ def _process_run_solutions(
786
791
  )
787
792
  else:
788
793
  if bool(stdout_output):
789
- with open(os.path.join(solutions_dst, DEFAULT_OUTPUT_JSON_FILE), "w") as f:
794
+ with open(os.path.join(solutions_dst, DEFAULT_OUTPUT_JSON_FILE), "w", encoding="utf-8") as f:
790
795
  if isinstance(stdout_output, dict):
791
796
  json.dump(stdout_output, f, indent=2)
792
797
  elif isinstance(stdout_output, str):
@@ -795,7 +800,7 @@ def _process_run_solutions(
795
800
  # Update the run information file with the output size and type.
796
801
  calculate_files_size(run_dir, run_id, solutions_dst, metadata_key="output_size")
797
802
  info["metadata"]["format"]["output"] = {"type": output_format.value}
798
- with open(info_file, "w") as f:
803
+ with open(info_file, "w", encoding="utf-8") as f:
799
804
  json.dump(info, f, indent=2)
800
805
 
801
806
 
@@ -824,7 +829,7 @@ def _process_run_visuals(run_dir: str, outputs_dir: str) -> None:
824
829
  else:
825
830
  return
826
831
 
827
- with open(assets_file) as f:
832
+ with open(assets_file, encoding="utf-8") as f:
828
833
  assets = json.load(f)
829
834
 
830
835
  # Create visuals directory.
@@ -0,0 +1,109 @@
1
+ """
2
+ Tests for the encoding behaviour of _cli_call in nextmv.cli.init.
3
+
4
+ On Windows, subprocess pipes default to the system codepage (e.g. cp1252).
5
+ Byte 0x8f is undefined in cp1252, so without an explicit encoding this raises
6
+ UnicodeDecodeError. The fix decodes each stream independently:
7
+
8
+ - stderr → utf-8 with errors="replace" (human-facing, replacement char is OK)
9
+ - stdout → utf-8 strict (machine-readable JSON; corruption must
10
+ surface as a clear UnicodeDecodeError,
11
+ not a silent JSONDecodeError later)
12
+ """
13
+
14
+ import subprocess
15
+ import unittest
16
+ from io import BytesIO
17
+ from unittest.mock import MagicMock, patch
18
+
19
+ import typer
20
+
21
+
22
+ def _make_pipe(raw_bytes: bytes):
23
+ """Return a mock binary pipe whose iteration yields lines from *raw_bytes*."""
24
+ bio = BytesIO(raw_bytes)
25
+ mock_pipe = MagicMock()
26
+ mock_pipe.__iter__ = lambda self: iter(bio)
27
+ return mock_pipe
28
+
29
+
30
+ def _make_process(stdout_bytes: bytes = b"", stderr_bytes: bytes = b"", returncode: int = 0):
31
+ mock = MagicMock()
32
+ mock.stdout = _make_pipe(stdout_bytes)
33
+ mock.stderr = _make_pipe(stderr_bytes)
34
+ mock.returncode = returncode
35
+ mock.wait = MagicMock()
36
+ return mock
37
+
38
+
39
+ class TestCliCallEncoding(unittest.TestCase):
40
+ """Verify that _cli_call survives non-UTF-8 bytes and applies the correct
41
+ decoding strategy to each stream."""
42
+
43
+ def _invoke(self, stdout_bytes: bytes, stderr_bytes: bytes) -> subprocess.CompletedProcess:
44
+ """Call _cli_call with a mocked Popen and return its result."""
45
+ from nextmv.cli.init import _cli_call
46
+
47
+ mock_process = _make_process(stdout_bytes, stderr_bytes)
48
+
49
+ with patch("nextmv.cli.init.subprocess.Popen", return_value=mock_process):
50
+ return _cli_call(["echo", "test"])
51
+
52
+ def test_non_utf8_in_stderr_replaced_not_raised(self):
53
+ """Byte 0x8f (undefined in cp1252) in stderr must not raise; it becomes a replacement char."""
54
+ result = self._invoke(
55
+ stdout_bytes=b"",
56
+ stderr_bytes=b"warning: bad byte \x8f here\n",
57
+ )
58
+ # The replacement character U+FFFD (or '?') appears; no exception was raised.
59
+ self.assertIn("warning: bad byte", result.stderr)
60
+
61
+ def test_valid_utf8_stderr_preserved(self):
62
+ """Normal UTF-8 stderr (including non-ASCII) must be preserved exactly."""
63
+ result = self._invoke(
64
+ stdout_bytes=b"",
65
+ stderr_bytes="info: résumé 日本語\n".encode(),
66
+ )
67
+ self.assertIn("résumé", result.stderr)
68
+ self.assertIn("日本語", result.stderr)
69
+
70
+ def test_valid_utf8_stdout_preserved(self):
71
+ """Normal UTF-8 stdout is decoded and returned intact."""
72
+ result = self._invoke(
73
+ stdout_bytes=b'{"key": "value"}\n',
74
+ stderr_bytes=b"",
75
+ )
76
+ self.assertIn('"key"', result.stdout)
77
+
78
+ def test_non_utf8_in_stdout_raises_unicode_error(self):
79
+ """Non-UTF-8 bytes in stdout must not be silently swallowed.
80
+
81
+ The UnicodeDecodeError is caught by _cli_call's outer handler, which
82
+ prints a human-readable message and raises typer.Exit(code=1). That is
83
+ the correct production behaviour: the caller sees a clear failure rather
84
+ than a confusing JSONDecodeError or silently corrupted data.
85
+ """
86
+ with self.assertRaises((UnicodeDecodeError, typer.Exit)):
87
+ self._invoke(
88
+ stdout_bytes=b'{"key": "\x8f"}\n',
89
+ stderr_bytes=b"",
90
+ )
91
+
92
+ def test_popen_called_in_binary_mode(self):
93
+ """_cli_call must open the subprocess in binary mode (no text=True / encoding kwarg)
94
+ so that each stream can be decoded with its own strategy."""
95
+ from nextmv.cli.init import _cli_call
96
+
97
+ mock_process = _make_process(b'{"ok": true}\n', b"")
98
+
99
+ with patch("nextmv.cli.init.subprocess.Popen", return_value=mock_process) as mock_popen:
100
+ _cli_call(["echo", "test"])
101
+
102
+ call_kwargs = mock_popen.call_args[1]
103
+ # Must NOT pass text=True or a global encoding – binary mode is required.
104
+ self.assertNotIn("encoding", call_kwargs)
105
+ self.assertNotIn("text", call_kwargs)
106
+
107
+
108
+ if __name__ == "__main__":
109
+ unittest.main()
@@ -1203,5 +1203,120 @@ class TestCopyNewOrModifiedFiles(unittest.TestCase):
1203
1203
  self._assert_file_not_exists(os.path.join(self.dst_dir, "regular.pyc"))
1204
1204
 
1205
1205
 
1206
+ class TestExecutorEncoding(unittest.TestCase):
1207
+ """Tests that execute_run handles non-UTF-8 bytes in subprocess output without crashing."""
1208
+
1209
+ def setUp(self):
1210
+ self.test_dir = tempfile.mkdtemp()
1211
+ self.run_dir = os.path.join(self.test_dir, "run_dir")
1212
+ os.makedirs(self.run_dir)
1213
+
1214
+ def tearDown(self):
1215
+ shutil.rmtree(self.test_dir)
1216
+
1217
+ def _make_info_file(self, run_id: str) -> None:
1218
+ info_file = os.path.join(self.run_dir, f"{run_id}.json")
1219
+ with open(info_file, "w", encoding="utf-8") as f:
1220
+ json.dump(
1221
+ {
1222
+ "metadata": {
1223
+ "created_at": "2023-01-01T00:00:00Z",
1224
+ "status_v2": "pending",
1225
+ "format": {"output": {"type": "json"}},
1226
+ }
1227
+ },
1228
+ f,
1229
+ )
1230
+
1231
+ def _run_execute_run(self, stdout_lines, stderr_lines, run_id="test_encoding_run"):
1232
+ """Helper that patches Popen and runs execute_run, returning normally."""
1233
+ self._make_info_file(run_id)
1234
+
1235
+ mock_process = Mock()
1236
+ mock_process.returncode = 0
1237
+ mock_process.stdin = Mock()
1238
+ mock_process.stdout = iter(stdout_lines)
1239
+ mock_process.stderr = iter(stderr_lines)
1240
+
1241
+ with (
1242
+ patch("nextmv.local.executor._copy_files_from_manifest"),
1243
+ patch("nextmv.local.executor.process_run_output"),
1244
+ patch("nextmv.local.executor.subprocess.Popen", return_value=mock_process),
1245
+ ):
1246
+ execute_run(
1247
+ run_id=run_id,
1248
+ src="/test/src",
1249
+ manifest_dict={"execution": {"entrypoint": "main.py"}, "type": "python", "files": ["main.py"]},
1250
+ run_dir=self.run_dir,
1251
+ run_config={"format": {"input": {"type": "json"}}},
1252
+ input_data={"test": "data"},
1253
+ )
1254
+
1255
+ def test_non_utf8_bytes_in_stderr_do_not_crash(self):
1256
+ """Non-UTF-8 bytes in stderr must not raise UnicodeDecodeError.
1257
+
1258
+ On Windows the subprocess pipes default to the system codepage (e.g.
1259
+ cp1252). Byte 0x8f is undefined in cp1252, so without an explicit
1260
+ encoding this would raise UnicodeDecodeError. The fix is to open the
1261
+ Popen with encoding='utf-8' and errors='replace'.
1262
+ """
1263
+ # Simulate a line that contains the byte 0x8f – undefined in cp1252.
1264
+ # We use a plain string here because the mock iter already yields str;
1265
+ # the important thing is that the pipeline doesn't blow up when such
1266
+ # a replacement character reaches the log file writer.
1267
+ bad_line = "progress: \ufffd done\n" # U+FFFD = replacement character
1268
+ self._run_execute_run(stdout_lines=[], stderr_lines=[bad_line])
1269
+
1270
+ logs_file = os.path.join(self.run_dir, LOGS_KEY, LOGS_FILE)
1271
+ self.assertTrue(os.path.exists(logs_file))
1272
+ with open(logs_file, encoding="utf-8") as f:
1273
+ content = f.read()
1274
+ self.assertIn("progress:", content)
1275
+
1276
+ def test_non_utf8_bytes_in_stdout_do_not_crash(self):
1277
+ """Non-UTF-8 replacement characters in stdout are handled gracefully."""
1278
+ bad_line = '{"result": "\ufffd"}\n'
1279
+ self._run_execute_run(stdout_lines=[bad_line], stderr_lines=[])
1280
+
1281
+ def test_log_file_written_as_utf8(self):
1282
+ """The logs file must be written with UTF-8 encoding so non-ASCII characters survive."""
1283
+ unicode_line = "info: résumé café naïve 日本語\n"
1284
+ self._run_execute_run(stdout_lines=[], stderr_lines=[unicode_line])
1285
+
1286
+ logs_file = os.path.join(self.run_dir, LOGS_KEY, LOGS_FILE)
1287
+ with open(logs_file, encoding="utf-8") as f:
1288
+ content = f.read()
1289
+ self.assertIn("résumé", content)
1290
+ self.assertIn("日本語", content)
1291
+
1292
+ def test_popen_called_with_utf8_encoding(self):
1293
+ """subprocess.Popen must be called with encoding='utf-8' and errors='replace'."""
1294
+ self._make_info_file("enc_check")
1295
+
1296
+ mock_process = Mock()
1297
+ mock_process.returncode = 0
1298
+ mock_process.stdin = Mock()
1299
+ mock_process.stdout = iter([])
1300
+ mock_process.stderr = iter([])
1301
+
1302
+ with (
1303
+ patch("nextmv.local.executor._copy_files_from_manifest"),
1304
+ patch("nextmv.local.executor.process_run_output"),
1305
+ patch("nextmv.local.executor.subprocess.Popen", return_value=mock_process) as mock_popen,
1306
+ ):
1307
+ execute_run(
1308
+ run_id="enc_check",
1309
+ src="/test/src",
1310
+ manifest_dict={"execution": {"entrypoint": "main.py"}, "type": "python", "files": ["main.py"]},
1311
+ run_dir=self.run_dir,
1312
+ run_config={"format": {"input": {"type": "json"}}},
1313
+ input_data={"test": "data"},
1314
+ )
1315
+
1316
+ call_kwargs = mock_popen.call_args[1]
1317
+ self.assertEqual(call_kwargs.get("encoding"), "utf-8")
1318
+ self.assertEqual(call_kwargs.get("errors"), "replace")
1319
+
1320
+
1206
1321
  if __name__ == "__main__":
1207
1322
  unittest.main()
@@ -1 +0,0 @@
1
- __version__ = "v1.7.2"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes