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