ob-metaflow-extensions 1.4.11__tar.gz → 1.4.12__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.

Files changed (138) hide show
  1. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/PKG-INFO +1 -1
  2. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/app_cli.py +31 -23
  3. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/capsule.py +67 -34
  4. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/code_packager.py +6 -0
  5. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config/typed_configs.py +2 -1
  6. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config/unified_config.py +40 -3
  7. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config_schema.yaml +13 -4
  8. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/experimental/__init__.py +25 -18
  9. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/ob_metaflow_extensions.egg-info/PKG-INFO +1 -1
  10. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/setup.py +1 -1
  11. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/MANIFEST.in +0 -0
  12. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/README.md +0 -0
  13. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/__init__.py +0 -0
  14. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/config/__init__.py +0 -0
  15. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/__init__.py +0 -0
  16. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/__init__.py +0 -0
  17. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/app_cli.py +0 -0
  18. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/app_deploy_decorator.py +0 -0
  19. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/app_utils.py +0 -0
  20. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/consts.py +0 -0
  21. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/__init__.py +0 -0
  22. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/_state_machine.py +0 -0
  23. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/__init__.py +0 -0
  24. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/__init__.py +0 -0
  25. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/spinners.py +0 -0
  26. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/app_config.py +0 -0
  27. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/artifacts.py +0 -0
  28. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/click_importer.py +0 -0
  29. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/__init__.py +0 -0
  30. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/examples.py +0 -0
  31. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config/__init__.py +0 -0
  32. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config/cli_generator.py +0 -0
  33. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config/config_utils.py +0 -0
  34. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config/schema_export.py +0 -0
  35. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/config/typed_init_generator.py +0 -0
  36. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/dependencies.py +0 -0
  37. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/deployer.py +0 -0
  38. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/perimeters.py +0 -0
  39. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/secrets.py +0 -0
  40. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/utils.py +0 -0
  41. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/core/validations.py +0 -0
  42. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/deploy_decorator.py +0 -0
  43. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/apps/supervisord_utils.py +0 -0
  44. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/auth_server.py +0 -0
  45. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/aws/__init__.py +0 -0
  46. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/aws/assume_role.py +0 -0
  47. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py +0 -0
  48. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/card_utilities/__init__.py +0 -0
  49. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/card_utilities/async_cards.py +0 -0
  50. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/card_utilities/extra_components.py +0 -0
  51. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/card_utilities/injector.py +0 -0
  52. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/__init__.py +0 -0
  53. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +0 -0
  54. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/external_chckpt.py +0 -0
  55. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +0 -0
  56. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/fast_bakery/__init__.py +0 -0
  57. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py +0 -0
  58. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py +0 -0
  59. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py +0 -0
  60. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_cli.py +0 -0
  61. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_decorator.py +0 -0
  62. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/kubernetes/__init__.py +0 -0
  63. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/kubernetes/kubernetes_client.py +0 -0
  64. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/kubernetes/pod_killer.py +0 -0
  65. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nim/card.py +0 -0
  66. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nim/nim_decorator.py +0 -0
  67. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nim/nim_manager.py +0 -0
  68. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nim/utils.py +0 -0
  69. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/__init__.py +0 -0
  70. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/constants.py +0 -0
  71. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/exceptions.py +0 -0
  72. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/heartbeat_store.py +0 -0
  73. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf.py +0 -0
  74. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_cli.py +0 -0
  75. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_decorator.py +0 -0
  76. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvcf/utils.py +0 -0
  77. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvct/__init__.py +0 -0
  78. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvct/exceptions.py +0 -0
  79. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvct/nvct.py +0 -0
  80. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvct/nvct_cli.py +0 -0
  81. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvct/nvct_decorator.py +0 -0
  82. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvct/nvct_runner.py +0 -0
  83. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/nvct/utils.py +0 -0
  84. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/ollama/__init__.py +0 -0
  85. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/ollama/constants.py +0 -0
  86. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/ollama/exceptions.py +0 -0
  87. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/ollama/ollama.py +0 -0
  88. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/ollama/status_card.py +0 -0
  89. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/optuna/__init__.py +0 -0
  90. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/perimeters.py +0 -0
  91. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/profilers/deco_injector.py +0 -0
  92. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/profilers/gpu_profile_decorator.py +0 -0
  93. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/profilers/simple_card_decorator.py +0 -0
  94. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/s3_proxy/__init__.py +0 -0
  95. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/s3_proxy/constants.py +0 -0
  96. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/s3_proxy/exceptions.py +0 -0
  97. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_api.py +0 -0
  98. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_decorator.py +0 -0
  99. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_manager.py +0 -0
  100. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/secrets/__init__.py +0 -0
  101. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/secrets/secrets.py +0 -0
  102. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowflake/__init__.py +0 -0
  103. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowflake/snowflake.py +0 -0
  104. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/__init__.py +0 -0
  105. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark.py +0 -0
  106. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_cli.py +0 -0
  107. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_client.py +0 -0
  108. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_decorator.py +0 -0
  109. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_exceptions.py +0 -0
  110. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_job.py +0 -0
  111. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_service_spec.py +0 -0
  112. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/tensorboard/__init__.py +0 -0
  113. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/torchtune/__init__.py +0 -0
  114. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/vllm/__init__.py +0 -0
  115. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/vllm/constants.py +0 -0
  116. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/vllm/exceptions.py +0 -0
  117. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/vllm/status_card.py +0 -0
  118. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/plugins/vllm/vllm_manager.py +0 -0
  119. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/profilers/__init__.py +0 -0
  120. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/profilers/gpu.py +0 -0
  121. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/remote_config.py +0 -0
  122. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/__init__.py +0 -0
  123. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py +0 -0
  124. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/ob_internal.py +0 -0
  125. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/azure/__init__.py +0 -0
  126. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/gcp/__init__.py +0 -0
  127. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/kubernetes/__init__.py +0 -0
  128. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/ollama/__init__.py +0 -0
  129. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/optuna/__init__.py +0 -0
  130. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/snowflake/__init__.py +0 -0
  131. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/torchtune/__init__.py +0 -0
  132. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/plugins/vllm/__init__.py +0 -0
  133. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/metaflow_extensions/outerbounds/toplevel/s3_proxy.py +0 -0
  134. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/ob_metaflow_extensions.egg-info/SOURCES.txt +0 -0
  135. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/ob_metaflow_extensions.egg-info/dependency_links.txt +0 -0
  136. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/ob_metaflow_extensions.egg-info/requires.txt +0 -0
  137. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/ob_metaflow_extensions.egg-info/top_level.txt +0 -0
  138. {ob_metaflow_extensions-1.4.11 → ob_metaflow_extensions-1.4.12}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob_metaflow_extensions
3
- Version: 1.4.11
3
+ Version: 1.4.12
4
4
  Summary: Outerbounds Platform Extensions for Metaflow
5
5
  Author: Outerbounds, Inc.
6
6
  License: Commercial
@@ -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=4,
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
- package_dir = app_config.get_state("packaging_directory")
381
- if package_dir is None:
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=[package_dir], file_suffixes=suffixes
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
- packaging_directory = None
453
- package_src_path = app_config.get("package", {}).get("src_path", None)
454
- if package_src_path:
455
- if os.path.isfile(package_src_path):
456
- raise AppConfigError("src_path must be a directory, not a file")
457
- elif os.path.isdir(package_src_path):
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
- packaging_directory = os.getcwd()
472
+ package_src_paths = [os.getcwd()]
465
473
 
466
- app_config.set_state("packaging_directory", packaging_directory)
474
+ app_config.set_state("packaging_directories", package_src_paths)
467
475
  logger(
468
- "📦 Packaging directory : %s" % app_config.get_state("packaging_directory"),
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):
@@ -489,11 +498,10 @@ def deploy(
489
498
  ) # python gets a default value so it's always set.
490
499
  # The user has not set any dependencies, so we can sniff the packaging directory
491
500
  # for a dependencies file.
492
- requirements_file = os.path.join(
493
- packaging_directory, "requirements.txt"
501
+ pyproject_toml, requirements_file = _sniff_pyproject_and_requirements(
502
+ package_src_paths
494
503
  )
495
- pyproject_toml = os.path.join(packaging_directory, "pyproject.toml")
496
- if os.path.exists(pyproject_toml):
504
+ if pyproject_toml:
497
505
  app_config.set_state(
498
506
  "dependencies",
499
507
  {
@@ -504,7 +512,7 @@ def deploy(
504
512
  logger(
505
513
  "📦 Using dependencies from pyproject.toml: %s" % pyproject_toml
506
514
  )
507
- elif os.path.exists(requirements_file):
515
+ elif requirements_file:
508
516
  app_config.set_state(
509
517
  "dependencies",
510
518
  {
@@ -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(state_dir, f"debug_capsule_{self._capsule_id}.json")
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,7 @@ 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.
449
451
  def get_by_name(self, name: str, most_recent_only: bool = True):
450
452
  _url = os.path.join(self._base_url, f"?displayName={name}")
451
453
  response = self._wrapped_api_caller(
@@ -726,17 +728,51 @@ class CapsuleDeployer:
726
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)}",
727
729
  )
728
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
+
729
766
  def _monitor_worker_readiness(
730
767
  self,
731
768
  workers_sm: "CapsuleWorkersStateMachine",
769
+ capsule_sm: "CapsuleStateMachine",
732
770
  ):
733
771
  """returns True if the worker is crashlooping, False otherwise"""
734
772
  logger = self._logger_fn or partial(print, file=sys.stderr)
735
773
  for i in range(self._readiness_wait_time):
736
774
  time.sleep(1)
737
- workers_response = self.get_workers()
738
- workers_sm.add_status(workers_response)
739
- workers_sm.report_current_status(logger)
775
+ self._update_capsule_and_worker_sm(capsule_sm, workers_sm, logger)
740
776
  if workers_sm.is_crashlooping:
741
777
  return True
742
778
  return False
@@ -782,21 +818,19 @@ class CapsuleDeployer:
782
818
  minimum_replicas=min_replicas,
783
819
  )
784
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.
785
829
  for i in range(self._create_timeout):
786
830
  time.sleep(1)
787
- capsule_response = self.get()
788
- workers_response = self.get_workers()
789
-
790
- # We first need to check if someone has not upgraded the capsule under the hood and
791
- # the current deployment instance is invalid.
792
- self._backend_version_mismatch_check(
793
- 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
794
833
  )
795
- state_machine.add_status(capsule_response.get("status", {})) # type: ignore
796
- workers_state_machine.add_status(workers_response)
797
- state_machine.report_current_status(logger)
798
-
799
- workers_state_machine.report_current_status(logger)
800
834
  # Deployment readiness checks will determine what is the terminal state
801
835
  # of the workerstate machine. If we detect a terminal state in the workers,
802
836
  # then even if the capsule upgrade is still in progress we will end up crashing
@@ -839,7 +873,8 @@ class CapsuleDeployer:
839
873
  % self.identifier
840
874
  )
841
875
  _further_readiness_check_failed = self._monitor_worker_readiness(
842
- workers_state_machine
876
+ workers_state_machine,
877
+ state_machine,
843
878
  )
844
879
 
845
880
  if CAPSULE_DEBUG:
@@ -883,13 +918,18 @@ class CapsuleDeployer:
883
918
 
884
919
  break
885
920
 
886
- if CAPSULE_DEBUG and self._debug_dir:
887
- state_machine.save_debug_info(self._debug_dir)
888
- workers_state_machine.save_debug_info(self._debug_dir)
889
- if i % 3 == 0: # Every 3 seconds report the status
890
- logger(
891
- 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}"
892
- )
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
+ )
893
933
 
894
934
  # We will only check ready_to_serve_traffic under the following conditions:
895
935
  # If the readiness condition is not Async and min_replicas in this deployment
@@ -907,13 +947,6 @@ class CapsuleDeployer:
907
947
  f"Capsule {self.identifier} failed to be ready to serve traffic",
908
948
  )
909
949
 
910
- if CAPSULE_DEBUG and self._debug_dir:
911
- state_machine.save_debug_info(self._debug_dir)
912
- workers_state_machine.save_debug_info(self._debug_dir)
913
- logger(
914
- f"[debug] 💊 {self.capsule_type} {self.identifier} deployment status [on return]: {state_machine.current_status} | worker states: {workers_state_machine.current_status}"
915
- )
916
-
917
950
  return dict(
918
951
  id=self.identifier,
919
952
  auth_type=self.capsule_type,
@@ -441,6 +441,7 @@ class CodePackager:
441
441
  root,
442
442
  exclude_hidden=True,
443
443
  suffixes=None,
444
+ normalized_rel_path=False,
444
445
  ) -> List[Tuple[str, str]]:
445
446
  """
446
447
  Walk a directory and yield tuples of (file_path, relative_arcname) for files
@@ -456,6 +457,8 @@ class CodePackager:
456
457
  Whether to exclude hidden files and directories (those starting with '.')
457
458
  suffixes : List[str], optional
458
459
  List of file suffixes to include (e.g. ['.py', '.txt'])
460
+ normalized_rel_path : bool, default False
461
+ 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
462
 
460
463
  Returns
461
464
  -------
@@ -468,6 +471,8 @@ class CodePackager:
468
471
  for file_path, rel_path in symlink_friendly_walk(
469
472
  root, exclude_hidden, suffixes
470
473
  ):
474
+ if normalized_rel_path:
475
+ rel_path = file_path.replace(root, "")
471
476
  files.append((file_path, rel_path))
472
477
  return files
473
478
 
@@ -520,6 +525,7 @@ class CodePackager:
520
525
  path,
521
526
  exclude_hidden=True,
522
527
  suffixes=suffixes,
528
+ normalized_rel_path=True,
523
529
  ):
524
530
  tar.add(
525
531
  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
- src_path: Optional[str]
71
+ src_paths: Optional[list]
71
72
  suffixes: Optional[list]
72
73
 
73
74
 
@@ -222,6 +222,18 @@ class ResourceConfig(metaclass=ConfigMeta):
222
222
  parsing_fn=UnitParser("disk").parse,
223
223
  )
224
224
 
225
+ shared_memory = ConfigField(
226
+ cli_meta=CLIOption(
227
+ name="shared_memory",
228
+ cli_option_str="--shared-memory",
229
+ help="Shared memory resource request and limit.",
230
+ ),
231
+ field_type=str,
232
+ example="1Gi",
233
+ validation_fn=UnitParser.validation_wrapper_fn("memory"),
234
+ parsing_fn=UnitParser("memory").parse,
235
+ )
236
+
225
237
 
226
238
  class HealthCheckConfig(metaclass=ConfigMeta):
227
239
  """Health check configuration."""
@@ -541,14 +553,16 @@ class DependencyConfig(metaclass=ConfigMeta):
541
553
  class PackageConfig(metaclass=ConfigMeta):
542
554
  """Package configuration."""
543
555
 
544
- src_path = ConfigField(
556
+ src_paths = ConfigField(
545
557
  cli_meta=CLIOption(
546
558
  name="package_src_path",
547
559
  cli_option_str="--package-src-path",
560
+ multiple=True,
548
561
  help="The path to the source code to deploy with the App.",
562
+ click_type=str,
549
563
  ),
550
- field_type=str,
551
- example="./",
564
+ field_type=list,
565
+ example=["./"],
552
566
  )
553
567
  suffixes = ConfigField(
554
568
  cli_meta=CLIOption(
@@ -560,6 +574,28 @@ class PackageConfig(metaclass=ConfigMeta):
560
574
  example=[".py", ".ipynb"],
561
575
  )
562
576
 
577
+ @staticmethod
578
+ def validate(package_config: "PackageConfig"):
579
+ if package_config.src_paths is None:
580
+ return True
581
+ if package_config.src_paths:
582
+ for path in package_config.src_paths:
583
+ if not os.path.exists(path):
584
+ raise ConfigValidationFailedException(
585
+ field_name="src_paths",
586
+ field_info=package_config._get_field("src_paths"), # type: ignore
587
+ current_value=package_config.src_paths,
588
+ message=f"Path does not exist : `{path}`",
589
+ )
590
+ if not os.path.isdir(path):
591
+ raise ConfigValidationFailedException(
592
+ field_name="src_paths",
593
+ field_info=package_config._get_field("src_paths"), # type: ignore
594
+ current_value=package_config.src_paths,
595
+ message=f"Path is not a directory : `{path}`",
596
+ )
597
+ return True
598
+
563
599
 
564
600
  def everything_is_string(*args):
565
601
  return all(isinstance(arg, str) for arg in args)
@@ -852,6 +888,7 @@ How to read this schema:
852
888
  cli_meta=None, # No top-level CLI option, only nested fields have CLI options
853
889
  field_type=PackageConfig,
854
890
  help="Configurations associated with packaging the app.",
891
+ validation_fn=PackageConfig.validate,
855
892
  )
856
893
 
857
894
  no_deps = ConfigField(
@@ -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
@@ -218,7 +224,7 @@ properties:
218
224
  description: The Python version to use for the app.
219
225
  type: string
220
226
  example: '3.10'
221
- mutation_behavior: not_allowed
227
+ mutation_behavior: union
222
228
  cli_option: --python
223
229
  pypi:
224
230
  description: |-
@@ -247,10 +253,13 @@ properties:
247
253
  type: object
248
254
  required: []
249
255
  properties:
250
- src_path:
256
+ src_paths:
251
257
  description: The path to the source code to deploy with the App.
252
- type: string
253
- example: ./
258
+ type: array
259
+ items:
260
+ type: string
261
+ example:
262
+ - ./
254
263
  mutation_behavior: union
255
264
  cli_option: --package-src-path
256
265
  suffixes:
@@ -55,24 +55,31 @@ def _code_info(app_config: "AppConfig"):
55
55
  def _call_git(args, path=None):
56
56
  return "", 1, True
57
57
 
58
- repo_info = get_repository_info(app_config.get_state("packaging_directory", None))
59
- if len(repo_info) == 0:
58
+ package_dirs = app_config.get_state("packaging_directories")
59
+ if package_dirs is None:
60
60
  return None
61
+ for directory in package_dirs:
62
+ repo_info = get_repository_info(directory)
63
+ if len(repo_info) == 0:
64
+ continue
65
+ git_log_info, returncode, failed = _call_git(
66
+ ["log", "-1", "--pretty=%B"],
67
+ path=directory,
68
+ )
69
+ repo_url = repo_info["repo_url"]
70
+ if isinstance(repo_url, str):
71
+ _url = (
72
+ repo_url if not repo_url.endswith(".git") else repo_url.rstrip(".git")
73
+ )
74
+ else:
75
+ _url = str(repo_url)
76
+ _code_info = {
77
+ "commitId": repo_info["commit_sha"],
78
+ "commitLink": os.path.join(_url, "commit", str(repo_info["commit_sha"])),
79
+ }
80
+ if not failed and returncode == 0 and isinstance(git_log_info, str):
81
+ _code_info["commitMessage"] = git_log_info.strip()
61
82
 
62
- git_log_info, returncode, failed = _call_git(
63
- ["log", "-1", "--pretty=%B"],
64
- path=app_config.get_state("packaging_directory", None),
65
- )
66
- repo_url = repo_info["repo_url"]
67
- if isinstance(repo_url, str):
68
- _url = repo_url if not repo_url.endswith(".git") else repo_url.rstrip(".git")
69
- else:
70
- _url = str(repo_url)
71
- _code_info = {
72
- "commitId": repo_info["commit_sha"],
73
- "commitLink": os.path.join(_url, "commit", str(repo_info["commit_sha"])),
74
- }
75
- if not failed and returncode == 0 and isinstance(git_log_info, str):
76
- _code_info["commitMessage"] = git_log_info.strip()
83
+ return _code_info
77
84
 
78
- return _code_info
85
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob-metaflow-extensions
3
- Version: 1.4.11
3
+ Version: 1.4.12
4
4
  Summary: Outerbounds Platform Extensions for Metaflow
5
5
  Author: Outerbounds, Inc.
6
6
  License: Commercial
@@ -2,7 +2,7 @@ from setuptools import setup, find_namespace_packages
2
2
  from pathlib import Path
3
3
 
4
4
 
5
- version = "1.4.11"
5
+ version = "1.4.12"
6
6
  this_directory = Path(__file__).parent
7
7
  long_description = (this_directory / "README.md").read_text()
8
8