ob-metaflow-extensions 1.2.10__tar.gz → 1.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/PKG-INFO +1 -1
  2. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/__init__.py +3 -0
  3. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/_state_machine.py +9 -9
  4. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/app_cli.py +8 -8
  5. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/capsule.py +10 -12
  6. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/dependencies.py +1 -1
  7. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/secrets.py +1 -1
  8. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/utils.py +2 -2
  9. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/aws/assume_role_decorator.py +25 -12
  10. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +71 -0
  11. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/external_chckpt.py +85 -0
  12. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +73 -0
  13. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/fast_bakery/docker_environment.py +6 -2
  14. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/s3_proxy/__init__.py +7 -0
  15. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/s3_proxy/constants.py +8 -0
  16. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/s3_proxy/exceptions.py +13 -0
  17. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_api.py +93 -0
  18. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_decorator.py +106 -0
  19. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/plugins/s3_proxy/s3_proxy_manager.py +222 -0
  20. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/global_aliases_for_metaflow_package.py +33 -1
  21. ob_metaflow_extensions-1.3.1/metaflow_extensions/outerbounds/toplevel/s3_proxy.py +88 -0
  22. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/ob_metaflow_extensions.egg-info/PKG-INFO +1 -1
  23. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/ob_metaflow_extensions.egg-info/SOURCES.txt +8 -0
  24. ob_metaflow_extensions-1.3.1/ob_metaflow_extensions.egg-info/requires.txt +3 -0
  25. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/setup.py +2 -2
  26. ob_metaflow_extensions-1.2.10/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/coreweave.py +0 -139
  27. ob_metaflow_extensions-1.2.10/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/nebius.py +0 -144
  28. ob_metaflow_extensions-1.2.10/ob_metaflow_extensions.egg-info/requires.txt +0 -3
  29. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/MANIFEST.in +0 -0
  30. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/README.md +0 -0
  31. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/__init__.py +0 -0
  32. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/config/__init__.py +0 -0
  33. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/__init__.py +0 -0
  34. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/app_cli.py +0 -0
  35. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/app_deploy_decorator.py +0 -0
  36. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/app_utils.py +0 -0
  37. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/consts.py +0 -0
  38. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/__init__.py +0 -0
  39. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/__init__.py +0 -0
  40. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/__init__.py +0 -0
  41. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/_vendor/spinner/spinners.py +0 -0
  42. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/app_config.py +0 -0
  43. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/artifacts.py +0 -0
  44. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/click_importer.py +0 -0
  45. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/__init__.py +0 -0
  46. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/code_packager.py +0 -0
  47. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/code_package/examples.py +0 -0
  48. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config/__init__.py +0 -0
  49. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config/cli_generator.py +0 -0
  50. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config/config_utils.py +0 -0
  51. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config/schema_export.py +0 -0
  52. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config/typed_configs.py +0 -0
  53. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config/typed_init_generator.py +0 -0
  54. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config/unified_config.py +0 -0
  55. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/config_schema.yaml +0 -0
  56. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/deployer.py +0 -0
  57. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/experimental/__init__.py +0 -0
  58. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/perimeters.py +0 -0
  59. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/core/validations.py +0 -0
  60. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/deploy_decorator.py +0 -0
  61. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/apps/supervisord_utils.py +0 -0
  62. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/auth_server.py +0 -0
  63. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/aws/__init__.py +0 -0
  64. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/aws/assume_role.py +0 -0
  65. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/card_utilities/__init__.py +0 -0
  66. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/card_utilities/async_cards.py +0 -0
  67. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/card_utilities/extra_components.py +0 -0
  68. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/card_utilities/injector.py +0 -0
  69. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/checkpoint_datastores/__init__.py +0 -0
  70. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/fast_bakery/__init__.py +0 -0
  71. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/fast_bakery/baker.py +0 -0
  72. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery.py +0 -0
  73. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_cli.py +0 -0
  74. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/fast_bakery/fast_bakery_decorator.py +0 -0
  75. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/kubernetes/__init__.py +0 -0
  76. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/kubernetes/kubernetes_client.py +0 -0
  77. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/kubernetes/pod_killer.py +0 -0
  78. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nim/card.py +0 -0
  79. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nim/nim_decorator.py +0 -0
  80. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nim/nim_manager.py +0 -0
  81. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nim/utils.py +0 -0
  82. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/__init__.py +0 -0
  83. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/constants.py +0 -0
  84. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/exceptions.py +0 -0
  85. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/heartbeat_store.py +0 -0
  86. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf.py +0 -0
  87. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_cli.py +0 -0
  88. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/nvcf_decorator.py +0 -0
  89. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvcf/utils.py +0 -0
  90. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvct/__init__.py +0 -0
  91. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvct/exceptions.py +0 -0
  92. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvct/nvct.py +0 -0
  93. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvct/nvct_cli.py +0 -0
  94. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvct/nvct_decorator.py +0 -0
  95. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvct/nvct_runner.py +0 -0
  96. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/nvct/utils.py +0 -0
  97. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/ollama/__init__.py +0 -0
  98. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/ollama/constants.py +0 -0
  99. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/ollama/exceptions.py +0 -0
  100. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/ollama/ollama.py +0 -0
  101. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/ollama/status_card.py +0 -0
  102. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/perimeters.py +0 -0
  103. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/profilers/deco_injector.py +0 -0
  104. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/profilers/gpu_profile_decorator.py +0 -0
  105. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/profilers/simple_card_decorator.py +0 -0
  106. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/secrets/__init__.py +0 -0
  107. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/secrets/secrets.py +0 -0
  108. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowflake/__init__.py +0 -0
  109. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowflake/snowflake.py +0 -0
  110. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/__init__.py +0 -0
  111. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark.py +0 -0
  112. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_cli.py +0 -0
  113. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_client.py +0 -0
  114. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_decorator.py +0 -0
  115. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_exceptions.py +0 -0
  116. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_job.py +0 -0
  117. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/snowpark/snowpark_service_spec.py +0 -0
  118. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/tensorboard/__init__.py +0 -0
  119. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/torchtune/__init__.py +0 -0
  120. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/vllm/__init__.py +0 -0
  121. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/vllm/constants.py +0 -0
  122. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/vllm/exceptions.py +0 -0
  123. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/vllm/status_card.py +0 -0
  124. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/plugins/vllm/vllm_manager.py +0 -0
  125. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/profilers/__init__.py +0 -0
  126. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/profilers/gpu.py +0 -0
  127. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/remote_config.py +0 -0
  128. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/__init__.py +0 -0
  129. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/ob_internal.py +0 -0
  130. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/plugins/azure/__init__.py +0 -0
  131. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/plugins/gcp/__init__.py +0 -0
  132. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/plugins/kubernetes/__init__.py +0 -0
  133. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/plugins/ollama/__init__.py +0 -0
  134. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/plugins/snowflake/__init__.py +0 -0
  135. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/plugins/torchtune/__init__.py +0 -0
  136. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/metaflow_extensions/outerbounds/toplevel/plugins/vllm/__init__.py +0 -0
  137. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/ob_metaflow_extensions.egg-info/dependency_links.txt +0 -0
  138. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/ob_metaflow_extensions.egg-info/top_level.txt +0 -0
  139. {ob_metaflow_extensions-1.2.10 → ob_metaflow_extensions-1.3.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob_metaflow_extensions
3
- Version: 1.2.10
3
+ Version: 1.3.1
4
4
  Summary: Outerbounds Platform Extensions for Metaflow
5
5
  Author: Outerbounds, Inc.
6
6
  License: Commercial
@@ -340,6 +340,9 @@ STEP_DECORATORS_DESC = [
340
340
  ("ollama", ".ollama.OllamaDecorator"),
341
341
  ("vllm", ".vllm.VLLMDecorator"),
342
342
  ("app_deploy", ".apps.app_deploy_decorator.AppDeployDecorator"),
343
+ ("s3_proxy", ".s3_proxy.s3_proxy_decorator.S3ProxyDecorator"),
344
+ ("nebius_s3_proxy", ".s3_proxy.s3_proxy_decorator.NebiusS3ProxyDecorator"),
345
+ ("coreweave_s3_proxy", ".s3_proxy.s3_proxy_decorator.CoreWeaveS3ProxyDecorator"),
343
346
  ]
344
347
 
345
348
  TOGGLE_STEP_DECORATOR = [
@@ -199,29 +199,29 @@ class DEPLOYMENT_READY_CONDITIONS:
199
199
  This allows users or platform designers to configure the criteria for deployment readiness.
200
200
 
201
201
  Why do we need deployment readiness conditions?
202
- - Deployments might be taking place from a CI/CD esq environment, In these setups, the downstream build triggers might be depending on a specific criteria for deployment completion. Having readiness conditions allows the CI/CD systems to get a signal of when the deployment is ready.
202
+ - Deployments might be taking place from a CI/CD-esque environment, In these setups, the downstream build triggers might be depending on a specific criteria for deployment completion. Having readiness conditions allows the CI/CD systems to get a signal of when the deployment is ready.
203
203
  - Users might be calling the deployment API under different conditions:
204
204
  - Some users might want a cluster of workers ready before serving traffic while others might want just one worker ready to start serving traffic.
205
205
 
206
206
  Some readiness conditions include:
207
- 1) [at_least_one_running] Atleast min(min_replicas, 1) workers of the current deployment instance's version have started running.
207
+ 1) [at_least_one_running] At least min(min_replicas, 1) workers of the current deployment instance's version have started running.
208
208
  - Usecase: Some endpoints may be deployed ephemerally and are considered ready when at least one instance is running; additional instances are for load management.
209
- 2) [all_running] Atleast min_replicas number of workers are running for the deployment to be considered ready.
209
+ 2) [all_running] At least min_replicas number of workers are running for the deployment to be considered ready.
210
210
  - Usecase: Operators may require that all replicas are available before traffic is routed. Needed when inference endpoints maybe under some SLA or require a larger load
211
- 3) [fully_finished] Atleast min_replicas number of workers are running for the deployment and there are no pending or crashlooping workers from previous versions lying around.
211
+ 3) [fully_finished] At least min_replicas number of workers are running for the deployment and there are no pending or crashlooping workers from previous versions lying around.
212
212
  - Usecase: Ensuring endpoint is fully available and no other versions are running or endpoint has been fully scaled down.
213
213
  4) [async] The deployment will be assumed ready as soon as the server responds with a 200.
214
214
  - Usecase: Operators may only care that the URL is minted for the deployment or the deployment eventually scales down to 0.
215
215
  """
216
216
 
217
- # `ATLEAST_ONE_RUNNING` implies that atleast one worker of the current deployment instance's version has started running.
217
+ # `ATLEAST_ONE_RUNNING` implies that at least one worker of the current deployment instance's version has started running.
218
218
  ATLEAST_ONE_RUNNING = "at_least_one_running"
219
219
 
220
220
  # `ALL_RUNNING` implies that all workers of the current deployment instance's version have started running (i.e. all workers aligning to the minimum number of replicas).
221
221
  # It doesn't imply that all the workers relating to other deployments have been torn down.
222
222
  ALL_RUNNING = "all_running"
223
223
 
224
- # `FULLY_FINISHED` implies Atleast min_replicas number of workers are running for the deployment and there are no pending or crashlooping workers from previous versions lying around.
224
+ # `FULLY_FINISHED` implies at least min_replicas number of workers are running for the deployment and there are no pending or crashlooping workers from previous versions lying around.
225
225
  FULLY_FINISHED = "fully_finished"
226
226
 
227
227
  # `ASYNC` implies that the deployment will be assumed ready after the URL is minted and the worker statuses are not checked.
@@ -447,9 +447,9 @@ def _capsule_worker_semantic_status(
447
447
  crashlooping_workers = _make_version_dict(workers, "CrashLoopBackOff")
448
448
 
449
449
  # current_status (formulated basis):
450
- # - atleast one pods are pending for `_end_state_capsule_version`
451
- # - atleast one pod is in Running state for `_end_state_capsule_version` (maybe terminal) [Might require heath-check thing here]
452
- # - alteast one pod is crashlooping for `_end_state_capsule_version` (maybe terminal)
450
+ # - at least one pods are pending for `_end_state_capsule_version`
451
+ # - at least one pod is in Running state for `_end_state_capsule_version` (maybe terminal) [Might require health-check thing here]
452
+ # - at least one pod is crashlooping for `_end_state_capsule_version` (maybe terminal)
453
453
  # - all pods are running for `_end_state_capsule_version` that match the minimum number of replicas
454
454
  # - all pods are running for `_end_state_capsule_version` that match the maximum number of replicas and no other pods of older versions are running
455
455
  # - no pods relating to `_end_state_capsule_version` are pending/running/crashlooping
@@ -239,7 +239,7 @@ def _bake_image(app_config: AppConfig, cache_dir: str, logger):
239
239
  baking_status.resolved_image,
240
240
  )
241
241
  app_config.set_state("python_path", baking_status.python_path)
242
- logger("🐳 Using The Docker Image : %s" % app_config.get_state("image"))
242
+ logger("🐳 Using the docker image : %s" % app_config.get_state("image"))
243
243
 
244
244
 
245
245
  def print_table(data, headers):
@@ -374,7 +374,7 @@ def _package_necessary_things(app_config: AppConfig, logger):
374
374
  # or is it relative to where the caller command is sitting. Ideally it should work
375
375
  # like Kustomizations where its relative to where the yaml file sits for simplicity
376
376
  # of understanding relationships between config files. Ideally users can pass the src_path
377
- # from the command line and that will aliviate any need to package any other directories for
377
+ # from the command line and that will alleviate any need to package any other directories for
378
378
  #
379
379
 
380
380
  package_dir = app_config.get_state("packaging_directory")
@@ -395,7 +395,7 @@ def _package_necessary_things(app_config: AppConfig, logger):
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
- logger("💾 Code Package Saved to : %s" % app_config.get_state("code_package_url"))
398
+ logger("💾 Code package saved to : %s" % app_config.get_state("code_package_url"))
399
399
 
400
400
 
401
401
  @app.command(help="Deploy an app to the Outerbounds Platform.")
@@ -465,7 +465,7 @@ def deploy(
465
465
 
466
466
  app_config.set_state("packaging_directory", packaging_directory)
467
467
  logger(
468
- "📦 Packaging Directory : %s" % app_config.get_state("packaging_directory"),
468
+ "📦 Packaging directory : %s" % app_config.get_state("packaging_directory"),
469
469
  )
470
470
 
471
471
  if app_config.get("no_deps", False):
@@ -611,7 +611,7 @@ def deploy(
611
611
  )
612
612
  raise AppConfigError(message)
613
613
  capsule_logger(
614
- f"🚀 {'' if not force_upgrade else 'Force'} Upgrading {capsule.capsule_type.lower()} `{capsule.name}`....",
614
+ f"🚀 {'Upgrading' if not force_upgrade else 'Force upgrading'} {capsule.capsule_type.lower()} `{capsule.name}`....",
615
615
  color=ColorTheme.INFO_COLOR,
616
616
  system_msg=True,
617
617
  )
@@ -632,7 +632,7 @@ def deploy(
632
632
  capsule_spinner.stop()
633
633
 
634
634
  logger(
635
- f"💊 {capsule.capsule_type} {app_config.config['name']} ({capsule.identifier}) deployed! {capsule.capsule_type} exposed on the URL: {capsule.url}",
635
+ f"💊 {capsule.capsule_type} {app_config.config['name']} ({capsule.identifier}) deployed! {capsule.capsule_type} available on the URL: {capsule.url}",
636
636
  color=ColorTheme.INFO_COLOR,
637
637
  system_msg=True,
638
638
  )
@@ -761,7 +761,7 @@ def list(ctx, project, branch, name, tags, format, auth_type):
761
761
  def delete(ctx, name, cap_id, project, branch, tags, auto_approve):
762
762
 
763
763
  """Delete an app/apps from the Outerbounds Platform."""
764
- # Atleast one of the args need to be provided
764
+ # At least one of the args need to be provided
765
765
  if not any(
766
766
  [
767
767
  name is not None,
@@ -772,7 +772,7 @@ def delete(ctx, name, cap_id, project, branch, tags, auto_approve):
772
772
  ]
773
773
  ):
774
774
  raise AppConfigError(
775
- "Atleast one of the options need to be provided. You can use --name, --id, --project, --branch, --tag"
775
+ "At least one of the options need to be provided. You can use --name, --id, --project, --branch, --tag"
776
776
  )
777
777
 
778
778
  capsule_api = CapsuleApi(ctx.obj.api_url, ctx.obj.perimeter)
@@ -44,24 +44,24 @@ class CapsuleStateMachine:
44
44
  - Happy Path:
45
45
  - First time Create :
46
46
  - wait for status.updateInProgress to be set to False
47
- - (interleved) Poll the worker endpoints to check their status
47
+ - (interleaved) Poll the worker endpoints to check their status
48
48
  - showcase how many workers are coming up if things are on the cli side.
49
49
  - If the user has set some flag like `--dont-wait-to-fully-finish` then we check the `status.currentlyServedVersion` to see if even one replica is ready to
50
50
  serve traffic.
51
51
  - once the status.updateInProgress is set to False, it means that the replicas are ready
52
52
  - Upgrade:
53
53
  - wait for status.updateInProgress to be set to False
54
- - (interleved) Poll the worker endpoints to check their status and signal the user the number replicas coming up
54
+ - (interleaved) Poll the worker endpoints to check their status and signal the user the number replicas coming up
55
55
  - If the user has set some flag like `--dont-wait-to-fully-finish` then we check the `status.currentlyServedVersion` to see if even one replica is ready to
56
56
  serve traffic.
57
57
  - Unhappy Path:
58
58
  - First time Create :
59
59
  - wait for status.updateInProgress to be set to False,
60
- - (interleved) Poll the workers to check their status.
60
+ - (interleaved) Poll the workers to check their status.
61
61
  - If the worker pertaining the current deployment instance version is crashlooping then crash the deployment process with the error messages and logs.
62
62
  - Upgrade:
63
63
  - wait for status.updateInProgress to be set to False,
64
- - (interleved) Poll the workers to check their status.
64
+ - (interleaved) Poll the workers to check their status.
65
65
  - If the worker pertaining the current deployment instance version is crashlooping then crash the deployment process with the error messages and logs.
66
66
 
67
67
  """
@@ -210,9 +210,9 @@ class CapsuleInput:
210
210
  def construct_exec_command(cls, commands: List[str]):
211
211
  commands = ["set -eEuo pipefail"] + commands
212
212
  command_string = "\n".join(commands)
213
- # First constuct a base64 encoded string of the quoted command
213
+ # First construct a base64 encoded string of the quoted command
214
214
  # One of the reasons we don't directly pass the command string to the backend with a `\n` join
215
- # is because the backend controller doesnt play nice when the command can be a multi-line string.
215
+ # is because the backend controller doesn't play nice when the command can be a multi-line string.
216
216
  # So we encode it to a base64 string and then decode it back to a command string at runtime to provide to
217
217
  # `bash -c`. The ideal thing to have done is to run "bash -c {shlex.quote(command_string)}" and call it a day
218
218
  # but the backend controller yields the following error:
@@ -682,7 +682,7 @@ class CapsuleDeployer:
682
682
  """
683
683
  - `capsule_response.version` contains the version of the object present in the database
684
684
  - `current_deployment_instance_version` contains the version of the object that was deployed by this instance of the deployer.
685
- In the situtation that the versions of the objects become a mismatch then it means that current deployment process is not giving the user the
685
+ In the situation that the versions of the objects become a mismatch then it means that current deployment process is not giving the user the
686
686
  output that they desire.
687
687
  """
688
688
  if capsule_response.get("version", None) != current_deployment_instance_version:
@@ -783,24 +783,22 @@ class CapsuleDeployer:
783
783
  )
784
784
  if capsule_ready or failure_condition_satisfied:
785
785
  logger(
786
- "💊 %s deployment status: %s | worker states: [success :%s | failure :%s ] "
786
+ "💊 %s deployment status: %s "
787
787
  % (
788
788
  self.capsule_type.title(),
789
789
  "in progress"
790
790
  if state_machine.update_in_progress
791
791
  else "completed",
792
- capsule_ready,
793
- failure_condition_satisfied,
794
792
  )
795
793
  )
796
794
  _further_readiness_check_failed = False
797
795
  if further_check_worker_readiness:
798
796
  # HACK : monitor the workers for N seconds to make sure they are healthy
799
- # this is a hack. Ideally we should implment a healtcheck as a first class citizen
797
+ # this is a hack. Ideally we should implement a healthcheck as a first class citizen
800
798
  # but it will take some time to do that so in the meanwhile a timeout set on the cli
801
799
  # side will be really helpful.
802
800
  logger(
803
- "💊 running last minute readiness check for %s..."
801
+ "💊 Running last minute readiness check for %s..."
804
802
  % self.identifier
805
803
  )
806
804
  _further_readiness_check_failed = self._monitor_worker_readiness(
@@ -95,7 +95,7 @@ def bake_deployment_image(
95
95
  pinned_conda_libs = get_pinned_conda_libs(python_version, DEFAULT_DATASTORE)
96
96
  pypi_packages.update(pinned_conda_libs)
97
97
  _reference = app_config.get("name", "default")
98
- # `image` cannot be None. If by change it is none, FB will fart.
98
+ # `image` cannot be None. If by chance it is none, FB will fart.
99
99
  fb_response = bake_image(
100
100
  cache_file_path=cache_file_path,
101
101
  pypi_packages=pypi_packages,
@@ -116,7 +116,7 @@ class SecretRetriever:
116
116
 
117
117
  if not perimeter:
118
118
  raise OuterboundsSecretsException(
119
- "No perimeter set. Please make sure to run `outerbounds configure <...>` command which can be found on the Ourebounds UI or reach out to your Outerbounds support team."
119
+ "No perimeter set. Please make sure to run `outerbounds configure <...>` command which can be found on the Outerbounds UI or reach out to your Outerbounds support team."
120
120
  )
121
121
 
122
122
  if not integrations_url:
@@ -185,8 +185,8 @@ def safe_requests_wrapper(
185
185
  - How to handle retries for this case will be application specific.
186
186
  2. Errors when the API server may not be reachable (DNS resolution / network issues)
187
187
  - In this scenario, we know that something external to the API server is going wrong causing the issue.
188
- - Failing pre-maturely in the case might not be the best course of action since critical user jobs might crash on intermittent issues.
189
- - So in this case, we can just planely retry the request.
188
+ - Failing prematurely in the case might not be the best course of action since critical user jobs might crash on intermittent issues.
189
+ - So in this case, we can just plainly retry the request.
190
190
 
191
191
  This function handles the second case. It's a simple wrapper to handle the retry logic for connection errors.
192
192
  If this function is provided a `conn_error_retries` of 5, then the last retry will have waited 32 seconds.
@@ -1,12 +1,10 @@
1
- from metaflow.user_configs.config_decorators import (
2
- MutableFlow,
3
- MutableStep,
4
- CustomFlowDecorator,
5
- )
1
+ from metaflow.user_decorators.mutable_flow import MutableFlow
2
+ from metaflow.user_decorators.mutable_step import MutableStep
3
+ from metaflow.user_decorators.user_flow_decorator import FlowMutator
6
4
  from .assume_role import OBP_ASSUME_ROLE_ARN_ENV_VAR
7
5
 
8
6
 
9
- class assume_role(CustomFlowDecorator):
7
+ class assume_role(FlowMutator):
10
8
  """
11
9
  Flow-level decorator for assuming AWS IAM roles.
12
10
 
@@ -42,7 +40,7 @@ class assume_role(CustomFlowDecorator):
42
40
  "`role_arn` must be a valid AWS IAM role ARN starting with 'arn:aws:iam::'"
43
41
  )
44
42
 
45
- def evaluate(self, mutable_flow: MutableFlow) -> None:
43
+ def pre_mutate(self, mutable_flow: MutableFlow) -> None:
46
44
  """
47
45
  This method is called by Metaflow to apply the decorator to the flow.
48
46
  It sets up environment variables that will be used by the AWS client
@@ -51,14 +49,29 @@ class assume_role(CustomFlowDecorator):
51
49
  # Import environment decorator at runtime to avoid circular imports
52
50
  from metaflow import environment
53
51
 
52
+ def _swap_environment_variables(step: MutableStep, role_arn: str) -> None:
53
+ _step_has_env_set = True
54
+ _env_kwargs = {OBP_ASSUME_ROLE_ARN_ENV_VAR: role_arn}
55
+ for d in step.decorator_specs:
56
+ name, _, _, deco_kwargs = d
57
+ if name == "environment":
58
+ _env_kwargs.update(deco_kwargs["vars"])
59
+ _step_has_env_set = True
60
+
61
+ if _step_has_env_set:
62
+ # remove the environment decorator
63
+ step.remove_decorator("environment")
64
+
65
+ # add the environment decorator
66
+ step.add_decorator(
67
+ environment,
68
+ deco_kwargs=dict(vars=_env_kwargs),
69
+ )
70
+
54
71
  # Set the role ARN as an environment variable that will be picked up
55
72
  # by the get_aws_client function
56
73
  def _setup_role_assumption(step: MutableStep) -> None:
57
- # We'll inject the role assumption by adding an environment decorator
58
- # The role will be available through an environment variable
59
- step.add_decorator(
60
- environment, vars={OBP_ASSUME_ROLE_ARN_ENV_VAR: self.role_arn}
61
- )
74
+ _swap_environment_variables(step, self.role_arn)
62
75
 
63
76
  # Apply the role assumption setup to all steps in the flow
64
77
  for _, step in mutable_flow.steps:
@@ -0,0 +1,71 @@
1
+ from metaflow.user_decorators.user_flow_decorator import FlowMutator
2
+ from metaflow.user_decorators.mutable_flow import MutableFlow
3
+ from metaflow.user_decorators.mutable_step import MutableStep
4
+ from .external_chckpt import _ExternalCheckpointFlowDeco
5
+ import os
6
+
7
+
8
+ class coreweave_checkpoints(_ExternalCheckpointFlowDeco):
9
+
10
+ """
11
+
12
+ This decorator is used for setting the coreweave object store as the artifact store for checkpoints/models created by the flow.
13
+
14
+ Parameters
15
+ ----------
16
+ secrets: list
17
+ A list of secrets to be added to the step. These secrets should contain any secrets that are required globally and the secret
18
+ for the coreweave object store. The secret should contain the following keys:
19
+ - COREWEAVE_ACCESS_KEY
20
+ - COREWEAVE_SECRET_KEY
21
+
22
+ bucket_path: str
23
+ The path to the bucket to store the checkpoints/models.
24
+
25
+ Usage
26
+ -----
27
+ ```python
28
+ from metaflow import checkpoint, step, FlowSpec, coreweave_checkpoints
29
+
30
+ @coreweave_checkpoints(secrets=[], bucket_path=None)
31
+ class MyFlow(FlowSpec):
32
+ @checkpoint
33
+ @step
34
+ def start(self):
35
+ # Saves the checkpoint in the coreweave object store
36
+ current.checkpoint.save("./foo.txt")
37
+
38
+ @step
39
+ def end(self):
40
+ pass
41
+ ```
42
+ """
43
+
44
+ def __init__(self, *args, **kwargs):
45
+ super().__init__(*args, **kwargs)
46
+
47
+ def init(self, *args, **kwargs):
48
+ super().init(*args, **kwargs)
49
+ self.coreweave_endpoint_url = f"https://cwobject.com"
50
+
51
+ def pre_mutate(self, mutable_flow: MutableFlow) -> None:
52
+ from metaflow import (
53
+ with_artifact_store,
54
+ )
55
+
56
+ def _coreweave_config():
57
+ return {
58
+ "root": self.bucket_path,
59
+ "client_params": {
60
+ "aws_access_key_id": os.environ.get("COREWEAVE_ACCESS_KEY"),
61
+ "aws_secret_access_key": os.environ.get("COREWEAVE_SECRET_KEY"),
62
+ "endpoint_url": self.coreweave_endpoint_url,
63
+ "config": dict(s3={"addressing_style": "virtual"}),
64
+ },
65
+ }
66
+
67
+ mutable_flow.add_decorator(
68
+ with_artifact_store,
69
+ deco_kwargs=dict(type="coreweave", config=_coreweave_config),
70
+ )
71
+ self._swap_secrets(mutable_flow)
@@ -0,0 +1,85 @@
1
+ from metaflow.user_decorators.user_flow_decorator import FlowMutator
2
+ from metaflow.user_decorators.mutable_flow import MutableFlow
3
+ from metaflow.user_decorators.mutable_step import MutableStep
4
+ import os
5
+
6
+
7
+ class _ExternalCheckpointFlowDeco(FlowMutator):
8
+ def init(self, *args, **kwargs):
9
+ self.bucket_path = kwargs.get("bucket_path", None)
10
+
11
+ self.secrets = kwargs.get("secrets", [])
12
+ if self.bucket_path is None:
13
+ raise ValueError(
14
+ "`bucket_path` keyword argument is required for the coreweave_datastore"
15
+ )
16
+ if not self.bucket_path.startswith("s3://"):
17
+ raise ValueError(
18
+ "`bucket_path` must start with `s3://` for the coreweave_datastore"
19
+ )
20
+ if self.secrets is None:
21
+ raise ValueError(
22
+ "`secrets` keyword argument is required for the coreweave_datastore"
23
+ )
24
+
25
+ def _swap_secrets(self, mutable_flow: MutableFlow) -> None:
26
+ from metaflow import (
27
+ checkpoint,
28
+ model,
29
+ huggingface_hub,
30
+ secrets,
31
+ with_artifact_store,
32
+ )
33
+
34
+ def _add_secrets(step: MutableStep) -> None:
35
+ decos_to_add = []
36
+ swapping_decos = {
37
+ "huggingface_hub": huggingface_hub,
38
+ "model": model,
39
+ "checkpoint": checkpoint,
40
+ }
41
+ already_has_secrets = False
42
+ secrets_present_in_deco = []
43
+ for d in step.decorator_specs:
44
+ name, _, _, deco_kwargs = d
45
+ if name in swapping_decos:
46
+ decos_to_add.append((name, deco_kwargs))
47
+ elif name == "secrets":
48
+ already_has_secrets = True
49
+ secrets_present_in_deco.extend(deco_kwargs["sources"])
50
+
51
+ # If the step aleady has secrets then take all the sources in
52
+ # the secrets and add the addtional secrets to the existing secrets
53
+ secrets_to_add = self.secrets
54
+ if already_has_secrets:
55
+ secrets_to_add.extend(secrets_present_in_deco)
56
+
57
+ secrets_to_add = list(set(secrets_to_add))
58
+
59
+ if len(decos_to_add) == 0:
60
+ if already_has_secrets:
61
+ step.remove_decorator("secrets")
62
+
63
+ step.add_decorator(
64
+ secrets,
65
+ deco_kwargs=dict(
66
+ sources=secrets_to_add,
67
+ ),
68
+ )
69
+ return
70
+
71
+ for d, _ in decos_to_add:
72
+ step.remove_decorator(d)
73
+
74
+ step.add_decorator(
75
+ secrets,
76
+ deco_kwargs=dict(
77
+ sources=secrets_to_add,
78
+ ),
79
+ )
80
+ for d, attrs in decos_to_add:
81
+ _deco_to_add = swapping_decos[d]
82
+ step.add_decorator(_deco_to_add, deco_kwargs=attrs)
83
+
84
+ for step_name, step in mutable_flow.steps:
85
+ _add_secrets(step)
@@ -0,0 +1,73 @@
1
+ from metaflow.user_decorators.mutable_flow import MutableFlow
2
+ from .external_chckpt import _ExternalCheckpointFlowDeco
3
+ import os
4
+
5
+ NEBIUS_ENDPOINT_URL = "https://storage.eu-north1.nebius.cloud:443"
6
+
7
+
8
+ class nebius_checkpoints(_ExternalCheckpointFlowDeco):
9
+
10
+ """
11
+
12
+ This decorator is used for setting the nebius's S3 compatible object store as the artifact store for
13
+ checkpoints/models created by the flow.
14
+
15
+ Parameters
16
+ ----------
17
+ secrets: list
18
+ A list of secrets to be added to the step. These secrets should contain any secrets that are required globally and the secret
19
+ for the nebius object store. The secret should contain the following keys:
20
+ - NEBIUS_ACCESS_KEY
21
+ - NEBIUS_SECRET_KEY
22
+
23
+ bucket_path: str
24
+ The path to the bucket to store the checkpoints/models.
25
+
26
+ endpoint_url: str
27
+ The endpoint url for the nebius object store. Defaults to `https://storage.eu-north1.nebius.cloud:443`
28
+
29
+ Usage
30
+ -----
31
+ ```python
32
+ from metaflow import checkpoint, step, FlowSpec, nebius_checkpoints
33
+
34
+ @nebius_checkpoints(secrets=[], bucket_path=None)
35
+ class MyFlow(FlowSpec):
36
+ @checkpoint
37
+ @step
38
+ def start(self):
39
+ # Saves the checkpoint in the nebius object store
40
+ current.checkpoint.save("./foo.txt")
41
+
42
+ @step
43
+ def end(self):
44
+ pass
45
+ ```
46
+ """
47
+
48
+ def __init__(self, *args, **kwargs):
49
+ super().__init__(*args, **kwargs)
50
+
51
+ def init(self, *args, **kwargs):
52
+ super().init(*args, **kwargs)
53
+ self.nebius_endpoint_url = kwargs.get("endpoint_url", NEBIUS_ENDPOINT_URL)
54
+
55
+ def pre_mutate(self, mutable_flow: MutableFlow) -> None:
56
+ from metaflow import (
57
+ with_artifact_store,
58
+ )
59
+
60
+ def _nebius_config():
61
+ return {
62
+ "root": self.bucket_path,
63
+ "client_params": {
64
+ "aws_access_key_id": os.environ.get("NEBIUS_ACCESS_KEY"),
65
+ "aws_secret_access_key": os.environ.get("NEBIUS_SECRET_KEY"),
66
+ "endpoint_url": self.nebius_endpoint_url,
67
+ },
68
+ }
69
+
70
+ mutable_flow.add_decorator(
71
+ with_artifact_store, deco_kwargs=dict(type="s3", config=_nebius_config)
72
+ )
73
+ self._swap_secrets(mutable_flow)
@@ -351,12 +351,16 @@ class DockerEnvironment(MetaflowEnvironment):
351
351
  config.append("--disable=F0401")
352
352
  return config
353
353
 
354
- def get_package_commands(self, codepackage_url, datastore_type):
354
+ def get_package_commands(
355
+ self, codepackage_url, datastore_type, code_package_metadata=None
356
+ ):
355
357
  # we must set the skip install flag at this stage in order to skip package downloads,
356
358
  # doing so in bootstrap_commands is too late in the lifecycle.
357
359
  return [
358
360
  "export METAFLOW_SKIP_INSTALL_DEPENDENCIES=$FASTBAKERY_IMAGE",
359
- ] + super().get_package_commands(codepackage_url, datastore_type)
361
+ ] + super().get_package_commands(
362
+ codepackage_url, datastore_type, code_package_metadata=code_package_metadata
363
+ )
360
364
 
361
365
  def bootstrap_commands(self, step_name, datastore_type):
362
366
  if step_name in self.skipped_steps:
@@ -0,0 +1,7 @@
1
+ from .s3_proxy_decorator import (
2
+ S3ProxyDecorator,
3
+ NebiusS3ProxyDecorator,
4
+ CoreWeaveS3ProxyDecorator,
5
+ )
6
+
7
+ __all__ = ["S3ProxyDecorator", "NebiusS3ProxyDecorator", "CoreWeaveS3ProxyDecorator"]
@@ -0,0 +1,8 @@
1
+ S3_PROXY_BINARY_URLS = {
2
+ "aarch64": "https://fast-s3-proxy.outerbounds.sh/linux-arm64/s3-proxy-0.1.1.gz",
3
+ "x86_64": "https://fast-s3-proxy.outerbounds.sh/linux-amd64/s3-proxy-0.1.1.gz",
4
+ }
5
+
6
+ DEFAULT_PROXY_PORT = 8081
7
+ DEFAULT_PROXY_HOST = "localhost"
8
+ S3_PROXY_WRITE_MODES = ["origin-and-cache", "origin", "cache"]
@@ -0,0 +1,13 @@
1
+ from metaflow.exception import MetaflowException
2
+
3
+
4
+ class S3ProxyException(MetaflowException):
5
+ headline = "S3 Proxy Error"
6
+
7
+
8
+ class S3ProxyConfigException(S3ProxyException):
9
+ headline = "S3 Proxy Configuration Error"
10
+
11
+
12
+ class S3ProxyApiException(S3ProxyException):
13
+ headline = "S3 Proxy API Error"