ob-metaflow-extensions 1.4.1__tar.gz → 1.4.32__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.
Potentially problematic release.
This version of ob-metaflow-extensions might be problematic. Click here for more details.
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/PKG-INFO +1 -1
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/__init__.py +1 -1
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/app_cli.py +44 -25
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/app_config.py +2 -1
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/capsule.py +101 -38
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/code_packager.py +7 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config/typed_configs.py +4 -1
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config/unified_config.py +54 -5
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config_schema.yaml +20 -4
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/experimental/__init__.py +29 -18
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/perimeters.py +1 -1
- ob_metaflow_extensions-1.4.32/metaflow_extensions/outerbounds/plugins/optuna/__init__.py +48 -0
- ob_metaflow_extensions-1.4.32/metaflow_extensions/outerbounds/plugins/s3_proxy/binary_caller.py +132 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/s3_proxy/constants.py +4 -1
- ob_metaflow_extensions-1.4.32/metaflow_extensions/outerbounds/plugins/s3_proxy/proxy_bootstrap.py +59 -0
- ob_metaflow_extensions-1.4.32/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_decorator.py +250 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_manager.py +44 -41
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_client.py +6 -3
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_decorator.py +13 -7
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_job.py +8 -2
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py +32 -4
- ob_metaflow_extensions-1.4.32/metaflow_extensions/outerbounds/toplevel/plugins/optuna/__init__.py +1 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/ob_metaflow_extensions.egg-info/PKG-INFO +1 -1
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/ob_metaflow_extensions.egg-info/SOURCES.txt +4 -0
- ob_metaflow_extensions-1.4.32/ob_metaflow_extensions.egg-info/requires.txt +3 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/setup.py +2 -2
- ob_metaflow_extensions-1.4.1/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_decorator.py +0 -106
- ob_metaflow_extensions-1.4.1/ob_metaflow_extensions.egg-info/requires.txt +0 -3
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/MANIFEST.in +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/README.md +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/config/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/app_cli.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/app_deploy_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/app_utils.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/consts.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/_state_machine.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/spinners.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/artifacts.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/click_importer.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/examples.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config/cli_generator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config/config_utils.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config/schema_export.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/config/typed_init_generator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/dependencies.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/deployer.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/secrets.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/utils.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/core/validations.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/deploy_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/apps/supervisord_utils.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/auth_server.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/aws/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/aws/assume_role.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/card_utilities/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/card_utilities/async_cards.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/card_utilities/extra_components.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/card_utilities/injector.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/external_chckpt.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/fast_bakery/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_cli.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/kubernetes/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/kubernetes/kubernetes_client.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/kubernetes/pod_killer.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nim/card.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nim/nim_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nim/nim_manager.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nim/utils.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/constants.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/exceptions.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/heartbeat_store.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_cli.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvcf/utils.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvct/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvct/exceptions.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvct/nvct.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvct/nvct_cli.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvct/nvct_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvct/nvct_runner.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/nvct/utils.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/ollama/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/ollama/constants.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/ollama/exceptions.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/ollama/ollama.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/ollama/status_card.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/perimeters.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/profilers/deco_injector.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/profilers/gpu_profile_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/profilers/simple_card_decorator.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/s3_proxy/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/s3_proxy/exceptions.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_api.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/secrets/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/secrets/secrets.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowflake/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowflake/snowflake.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_cli.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_exceptions.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_service_spec.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/tensorboard/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/torchtune/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/vllm/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/vllm/constants.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/vllm/exceptions.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/vllm/status_card.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/plugins/vllm/vllm_manager.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/profilers/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/profilers/gpu.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/remote_config.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/ob_internal.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/plugins/azure/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/plugins/gcp/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/plugins/kubernetes/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/plugins/ollama/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/plugins/snowflake/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/plugins/torchtune/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/plugins/vllm/__init__.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/metaflow_extensions/outerbounds/toplevel/s3_proxy.py +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/ob_metaflow_extensions.egg-info/dependency_links.txt +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/ob_metaflow_extensions.egg-info/top_level.txt +0 -0
- {ob_metaflow_extensions-1.4.1 → ob_metaflow_extensions-1.4.32}/setup.cfg +0 -0
|
@@ -361,4 +361,4 @@ SECRETS_PROVIDERS_DESC = [
|
|
|
361
361
|
("outerbounds", ".secrets.secrets.OuterboundsSecretsProvider"),
|
|
362
362
|
]
|
|
363
363
|
# Adding an override here so the library can be imported at the metaflow.plugins level
|
|
364
|
-
__mf_promote_submodules__ = ["snowflake", "ollama", "torchtune"]
|
|
364
|
+
__mf_promote_submodules__ = ["snowflake", "ollama", "torchtune", "optuna"]
|
|
@@ -339,7 +339,7 @@ def deployment_instance_options(func):
|
|
|
339
339
|
"--readiness-wait-time",
|
|
340
340
|
type=int,
|
|
341
341
|
help="The time (in seconds) to monitor the deployment for readiness after the readiness condition is met.",
|
|
342
|
-
default=
|
|
342
|
+
default=15,
|
|
343
343
|
)
|
|
344
344
|
@click.option(
|
|
345
345
|
"--deployment-timeout",
|
|
@@ -377,8 +377,8 @@ def _package_necessary_things(app_config: AppConfig, logger):
|
|
|
377
377
|
# from the command line and that will alleviate any need to package any other directories for
|
|
378
378
|
#
|
|
379
379
|
|
|
380
|
-
|
|
381
|
-
if
|
|
380
|
+
package_dirs = app_config.get_state("packaging_directories")
|
|
381
|
+
if package_dirs is None:
|
|
382
382
|
app_config.set_state("code_package_url", None)
|
|
383
383
|
app_config.set_state("code_package_key", None)
|
|
384
384
|
return
|
|
@@ -391,13 +391,26 @@ def _package_necessary_things(app_config: AppConfig, logger):
|
|
|
391
391
|
datastore_type=DEFAULT_DATASTORE, code_package_prefix=CODE_PACKAGE_PREFIX
|
|
392
392
|
)
|
|
393
393
|
package_url, package_key = packager.store(
|
|
394
|
-
paths_to_include=
|
|
394
|
+
paths_to_include=package_dirs, file_suffixes=suffixes
|
|
395
395
|
)
|
|
396
396
|
app_config.set_state("code_package_url", package_url)
|
|
397
397
|
app_config.set_state("code_package_key", package_key)
|
|
398
398
|
logger("💾 Code package saved to : %s" % app_config.get_state("code_package_url"))
|
|
399
399
|
|
|
400
400
|
|
|
401
|
+
def _sniff_pyproject_and_requirements(packaging_directories: List[str]):
|
|
402
|
+
pyproject_path = None
|
|
403
|
+
requirements_path = None
|
|
404
|
+
for directory in packaging_directories:
|
|
405
|
+
pyproject_toml = os.path.join(directory, "pyproject.toml")
|
|
406
|
+
requirements_txt = os.path.join(directory, "requirements.txt")
|
|
407
|
+
if os.path.exists(pyproject_toml):
|
|
408
|
+
pyproject_path = pyproject_toml
|
|
409
|
+
elif os.path.exists(requirements_txt):
|
|
410
|
+
requirements_path = requirements_txt
|
|
411
|
+
return pyproject_path, requirements_path
|
|
412
|
+
|
|
413
|
+
|
|
401
414
|
@app.command(help="Deploy an app to the Outerbounds Platform.")
|
|
402
415
|
@click.option(
|
|
403
416
|
"--config-file",
|
|
@@ -449,23 +462,19 @@ def deploy(
|
|
|
449
462
|
system_msg=True,
|
|
450
463
|
)
|
|
451
464
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
packaging_directory = os.path.abspath(package_src_path)
|
|
459
|
-
else:
|
|
460
|
-
raise AppConfigError(f"src_path '{package_src_path}' does not exist")
|
|
461
|
-
else:
|
|
462
|
-
# If src_path is None then we assume then we can assume for the moment
|
|
465
|
+
package_src_paths = app_config.get("package", {}).get("src_paths", [])
|
|
466
|
+
if package_src_paths is None:
|
|
467
|
+
package_src_paths = []
|
|
468
|
+
|
|
469
|
+
if len(package_src_paths) == 0:
|
|
470
|
+
# If src_paths is None then we assume then we can assume for the moment
|
|
463
471
|
# that we can package the current working directory.
|
|
464
|
-
|
|
472
|
+
package_src_paths = [os.getcwd()]
|
|
465
473
|
|
|
466
|
-
app_config.set_state("
|
|
474
|
+
app_config.set_state("packaging_directories", package_src_paths)
|
|
467
475
|
logger(
|
|
468
|
-
"📦 Packaging
|
|
476
|
+
"📦 Packaging directories : %s"
|
|
477
|
+
% ", ".join(app_config.get_state("packaging_directories")),
|
|
469
478
|
)
|
|
470
479
|
|
|
471
480
|
if app_config.get("no_deps", False):
|
|
@@ -484,22 +493,32 @@ def deploy(
|
|
|
484
493
|
dependencies.get("conda", None) is None,
|
|
485
494
|
]
|
|
486
495
|
):
|
|
496
|
+
python_version = dependencies.get(
|
|
497
|
+
"python"
|
|
498
|
+
) # python gets a default value so it's always set.
|
|
487
499
|
# The user has not set any dependencies, so we can sniff the packaging directory
|
|
488
500
|
# for a dependencies file.
|
|
489
|
-
requirements_file =
|
|
490
|
-
|
|
501
|
+
pyproject_toml, requirements_file = _sniff_pyproject_and_requirements(
|
|
502
|
+
package_src_paths
|
|
491
503
|
)
|
|
492
|
-
pyproject_toml
|
|
493
|
-
if os.path.exists(pyproject_toml):
|
|
504
|
+
if pyproject_toml:
|
|
494
505
|
app_config.set_state(
|
|
495
|
-
"dependencies",
|
|
506
|
+
"dependencies",
|
|
507
|
+
{
|
|
508
|
+
"from_pyproject_toml": pyproject_toml,
|
|
509
|
+
"python": python_version,
|
|
510
|
+
},
|
|
496
511
|
)
|
|
497
512
|
logger(
|
|
498
513
|
"📦 Using dependencies from pyproject.toml: %s" % pyproject_toml
|
|
499
514
|
)
|
|
500
|
-
elif
|
|
515
|
+
elif requirements_file:
|
|
501
516
|
app_config.set_state(
|
|
502
|
-
"dependencies",
|
|
517
|
+
"dependencies",
|
|
518
|
+
{
|
|
519
|
+
"from_requirements_file": requirements_file,
|
|
520
|
+
"python": python_version,
|
|
521
|
+
},
|
|
503
522
|
)
|
|
504
523
|
logger(
|
|
505
524
|
"📦 Using dependencies from requirements.txt: %s"
|
|
@@ -45,10 +45,11 @@ def _try_loading_yaml(file):
|
|
|
45
45
|
class AuthType:
|
|
46
46
|
BROWSER = "Browser"
|
|
47
47
|
API = "API"
|
|
48
|
+
BROWSER_AND_API = "BrowserAndApi"
|
|
48
49
|
|
|
49
50
|
@classmethod
|
|
50
51
|
def enums(cls):
|
|
51
|
-
return [cls.BROWSER, cls.API]
|
|
52
|
+
return [cls.BROWSER, cls.API, cls.BROWSER_AND_API]
|
|
52
53
|
|
|
53
54
|
@classproperty
|
|
54
55
|
def default(cls):
|
|
@@ -7,7 +7,7 @@ import sys
|
|
|
7
7
|
import time
|
|
8
8
|
from functools import partial
|
|
9
9
|
import shlex
|
|
10
|
-
from typing import Optional, List, Dict, Any, Tuple, Union
|
|
10
|
+
from typing import Optional, List, Dict, Any, Tuple, Union, Callable
|
|
11
11
|
from .utils import TODOException, safe_requests_wrapper, MaximumRetriesExceeded
|
|
12
12
|
from .app_config import AppConfig, CAPSULE_DEBUG, AuthType
|
|
13
13
|
from . import experimental
|
|
@@ -75,7 +75,6 @@ class CapsuleStateMachine:
|
|
|
75
75
|
return self._status_trail
|
|
76
76
|
|
|
77
77
|
def add_status(self, status: CapsuleStatus):
|
|
78
|
-
assert type(status) == dict, "TODO: Make this check somewhere else"
|
|
79
78
|
self._status_trail.append({"timestamp": time.time(), "status": status})
|
|
80
79
|
|
|
81
80
|
@property
|
|
@@ -116,7 +115,9 @@ class CapsuleStateMachine:
|
|
|
116
115
|
pass
|
|
117
116
|
|
|
118
117
|
def save_debug_info(self, state_dir: str):
|
|
119
|
-
debug_path = os.path.join(
|
|
118
|
+
debug_path = os.path.join(
|
|
119
|
+
state_dir, f"debug_capsule_sm_{self._capsule_id}.json"
|
|
120
|
+
)
|
|
120
121
|
with open(debug_path, "w") as f:
|
|
121
122
|
json.dump(self._status_trail, f, indent=4)
|
|
122
123
|
|
|
@@ -427,7 +428,7 @@ class CapsuleApi:
|
|
|
427
428
|
message="Capsule JSON decode failed",
|
|
428
429
|
)
|
|
429
430
|
|
|
430
|
-
def get(self, capsule_id: str):
|
|
431
|
+
def get(self, capsule_id: str) -> Dict[str, Any]:
|
|
431
432
|
_url = os.path.join(self._base_url, capsule_id)
|
|
432
433
|
response = self._wrapped_api_caller(
|
|
433
434
|
requests.get,
|
|
@@ -446,6 +447,35 @@ class CapsuleApi:
|
|
|
446
447
|
message="Capsule JSON decode failed",
|
|
447
448
|
)
|
|
448
449
|
|
|
450
|
+
# TODO: refactor me since name *currently(9/8/25)* is unique across capsules.
|
|
451
|
+
def get_by_name(self, name: str, most_recent_only: bool = True):
|
|
452
|
+
_url = os.path.join(self._base_url, f"?displayName={name}")
|
|
453
|
+
response = self._wrapped_api_caller(
|
|
454
|
+
requests.get,
|
|
455
|
+
_url,
|
|
456
|
+
retryable_status_codes=[409], # todo : verify me
|
|
457
|
+
conn_error_retries=3,
|
|
458
|
+
)
|
|
459
|
+
try:
|
|
460
|
+
if most_recent_only:
|
|
461
|
+
result = response.json()
|
|
462
|
+
candidates = result["capsules"]
|
|
463
|
+
if not candidates:
|
|
464
|
+
return None
|
|
465
|
+
return sorted(
|
|
466
|
+
candidates, key=lambda x: x["metadata"]["createdAt"], reverse=True
|
|
467
|
+
)[0]
|
|
468
|
+
else:
|
|
469
|
+
return response.json()
|
|
470
|
+
except json.JSONDecodeError as e:
|
|
471
|
+
raise CapsuleApiException(
|
|
472
|
+
_url,
|
|
473
|
+
"get",
|
|
474
|
+
response.status_code,
|
|
475
|
+
response.text,
|
|
476
|
+
message="Capsule JSON decode failed",
|
|
477
|
+
)
|
|
478
|
+
|
|
449
479
|
def list(self):
|
|
450
480
|
response = self._wrapped_api_caller(
|
|
451
481
|
requests.get,
|
|
@@ -648,7 +678,7 @@ class CapsuleDeployer:
|
|
|
648
678
|
auth_type = self._app_config.get_state("auth", {}).get("type", AuthType.default)
|
|
649
679
|
if auth_type == AuthType.BROWSER:
|
|
650
680
|
return "App"
|
|
651
|
-
elif auth_type == AuthType.API:
|
|
681
|
+
elif auth_type == AuthType.API or auth_type == AuthType.BROWSER_AND_API:
|
|
652
682
|
return "Endpoint"
|
|
653
683
|
else:
|
|
654
684
|
raise TODOException(f"Unknown auth type: {auth_type}")
|
|
@@ -698,17 +728,51 @@ class CapsuleDeployer:
|
|
|
698
728
|
f"A capsule upgrade was triggered outside current deployment instance. Current deployment version was discarded. Current deployment version: {current_deployment_instance_version} and new version: {capsule_response.get('version', None)}",
|
|
699
729
|
)
|
|
700
730
|
|
|
731
|
+
def _update_capsule_and_worker_sm(
|
|
732
|
+
self,
|
|
733
|
+
capsule_sm: "CapsuleStateMachine",
|
|
734
|
+
workers_sm: "CapsuleWorkersStateMachine",
|
|
735
|
+
logger: Callable[[str], None],
|
|
736
|
+
) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
|
|
737
|
+
capsule_response = self.get()
|
|
738
|
+
capsule_sm.add_status(capsule_response.get("status", {})) # type: ignore
|
|
739
|
+
|
|
740
|
+
# We need to check if someone has not upgraded the capsule under the hood and
|
|
741
|
+
# the current deployment instance is invalid.
|
|
742
|
+
self._backend_version_mismatch_check(
|
|
743
|
+
capsule_response, self.current_deployment_instance_version # type: ignore
|
|
744
|
+
)
|
|
745
|
+
workers_response = self.get_workers()
|
|
746
|
+
capsule_sm.report_current_status(logger)
|
|
747
|
+
workers_sm.add_status(workers_response)
|
|
748
|
+
workers_sm.report_current_status(logger)
|
|
749
|
+
return capsule_response, workers_response
|
|
750
|
+
|
|
751
|
+
def _publish_capsule_debug_info(
|
|
752
|
+
self,
|
|
753
|
+
capsule_sm: "CapsuleStateMachine",
|
|
754
|
+
workers_sm: "CapsuleWorkersStateMachine",
|
|
755
|
+
capsule_response: Dict[str, Any],
|
|
756
|
+
):
|
|
757
|
+
if CAPSULE_DEBUG and self._debug_dir:
|
|
758
|
+
capsule_sm.save_debug_info(self._debug_dir)
|
|
759
|
+
workers_sm.save_debug_info(self._debug_dir)
|
|
760
|
+
debug_path = os.path.join(
|
|
761
|
+
self._debug_dir, f"debug_capsule_{self.identifier}.json"
|
|
762
|
+
)
|
|
763
|
+
with open(debug_path, "w") as f:
|
|
764
|
+
f.write(json.dumps(capsule_response, indent=4))
|
|
765
|
+
|
|
701
766
|
def _monitor_worker_readiness(
|
|
702
767
|
self,
|
|
703
768
|
workers_sm: "CapsuleWorkersStateMachine",
|
|
769
|
+
capsule_sm: "CapsuleStateMachine",
|
|
704
770
|
):
|
|
705
771
|
"""returns True if the worker is crashlooping, False otherwise"""
|
|
706
772
|
logger = self._logger_fn or partial(print, file=sys.stderr)
|
|
707
773
|
for i in range(self._readiness_wait_time):
|
|
708
774
|
time.sleep(1)
|
|
709
|
-
|
|
710
|
-
workers_sm.add_status(workers_response)
|
|
711
|
-
workers_sm.report_current_status(logger)
|
|
775
|
+
self._update_capsule_and_worker_sm(capsule_sm, workers_sm, logger)
|
|
712
776
|
if workers_sm.is_crashlooping:
|
|
713
777
|
return True
|
|
714
778
|
return False
|
|
@@ -754,21 +818,19 @@ class CapsuleDeployer:
|
|
|
754
818
|
minimum_replicas=min_replicas,
|
|
755
819
|
)
|
|
756
820
|
self.status = state_machine
|
|
821
|
+
|
|
822
|
+
# This loop will check all the conditions that help verify the terminal state.
|
|
823
|
+
# How it works is by extracting the statuses of the capsule and workers and
|
|
824
|
+
# then adding them as a part of a state-machine that helps track transitions and
|
|
825
|
+
# helps derive terminal states.
|
|
826
|
+
# We will first keep checking for terminal conditions or outright failure conditions
|
|
827
|
+
# If we reach a teminal condition like described in `DEPLOYMENT_READY_CONDITIONS`, then
|
|
828
|
+
# we will further check for readiness conditions.
|
|
757
829
|
for i in range(self._create_timeout):
|
|
758
830
|
time.sleep(1)
|
|
759
|
-
capsule_response = self.
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
# We first need to check if someone has not upgraded the capsule under the hood and
|
|
763
|
-
# the current deployment instance is invalid.
|
|
764
|
-
self._backend_version_mismatch_check(
|
|
765
|
-
capsule_response, self.current_deployment_instance_version # type: ignore
|
|
831
|
+
capsule_response, _ = self._update_capsule_and_worker_sm(
|
|
832
|
+
state_machine, workers_state_machine, logger
|
|
766
833
|
)
|
|
767
|
-
state_machine.add_status(capsule_response.get("status", {})) # type: ignore
|
|
768
|
-
workers_state_machine.add_status(workers_response)
|
|
769
|
-
state_machine.report_current_status(logger)
|
|
770
|
-
|
|
771
|
-
workers_state_machine.report_current_status(logger)
|
|
772
834
|
# Deployment readiness checks will determine what is the terminal state
|
|
773
835
|
# of the workerstate machine. If we detect a terminal state in the workers,
|
|
774
836
|
# then even if the capsule upgrade is still in progress we will end up crashing
|
|
@@ -793,9 +855,11 @@ class CapsuleDeployer:
|
|
|
793
855
|
"💊 %s deployment status: %s "
|
|
794
856
|
% (
|
|
795
857
|
self.capsule_type.title(),
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
858
|
+
(
|
|
859
|
+
"in progress"
|
|
860
|
+
if state_machine.update_in_progress
|
|
861
|
+
else "completed"
|
|
862
|
+
),
|
|
799
863
|
)
|
|
800
864
|
)
|
|
801
865
|
_further_readiness_check_failed = False
|
|
@@ -809,7 +873,8 @@ class CapsuleDeployer:
|
|
|
809
873
|
% self.identifier
|
|
810
874
|
)
|
|
811
875
|
_further_readiness_check_failed = self._monitor_worker_readiness(
|
|
812
|
-
workers_state_machine
|
|
876
|
+
workers_state_machine,
|
|
877
|
+
state_machine,
|
|
813
878
|
)
|
|
814
879
|
|
|
815
880
|
if CAPSULE_DEBUG:
|
|
@@ -853,13 +918,18 @@ class CapsuleDeployer:
|
|
|
853
918
|
|
|
854
919
|
break
|
|
855
920
|
|
|
856
|
-
|
|
857
|
-
state_machine
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
921
|
+
self._publish_capsule_debug_info(
|
|
922
|
+
state_machine, workers_state_machine, capsule_response
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
if CAPSULE_DEBUG and i % 3 == 0: # Every 3 seconds report the status
|
|
926
|
+
logger(
|
|
927
|
+
f"[debug] 💊 {self.capsule_type} {self.identifier} deployment status: {state_machine.current_status} | worker states: {workers_state_machine.current_status} | capsule_ready : {capsule_ready} | further_check_worker_readiness {further_check_worker_readiness}"
|
|
928
|
+
)
|
|
929
|
+
|
|
930
|
+
self._publish_capsule_debug_info(
|
|
931
|
+
state_machine, workers_state_machine, capsule_response
|
|
932
|
+
)
|
|
863
933
|
|
|
864
934
|
# We will only check ready_to_serve_traffic under the following conditions:
|
|
865
935
|
# If the readiness condition is not Async and min_replicas in this deployment
|
|
@@ -877,13 +947,6 @@ class CapsuleDeployer:
|
|
|
877
947
|
f"Capsule {self.identifier} failed to be ready to serve traffic",
|
|
878
948
|
)
|
|
879
949
|
|
|
880
|
-
if CAPSULE_DEBUG and self._debug_dir:
|
|
881
|
-
state_machine.save_debug_info(self._debug_dir)
|
|
882
|
-
workers_state_machine.save_debug_info(self._debug_dir)
|
|
883
|
-
logger(
|
|
884
|
-
f"[debug] 💊 {self.capsule_type} {self.identifier} deployment status [on return]: {state_machine.current_status} | worker states: {workers_state_machine.current_status}"
|
|
885
|
-
)
|
|
886
|
-
|
|
887
950
|
return dict(
|
|
888
951
|
id=self.identifier,
|
|
889
952
|
auth_type=self.capsule_type,
|
|
@@ -381,6 +381,7 @@ class CodePackager:
|
|
|
381
381
|
"google-auth",
|
|
382
382
|
"simple-gcp-object-downloader",
|
|
383
383
|
"google-cloud-secret-manager",
|
|
384
|
+
"packaging",
|
|
384
385
|
],
|
|
385
386
|
"local": [],
|
|
386
387
|
}
|
|
@@ -441,6 +442,7 @@ class CodePackager:
|
|
|
441
442
|
root,
|
|
442
443
|
exclude_hidden=True,
|
|
443
444
|
suffixes=None,
|
|
445
|
+
normalized_rel_path=False,
|
|
444
446
|
) -> List[Tuple[str, str]]:
|
|
445
447
|
"""
|
|
446
448
|
Walk a directory and yield tuples of (file_path, relative_arcname) for files
|
|
@@ -456,6 +458,8 @@ class CodePackager:
|
|
|
456
458
|
Whether to exclude hidden files and directories (those starting with '.')
|
|
457
459
|
suffixes : List[str], optional
|
|
458
460
|
List of file suffixes to include (e.g. ['.py', '.txt'])
|
|
461
|
+
normalized_rel_path : bool, default False
|
|
462
|
+
Whether to normalize the relative from the root. ie if the root is /a/b/c and the file is /a/b/c/d/e.py then the relative path will be d/e.py
|
|
459
463
|
|
|
460
464
|
Returns
|
|
461
465
|
-------
|
|
@@ -468,6 +472,8 @@ class CodePackager:
|
|
|
468
472
|
for file_path, rel_path in symlink_friendly_walk(
|
|
469
473
|
root, exclude_hidden, suffixes
|
|
470
474
|
):
|
|
475
|
+
if normalized_rel_path:
|
|
476
|
+
rel_path = file_path.replace(root, "")
|
|
471
477
|
files.append((file_path, rel_path))
|
|
472
478
|
return files
|
|
473
479
|
|
|
@@ -520,6 +526,7 @@ class CodePackager:
|
|
|
520
526
|
path,
|
|
521
527
|
exclude_hidden=True,
|
|
522
528
|
suffixes=suffixes,
|
|
529
|
+
normalized_rel_path=True,
|
|
523
530
|
):
|
|
524
531
|
tar.add(
|
|
525
532
|
file_path,
|
|
@@ -40,6 +40,7 @@ class ResourceConfigDict(TypedDict, total=False):
|
|
|
40
40
|
memory: Optional[str]
|
|
41
41
|
gpu: Optional[str]
|
|
42
42
|
disk: Optional[str]
|
|
43
|
+
shared_memory: Optional[str]
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
class AuthConfigDict(TypedDict, total=False):
|
|
@@ -67,7 +68,7 @@ class DependencyConfigDict(TypedDict, total=False):
|
|
|
67
68
|
|
|
68
69
|
|
|
69
70
|
class PackageConfigDict(TypedDict, total=False):
|
|
70
|
-
|
|
71
|
+
src_paths: Optional[list]
|
|
71
72
|
suffixes: Optional[list]
|
|
72
73
|
|
|
73
74
|
|
|
@@ -96,6 +97,7 @@ class TypedCoreConfig:
|
|
|
96
97
|
branch: Optional[str] = None,
|
|
97
98
|
models: Optional[list] = None,
|
|
98
99
|
data: Optional[list] = None,
|
|
100
|
+
generate_static_url: Optional[bool] = None,
|
|
99
101
|
**kwargs
|
|
100
102
|
) -> None:
|
|
101
103
|
self._kwargs = {
|
|
@@ -121,6 +123,7 @@ class TypedCoreConfig:
|
|
|
121
123
|
"branch": branch,
|
|
122
124
|
"models": models,
|
|
123
125
|
"data": data,
|
|
126
|
+
"generate_static_url": generate_static_url,
|
|
124
127
|
}
|
|
125
128
|
# Add any additional kwargs
|
|
126
129
|
self._kwargs.update(kwargs)
|
|
@@ -36,10 +36,11 @@ from .config_utils import (
|
|
|
36
36
|
class AuthType:
|
|
37
37
|
BROWSER = "Browser"
|
|
38
38
|
API = "API"
|
|
39
|
+
BROWSER_AND_API = "BrowserAndApi"
|
|
39
40
|
|
|
40
41
|
@classmethod
|
|
41
42
|
def choices(cls):
|
|
42
|
-
return [cls.BROWSER, cls.API]
|
|
43
|
+
return [cls.BROWSER, cls.API, cls.BROWSER_AND_API]
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
class UnitParser:
|
|
@@ -222,6 +223,18 @@ class ResourceConfig(metaclass=ConfigMeta):
|
|
|
222
223
|
parsing_fn=UnitParser("disk").parse,
|
|
223
224
|
)
|
|
224
225
|
|
|
226
|
+
shared_memory = ConfigField(
|
|
227
|
+
cli_meta=CLIOption(
|
|
228
|
+
name="shared_memory",
|
|
229
|
+
cli_option_str="--shared-memory",
|
|
230
|
+
help="Shared memory resource request and limit.",
|
|
231
|
+
),
|
|
232
|
+
field_type=str,
|
|
233
|
+
example="1Gi",
|
|
234
|
+
validation_fn=UnitParser.validation_wrapper_fn("memory"),
|
|
235
|
+
parsing_fn=UnitParser("memory").parse,
|
|
236
|
+
)
|
|
237
|
+
|
|
225
238
|
|
|
226
239
|
class HealthCheckConfig(metaclass=ConfigMeta):
|
|
227
240
|
"""Health check configuration."""
|
|
@@ -480,7 +493,7 @@ class DependencyConfig(metaclass=ConfigMeta):
|
|
|
480
493
|
help="The Python version to use for the app.",
|
|
481
494
|
),
|
|
482
495
|
field_type=str,
|
|
483
|
-
behavior=FieldBehavior.
|
|
496
|
+
behavior=FieldBehavior.UNION,
|
|
484
497
|
example="3.10",
|
|
485
498
|
)
|
|
486
499
|
pypi = ConfigField(
|
|
@@ -541,14 +554,16 @@ class DependencyConfig(metaclass=ConfigMeta):
|
|
|
541
554
|
class PackageConfig(metaclass=ConfigMeta):
|
|
542
555
|
"""Package configuration."""
|
|
543
556
|
|
|
544
|
-
|
|
557
|
+
src_paths = ConfigField(
|
|
545
558
|
cli_meta=CLIOption(
|
|
546
559
|
name="package_src_path",
|
|
547
560
|
cli_option_str="--package-src-path",
|
|
561
|
+
multiple=True,
|
|
548
562
|
help="The path to the source code to deploy with the App.",
|
|
563
|
+
click_type=str,
|
|
549
564
|
),
|
|
550
|
-
field_type=
|
|
551
|
-
example="./",
|
|
565
|
+
field_type=list,
|
|
566
|
+
example=["./"],
|
|
552
567
|
)
|
|
553
568
|
suffixes = ConfigField(
|
|
554
569
|
cli_meta=CLIOption(
|
|
@@ -560,6 +575,28 @@ class PackageConfig(metaclass=ConfigMeta):
|
|
|
560
575
|
example=[".py", ".ipynb"],
|
|
561
576
|
)
|
|
562
577
|
|
|
578
|
+
@staticmethod
|
|
579
|
+
def validate(package_config: "PackageConfig"):
|
|
580
|
+
if package_config.src_paths is None:
|
|
581
|
+
return True
|
|
582
|
+
if package_config.src_paths:
|
|
583
|
+
for path in package_config.src_paths:
|
|
584
|
+
if not os.path.exists(path):
|
|
585
|
+
raise ConfigValidationFailedException(
|
|
586
|
+
field_name="src_paths",
|
|
587
|
+
field_info=package_config._get_field("src_paths"), # type: ignore
|
|
588
|
+
current_value=package_config.src_paths,
|
|
589
|
+
message=f"Path does not exist : `{path}`",
|
|
590
|
+
)
|
|
591
|
+
if not os.path.isdir(path):
|
|
592
|
+
raise ConfigValidationFailedException(
|
|
593
|
+
field_name="src_paths",
|
|
594
|
+
field_info=package_config._get_field("src_paths"), # type: ignore
|
|
595
|
+
current_value=package_config.src_paths,
|
|
596
|
+
message=f"Path is not a directory : `{path}`",
|
|
597
|
+
)
|
|
598
|
+
return True
|
|
599
|
+
|
|
563
600
|
|
|
564
601
|
def everything_is_string(*args):
|
|
565
602
|
return all(isinstance(arg, str) for arg in args)
|
|
@@ -852,6 +889,7 @@ How to read this schema:
|
|
|
852
889
|
cli_meta=None, # No top-level CLI option, only nested fields have CLI options
|
|
853
890
|
field_type=PackageConfig,
|
|
854
891
|
help="Configurations associated with packaging the app.",
|
|
892
|
+
validation_fn=PackageConfig.validate,
|
|
855
893
|
)
|
|
856
894
|
|
|
857
895
|
no_deps = ConfigField(
|
|
@@ -929,6 +967,17 @@ How to read this schema:
|
|
|
929
967
|
is_experimental=True,
|
|
930
968
|
example=[{"asset_id": "data-789", "asset_instance_id": "instance-101"}],
|
|
931
969
|
)
|
|
970
|
+
generate_static_url = ConfigField(
|
|
971
|
+
cli_meta=CLIOption(
|
|
972
|
+
name="generate_static_url",
|
|
973
|
+
cli_option_str="--generate-static-url",
|
|
974
|
+
help="Generate a static URL for the app based on its name.",
|
|
975
|
+
is_flag=True,
|
|
976
|
+
),
|
|
977
|
+
field_type=bool,
|
|
978
|
+
default=False,
|
|
979
|
+
help="Generate a static URL for the app based on its name.",
|
|
980
|
+
)
|
|
932
981
|
# ------- /Experimental -------------
|
|
933
982
|
|
|
934
983
|
def to_dict(self):
|
|
@@ -129,6 +129,12 @@ properties:
|
|
|
129
129
|
example: 1Gi
|
|
130
130
|
mutation_behavior: union
|
|
131
131
|
cli_option: --disk
|
|
132
|
+
shared_memory:
|
|
133
|
+
description: Shared memory resource request and limit. (validation applied)
|
|
134
|
+
type: string
|
|
135
|
+
example: 1Gi
|
|
136
|
+
mutation_behavior: union
|
|
137
|
+
cli_option: --shared-memory
|
|
132
138
|
mutation_behavior: union
|
|
133
139
|
auth:
|
|
134
140
|
title: AuthConfig
|
|
@@ -143,6 +149,7 @@ properties:
|
|
|
143
149
|
enum:
|
|
144
150
|
- Browser
|
|
145
151
|
- API
|
|
152
|
+
- BrowserAndApi
|
|
146
153
|
example: Browser
|
|
147
154
|
mutation_behavior: union
|
|
148
155
|
cli_option: --auth-type
|
|
@@ -218,7 +225,7 @@ properties:
|
|
|
218
225
|
description: The Python version to use for the app.
|
|
219
226
|
type: string
|
|
220
227
|
example: '3.10'
|
|
221
|
-
mutation_behavior:
|
|
228
|
+
mutation_behavior: union
|
|
222
229
|
cli_option: --python
|
|
223
230
|
pypi:
|
|
224
231
|
description: |-
|
|
@@ -247,10 +254,13 @@ properties:
|
|
|
247
254
|
type: object
|
|
248
255
|
required: []
|
|
249
256
|
properties:
|
|
250
|
-
|
|
257
|
+
src_paths:
|
|
251
258
|
description: The path to the source code to deploy with the App.
|
|
252
|
-
type:
|
|
253
|
-
|
|
259
|
+
type: array
|
|
260
|
+
items:
|
|
261
|
+
type: string
|
|
262
|
+
example:
|
|
263
|
+
- ./
|
|
254
264
|
mutation_behavior: union
|
|
255
265
|
cli_option: --package-src-path
|
|
256
266
|
suffixes:
|
|
@@ -319,3 +329,9 @@ properties:
|
|
|
319
329
|
asset_instance_id: instance-101
|
|
320
330
|
experimental: true
|
|
321
331
|
mutation_behavior: union
|
|
332
|
+
generate_static_url:
|
|
333
|
+
description: Generate a static URL for the app based on its name.
|
|
334
|
+
type: boolean
|
|
335
|
+
default: false
|
|
336
|
+
mutation_behavior: union
|
|
337
|
+
cli_option: --generate-static-url
|