ob-metaflow 2.12.36.2__tar.gz → 2.12.39.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.

Potentially problematic release.


This version of ob-metaflow might be problematic. Click here for more details.

Files changed (374) hide show
  1. {ob_metaflow-2.12.36.2/ob_metaflow.egg-info → ob_metaflow-2.12.39.1}/PKG-INFO +2 -2
  2. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/argo_workflows_deployer_objects.py +42 -0
  3. ob_metaflow-2.12.39.1/metaflow/plugins/pypi/bootstrap.py +275 -0
  4. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/conda_environment.py +76 -21
  5. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/micromamba.py +42 -15
  6. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/pip.py +8 -3
  7. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/utils.py +5 -0
  8. ob_metaflow-2.12.39.1/metaflow/version.py +1 -0
  9. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1/ob_metaflow.egg-info}/PKG-INFO +2 -2
  10. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/ob_metaflow.egg-info/requires.txt +1 -1
  11. ob_metaflow-2.12.36.2/metaflow/plugins/pypi/bootstrap.py +0 -140
  12. ob_metaflow-2.12.36.2/metaflow/version.py +0 -1
  13. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/LICENSE +0 -0
  14. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/MANIFEST.in +0 -0
  15. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/README.md +0 -0
  16. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/R.py +0 -0
  17. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/__init__.py +0 -0
  18. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/__init__.py +0 -0
  19. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/__init__.py +0 -0
  20. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/_bashcomplete.py +0 -0
  21. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/_compat.py +0 -0
  22. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/_termui_impl.py +0 -0
  23. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/_textwrap.py +0 -0
  24. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/_unicodefun.py +0 -0
  25. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/_winconsole.py +0 -0
  26. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/core.py +0 -0
  27. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/decorators.py +0 -0
  28. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/exceptions.py +0 -0
  29. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/formatting.py +0 -0
  30. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/globals.py +0 -0
  31. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/parser.py +0 -0
  32. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/termui.py +0 -0
  33. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/testing.py +0 -0
  34. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/types.py +0 -0
  35. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/click/utils.py +0 -0
  36. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/__init__.py +0 -0
  37. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/_adapters.py +0 -0
  38. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/_collections.py +0 -0
  39. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/_compat.py +0 -0
  40. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/_functools.py +0 -0
  41. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/_itertools.py +0 -0
  42. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/_meta.py +0 -0
  43. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/_text.py +0 -0
  44. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/importlib_metadata/py.typed +0 -0
  45. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/__init__.py +0 -0
  46. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/_elffile.py +0 -0
  47. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/_manylinux.py +0 -0
  48. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/_musllinux.py +0 -0
  49. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/_parser.py +0 -0
  50. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/_structures.py +0 -0
  51. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/_tokenizer.py +0 -0
  52. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/markers.py +0 -0
  53. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/py.typed +0 -0
  54. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/requirements.py +0 -0
  55. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/specifiers.py +0 -0
  56. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/tags.py +0 -0
  57. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/utils.py +0 -0
  58. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/packaging/version.py +0 -0
  59. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/__init__.py +0 -0
  60. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_checkers.py +0 -0
  61. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_config.py +0 -0
  62. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_decorators.py +0 -0
  63. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_exceptions.py +0 -0
  64. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_functions.py +0 -0
  65. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_importhook.py +0 -0
  66. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_memo.py +0 -0
  67. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_pytest_plugin.py +0 -0
  68. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_suppression.py +0 -0
  69. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_transformer.py +0 -0
  70. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_union_transformer.py +0 -0
  71. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/_utils.py +0 -0
  72. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typeguard/py.typed +0 -0
  73. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/typing_extensions.py +0 -0
  74. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_5/__init__.py +0 -0
  75. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -0
  76. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -0
  77. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_5/zipp.py +0 -0
  78. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/__init__.py +0 -0
  79. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/__init__.py +0 -0
  80. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/_adapters.py +0 -0
  81. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/_collections.py +0 -0
  82. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/_compat.py +0 -0
  83. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/_functools.py +0 -0
  84. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/_itertools.py +0 -0
  85. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/_meta.py +0 -0
  86. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/_text.py +0 -0
  87. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/importlib_metadata/py.typed +0 -0
  88. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/typing_extensions.py +0 -0
  89. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/v3_6/zipp.py +0 -0
  90. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/_vendor/zipp.py +0 -0
  91. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cards.py +0 -0
  92. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli.py +0 -0
  93. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli_args.py +0 -0
  94. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli_components/__init__.py +0 -0
  95. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli_components/dump_cmd.py +0 -0
  96. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli_components/init_cmd.py +0 -0
  97. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli_components/run_cmds.py +0 -0
  98. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli_components/step_cmd.py +0 -0
  99. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cli_components/utils.py +0 -0
  100. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/client/__init__.py +0 -0
  101. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/client/core.py +0 -0
  102. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/client/filecache.py +0 -0
  103. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/clone_util.py +0 -0
  104. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/__init__.py +0 -0
  105. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/configure_cmd.py +0 -0
  106. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/develop/__init__.py +0 -0
  107. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/develop/stub_generator.py +0 -0
  108. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/develop/stubs.py +0 -0
  109. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/main_cli.py +0 -0
  110. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/tutorials_cmd.py +0 -0
  111. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd/util.py +0 -0
  112. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/cmd_with_io.py +0 -0
  113. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/__init__.py +0 -0
  114. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/content_addressed_store.py +0 -0
  115. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/datastore_set.py +0 -0
  116. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/datastore_storage.py +0 -0
  117. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/exceptions.py +0 -0
  118. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/flow_datastore.py +0 -0
  119. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/inputs.py +0 -0
  120. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/datastore/task_datastore.py +0 -0
  121. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/debug.py +0 -0
  122. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/decorators.py +0 -0
  123. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/event_logger.py +0 -0
  124. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/events.py +0 -0
  125. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/exception.py +0 -0
  126. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/extension_support/__init__.py +0 -0
  127. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/extension_support/_empty_file.py +0 -0
  128. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/extension_support/cmd.py +0 -0
  129. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/extension_support/integrations.py +0 -0
  130. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/extension_support/plugins.py +0 -0
  131. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/flowspec.py +0 -0
  132. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/graph.py +0 -0
  133. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/includefile.py +0 -0
  134. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/info_file.py +0 -0
  135. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/integrations.py +0 -0
  136. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/lint.py +0 -0
  137. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metadata_provider/__init__.py +0 -0
  138. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metadata_provider/heartbeat.py +0 -0
  139. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metadata_provider/metadata.py +0 -0
  140. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metadata_provider/util.py +0 -0
  141. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metaflow_config.py +0 -0
  142. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metaflow_config_funcs.py +0 -0
  143. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metaflow_current.py +0 -0
  144. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metaflow_environment.py +0 -0
  145. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metaflow_profile.py +0 -0
  146. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/metaflow_version.py +0 -0
  147. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/mflog/__init__.py +0 -0
  148. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/mflog/mflog.py +0 -0
  149. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/mflog/save_logs.py +0 -0
  150. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/mflog/save_logs_periodically.py +0 -0
  151. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/mflog/tee.py +0 -0
  152. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/monitor.py +0 -0
  153. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/multicore_utils.py +0 -0
  154. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/package.py +0 -0
  155. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/parameters.py +0 -0
  156. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/__init__.py +0 -0
  157. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/__init__.py +0 -0
  158. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/airflow.py +0 -0
  159. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/airflow_cli.py +0 -0
  160. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/airflow_decorator.py +0 -0
  161. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/airflow_utils.py +0 -0
  162. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/dag.py +0 -0
  163. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/exception.py +0 -0
  164. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/plumbing/__init__.py +0 -0
  165. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/plumbing/set_parameters.py +0 -0
  166. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/sensors/__init__.py +0 -0
  167. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/sensors/base_sensor.py +0 -0
  168. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/sensors/external_task_sensor.py +0 -0
  169. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/airflow/sensors/s3_sensor.py +0 -0
  170. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/__init__.py +0 -0
  171. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/argo_client.py +0 -0
  172. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/argo_events.py +0 -0
  173. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/argo_workflows.py +0 -0
  174. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/argo_workflows_cli.py +0 -0
  175. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/argo_workflows_decorator.py +0 -0
  176. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/argo_workflows_deployer.py +0 -0
  177. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/capture_error.py +0 -0
  178. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/generate_input_paths.py +0 -0
  179. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/argo/jobset_input_paths.py +0 -0
  180. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/__init__.py +0 -0
  181. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/aws_client.py +0 -0
  182. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/aws_utils.py +0 -0
  183. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/batch/__init__.py +0 -0
  184. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/batch/batch.py +0 -0
  185. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/batch/batch_cli.py +0 -0
  186. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/batch/batch_client.py +0 -0
  187. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/batch/batch_decorator.py +0 -0
  188. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/secrets_manager/__init__.py +0 -0
  189. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +0 -0
  190. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/__init__.py +0 -0
  191. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -0
  192. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/event_bridge_client.py +0 -0
  193. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/production_token.py +0 -0
  194. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/schedule_decorator.py +0 -0
  195. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/set_batch_environment.py +0 -0
  196. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/step_functions.py +0 -0
  197. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/step_functions_cli.py +0 -0
  198. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/step_functions_client.py +0 -0
  199. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/step_functions_decorator.py +0 -0
  200. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/step_functions_deployer.py +0 -0
  201. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +0 -0
  202. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/__init__.py +0 -0
  203. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/azure_credential.py +0 -0
  204. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/azure_exceptions.py +0 -0
  205. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +0 -0
  206. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/azure_tail.py +0 -0
  207. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/azure_utils.py +0 -0
  208. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/blob_service_client_factory.py +0 -0
  209. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/azure/includefile_support.py +0 -0
  210. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/__init__.py +0 -0
  211. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_cli.py +0 -0
  212. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_client.py +0 -0
  213. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_creator.py +0 -0
  214. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_datastore.py +0 -0
  215. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_decorator.py +0 -0
  216. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/__init__.py +0 -0
  217. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/base.html +0 -0
  218. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/basic.py +0 -0
  219. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/bundle.css +0 -0
  220. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/card.py +0 -0
  221. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/chevron/__init__.py +0 -0
  222. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/chevron/main.py +0 -0
  223. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/chevron/metadata.py +0 -0
  224. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/chevron/renderer.py +0 -0
  225. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/chevron/tokenizer.py +0 -0
  226. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/components.py +0 -0
  227. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/convert_to_native_type.py +0 -0
  228. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/main.js +0 -0
  229. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/renderer_tools.py +0 -0
  230. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_modules/test_cards.py +0 -0
  231. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_resolver.py +0 -0
  232. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_server.py +0 -0
  233. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/card_viewer/viewer.html +0 -0
  234. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/component_serializer.py +0 -0
  235. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/cards/exception.py +0 -0
  236. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/catch_decorator.py +0 -0
  237. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datastores/__init__.py +0 -0
  238. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datastores/azure_storage.py +0 -0
  239. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datastores/gs_storage.py +0 -0
  240. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datastores/local_storage.py +0 -0
  241. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datastores/s3_storage.py +0 -0
  242. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datatools/__init__.py +0 -0
  243. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datatools/local.py +0 -0
  244. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datatools/s3/__init__.py +0 -0
  245. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datatools/s3/s3.py +0 -0
  246. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datatools/s3/s3op.py +0 -0
  247. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datatools/s3/s3tail.py +0 -0
  248. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/datatools/s3/s3util.py +0 -0
  249. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/debug_logger.py +0 -0
  250. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/debug_monitor.py +0 -0
  251. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/__init__.py +0 -0
  252. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/client.py +0 -0
  253. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/client_modules.py +0 -0
  254. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/communication/__init__.py +0 -0
  255. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/communication/bytestream.py +0 -0
  256. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/communication/channel.py +0 -0
  257. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/communication/socket_bytestream.py +0 -0
  258. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/communication/utils.py +0 -0
  259. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/__init__.py +0 -0
  260. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +0 -0
  261. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +0 -0
  262. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/configurations/test_lib_impl/__init__.py +0 -0
  263. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +0 -0
  264. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/consts.py +0 -0
  265. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/data_transferer.py +0 -0
  266. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/exception_transferer.py +0 -0
  267. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/override_decorators.py +0 -0
  268. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/server.py +0 -0
  269. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/stub.py +0 -0
  270. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/env_escape/utils.py +0 -0
  271. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/environment_decorator.py +0 -0
  272. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/events_decorator.py +0 -0
  273. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/frameworks/__init__.py +0 -0
  274. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/frameworks/pytorch.py +0 -0
  275. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/gcp/__init__.py +0 -0
  276. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +0 -0
  277. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/gcp/gs_exceptions.py +0 -0
  278. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/gcp/gs_storage_client_factory.py +0 -0
  279. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/gcp/gs_tail.py +0 -0
  280. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/gcp/gs_utils.py +0 -0
  281. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/gcp/includefile_support.py +0 -0
  282. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/__init__.py +0 -0
  283. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/kube_utils.py +0 -0
  284. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/kubernetes.py +0 -0
  285. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/kubernetes_cli.py +0 -0
  286. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/kubernetes_client.py +0 -0
  287. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/kubernetes_decorator.py +0 -0
  288. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/kubernetes_job.py +0 -0
  289. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/kubernetes/kubernetes_jobsets.py +0 -0
  290. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/logs_cli.py +0 -0
  291. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/metadata_providers/__init__.py +0 -0
  292. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/metadata_providers/local.py +0 -0
  293. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/metadata_providers/service.py +0 -0
  294. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/package_cli.py +0 -0
  295. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/parallel_decorator.py +0 -0
  296. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/project_decorator.py +0 -0
  297. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/__init__.py +0 -0
  298. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/conda_decorator.py +0 -0
  299. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/pypi_decorator.py +0 -0
  300. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/pypi_environment.py +0 -0
  301. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/pypi/utils.py +0 -0
  302. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/resources_decorator.py +0 -0
  303. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/retry_decorator.py +0 -0
  304. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/secrets/__init__.py +0 -0
  305. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/secrets/inline_secrets_provider.py +0 -0
  306. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/secrets/secrets_decorator.py +0 -0
  307. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/storage_executor.py +0 -0
  308. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/tag_cli.py +0 -0
  309. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/test_unbounded_foreach_decorator.py +0 -0
  310. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/plugins/timeout_decorator.py +0 -0
  311. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/procpoll.py +0 -0
  312. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/py.typed +0 -0
  313. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/pylint_wrapper.py +0 -0
  314. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/__init__.py +0 -0
  315. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/click_api.py +0 -0
  316. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/deployer.py +0 -0
  317. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/deployer_impl.py +0 -0
  318. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/metaflow_runner.py +0 -0
  319. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/nbdeploy.py +0 -0
  320. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/nbrun.py +0 -0
  321. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runner/subprocess_manager.py +0 -0
  322. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/runtime.py +0 -0
  323. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/sidecar/__init__.py +0 -0
  324. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/sidecar/sidecar.py +0 -0
  325. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/sidecar/sidecar_messages.py +0 -0
  326. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/sidecar/sidecar_subprocess.py +0 -0
  327. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/sidecar/sidecar_worker.py +0 -0
  328. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/system/__init__.py +0 -0
  329. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/system/system_logger.py +0 -0
  330. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/system/system_monitor.py +0 -0
  331. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/system/system_utils.py +0 -0
  332. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tagging_util.py +0 -0
  333. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/task.py +0 -0
  334. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tracing/__init__.py +0 -0
  335. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tracing/propagator.py +0 -0
  336. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tracing/span_exporter.py +0 -0
  337. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tracing/tracing_modules.py +0 -0
  338. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tuple_util.py +0 -0
  339. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/00-helloworld/README.md +0 -0
  340. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/00-helloworld/helloworld.py +0 -0
  341. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/01-playlist/README.md +0 -0
  342. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/01-playlist/movies.csv +0 -0
  343. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/01-playlist/playlist.ipynb +0 -0
  344. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/01-playlist/playlist.py +0 -0
  345. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/02-statistics/README.md +0 -0
  346. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/02-statistics/movies.csv +0 -0
  347. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/02-statistics/stats.ipynb +0 -0
  348. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/02-statistics/stats.py +0 -0
  349. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/03-playlist-redux/README.md +0 -0
  350. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/03-playlist-redux/playlist.py +0 -0
  351. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/04-playlist-plus/README.md +0 -0
  352. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/04-playlist-plus/playlist.py +0 -0
  353. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/05-hello-cloud/README.md +0 -0
  354. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/05-hello-cloud/hello-cloud.ipynb +0 -0
  355. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/05-hello-cloud/hello-cloud.py +0 -0
  356. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/06-statistics-redux/README.md +0 -0
  357. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/06-statistics-redux/stats.ipynb +0 -0
  358. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/07-worldview/README.md +0 -0
  359. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/07-worldview/worldview.ipynb +0 -0
  360. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/08-autopilot/README.md +0 -0
  361. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/tutorials/08-autopilot/autopilot.ipynb +0 -0
  362. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/unbounded_foreach.py +0 -0
  363. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/user_configs/__init__.py +0 -0
  364. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/user_configs/config_decorators.py +0 -0
  365. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/user_configs/config_options.py +0 -0
  366. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/user_configs/config_parameters.py +0 -0
  367. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/util.py +0 -0
  368. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/metaflow/vendor.py +0 -0
  369. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/ob_metaflow.egg-info/SOURCES.txt +0 -0
  370. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/ob_metaflow.egg-info/dependency_links.txt +0 -0
  371. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/ob_metaflow.egg-info/entry_points.txt +0 -0
  372. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/ob_metaflow.egg-info/top_level.txt +0 -0
  373. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/setup.cfg +0 -0
  374. {ob_metaflow-2.12.36.2 → ob_metaflow-2.12.39.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob-metaflow
3
- Version: 2.12.36.2
3
+ Version: 2.12.39.1
4
4
  Summary: Metaflow: More Data Science, Less Engineering
5
5
  Author: Netflix, Outerbounds & the Metaflow Community
6
6
  Author-email: help@outerbounds.co
@@ -12,7 +12,7 @@ Requires-Dist: boto3
12
12
  Requires-Dist: pylint
13
13
  Requires-Dist: kubernetes
14
14
  Provides-Extra: stubs
15
- Requires-Dist: metaflow-stubs==2.12.36.2; extra == "stubs"
15
+ Requires-Dist: metaflow-stubs==2.12.39.1; extra == "stubs"
16
16
 
17
17
  ![Metaflow_Logo_Horizontal_FullColor_Ribbon_Dark_RGB](https://user-images.githubusercontent.com/763451/89453116-96a57e00-d713-11ea-9fa6-82b29d4d6eff.png)
18
18
 
@@ -1,5 +1,6 @@
1
1
  import sys
2
2
  import json
3
+ import time
3
4
  import tempfile
4
5
  from typing import ClassVar, Optional
5
6
 
@@ -170,6 +171,47 @@ class ArgoWorkflowsTriggeredRun(TriggeredRun):
170
171
  command_obj.sync_wait()
171
172
  return command_obj.process.returncode == 0
172
173
 
174
+ def wait_for_completion(self, timeout: Optional[int] = None):
175
+ """
176
+ Wait for the workflow to complete or timeout.
177
+
178
+ Parameters
179
+ ----------
180
+ timeout : int, optional, default None
181
+ Maximum time in seconds to wait for workflow completion.
182
+ If None, waits indefinitely.
183
+
184
+ Raises
185
+ ------
186
+ TimeoutError
187
+ If the workflow does not complete within the specified timeout period.
188
+ """
189
+ start_time = time.time()
190
+ check_interval = 5
191
+ while self.is_running:
192
+ if timeout is not None and (time.time() - start_time) > timeout:
193
+ raise TimeoutError(
194
+ "Workflow did not complete within specified timeout."
195
+ )
196
+ time.sleep(check_interval)
197
+
198
+ @property
199
+ def is_running(self):
200
+ """
201
+ Check if the workflow is currently running.
202
+
203
+ Returns
204
+ -------
205
+ bool
206
+ True if the workflow status is either 'Pending' or 'Running',
207
+ False otherwise.
208
+ """
209
+ workflow_status = self.status
210
+ # full list of all states present here:
211
+ # https://github.com/argoproj/argo-workflows/blob/main/pkg/apis/workflow/v1alpha1/workflow_types.go#L54
212
+ # we only consider non-terminal states to determine if the workflow has not finished
213
+ return workflow_status is not None and workflow_status in ["Pending", "Running"]
214
+
173
215
  @property
174
216
  def status(self) -> Optional[str]:
175
217
  """
@@ -0,0 +1,275 @@
1
+ import bz2
2
+ import concurrent.futures
3
+ import io
4
+ import json
5
+ import os
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ import tarfile
10
+ import time
11
+
12
+ import requests
13
+
14
+ from metaflow.metaflow_config import DATASTORE_LOCAL_DIR
15
+ from metaflow.plugins import DATASTORES
16
+ from metaflow.util import which
17
+
18
+ from . import MAGIC_FILE, _datastore_packageroot
19
+
20
+ # Bootstraps a valid conda virtual environment composed of conda and pypi packages
21
+
22
+
23
+ def timer(func):
24
+ def wrapper(*args, **kwargs):
25
+ start_time = time.time()
26
+ result = func(*args, **kwargs)
27
+ duration = time.time() - start_time
28
+ # print(f"Time taken for {func.__name__}: {duration:.2f} seconds")
29
+ return result
30
+
31
+ return wrapper
32
+
33
+
34
+ if __name__ == "__main__":
35
+ if len(sys.argv) != 5:
36
+ print("Usage: bootstrap.py <flow_name> <id> <datastore_type> <architecture>")
37
+ sys.exit(1)
38
+ _, flow_name, id_, datastore_type, architecture = sys.argv
39
+
40
+ # TODO: Detect architecture on the fly when dealing with arm architectures.
41
+ # ARCH=$(uname -m)
42
+ # OS=$(uname)
43
+
44
+ # if [[ "$OS" == "Linux" ]]; then
45
+ # PLATFORM="linux"
46
+ # if [[ "$ARCH" == "aarch64" ]]; then
47
+ # ARCH="aarch64";
48
+ # elif [[ $ARCH == "ppc64le" ]]; then
49
+ # ARCH="ppc64le";
50
+ # else
51
+ # ARCH="64";
52
+ # fi
53
+ # fi
54
+
55
+ # if [[ "$OS" == "Darwin" ]]; then
56
+ # PLATFORM="osx";
57
+ # if [[ "$ARCH" == "arm64" ]]; then
58
+ # ARCH="arm64";
59
+ # else
60
+ # ARCH="64"
61
+ # fi
62
+ # fi
63
+
64
+ prefix = os.path.join(os.getcwd(), architecture, id_)
65
+ pkgs_dir = os.path.join(os.getcwd(), ".pkgs")
66
+ conda_pkgs_dir = os.path.join(pkgs_dir, "conda")
67
+ pypi_pkgs_dir = os.path.join(pkgs_dir, "pypi")
68
+ manifest_dir = os.path.join(os.getcwd(), DATASTORE_LOCAL_DIR, flow_name)
69
+
70
+ datastores = [d for d in DATASTORES if d.TYPE == datastore_type]
71
+ if not datastores:
72
+ print(f"No datastore found for type: {datastore_type}")
73
+ sys.exit(1)
74
+
75
+ storage = datastores[0](
76
+ _datastore_packageroot(datastores[0], lambda *args, **kwargs: None)
77
+ )
78
+
79
+ # Move MAGIC_FILE inside local datastore.
80
+ os.makedirs(manifest_dir, exist_ok=True)
81
+ shutil.move(
82
+ os.path.join(os.getcwd(), MAGIC_FILE),
83
+ os.path.join(manifest_dir, MAGIC_FILE),
84
+ )
85
+ with open(os.path.join(manifest_dir, MAGIC_FILE)) as f:
86
+ env = json.load(f)[id_][architecture]
87
+
88
+ def run_cmd(cmd):
89
+ result = subprocess.run(
90
+ cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
91
+ )
92
+ if result.returncode != 0:
93
+ print(f"Bootstrap failed while executing: {cmd}")
94
+ print("Stdout:", result.stdout)
95
+ print("Stderr:", result.stderr)
96
+ sys.exit(1)
97
+
98
+ @timer
99
+ def install_micromamba(architecture):
100
+ micromamba_dir = os.path.join(os.getcwd(), "micromamba")
101
+ micromamba_path = os.path.join(micromamba_dir, "bin", "micromamba")
102
+
103
+ if which("micromamba"):
104
+ return which("micromamba")
105
+ if os.path.exists(micromamba_path):
106
+ os.environ["PATH"] += os.pathsep + os.path.dirname(micromamba_path)
107
+ return micromamba_path
108
+
109
+ # Download and extract in one go
110
+ # TODO: Serve from cloudflare
111
+ url = f"https://micro.mamba.pm/api/micromamba/{architecture}/2.0.4"
112
+
113
+ # Prepare directory once
114
+ os.makedirs(os.path.dirname(micromamba_path), exist_ok=True)
115
+
116
+ # Stream and process directly to file
117
+ with requests.get(url, stream=True, timeout=30) as response:
118
+ if response.status_code != 200:
119
+ raise Exception(
120
+ f"Failed to download micromamba: HTTP {response.status_code}"
121
+ )
122
+
123
+ decompressor = bz2.BZ2Decompressor()
124
+
125
+ # Process in memory without temporary files
126
+ tar_content = decompressor.decompress(response.raw.read())
127
+
128
+ with tarfile.open(fileobj=io.BytesIO(tar_content), mode="r:") as tar:
129
+ member = tar.getmember("bin/micromamba")
130
+ # Extract directly to final location
131
+ with open(micromamba_path, "wb") as f:
132
+ f.write(tar.extractfile(member).read())
133
+
134
+ # Set executable permission
135
+ os.chmod(micromamba_path, 0o755)
136
+
137
+ # Update PATH only once at the end
138
+ os.environ["PATH"] += os.pathsep + os.path.dirname(micromamba_path)
139
+ return micromamba_path
140
+
141
+ @timer
142
+ def download_conda_packages(storage, packages, dest_dir):
143
+
144
+ def process_conda_package(args):
145
+ # Ensure that conda packages go into architecture specific folders.
146
+ # The path looks like REPO/CHANNEL/CONDA_SUBDIR/PACKAGE. We trick
147
+ # Micromamba into believing that all packages are coming from a local
148
+ # channel - the only hurdle is ensuring that packages are organised
149
+ # properly.
150
+ key, tmpfile, dest_dir = args
151
+ dest = os.path.join(dest_dir, "/".join(key.split("/")[-2:]))
152
+ os.makedirs(os.path.dirname(dest), exist_ok=True)
153
+ shutil.move(tmpfile, dest)
154
+
155
+ os.makedirs(dest_dir, exist_ok=True)
156
+ with storage.load_bytes([package["path"] for package in packages]) as results:
157
+ with concurrent.futures.ThreadPoolExecutor() as executor:
158
+ executor.map(
159
+ process_conda_package,
160
+ [(key, tmpfile, dest_dir) for key, tmpfile, _ in results],
161
+ )
162
+ # for key, tmpfile, _ in results:
163
+
164
+ # # TODO: consider RAM disk
165
+ # dest = os.path.join(dest_dir, "/".join(key.split("/")[-2:]))
166
+ # os.makedirs(os.path.dirname(dest), exist_ok=True)
167
+ # shutil.move(tmpfile, dest)
168
+ return dest_dir
169
+
170
+ @timer
171
+ def download_pypi_packages(storage, packages, dest_dir):
172
+
173
+ def process_pypi_package(args):
174
+ key, tmpfile, dest_dir = args
175
+ dest = os.path.join(dest_dir, os.path.basename(key))
176
+ shutil.move(tmpfile, dest)
177
+
178
+ os.makedirs(dest_dir, exist_ok=True)
179
+ with storage.load_bytes([package["path"] for package in packages]) as results:
180
+ with concurrent.futures.ThreadPoolExecutor() as executor:
181
+ executor.map(
182
+ process_pypi_package,
183
+ [(key, tmpfile, dest_dir) for key, tmpfile, _ in results],
184
+ )
185
+ # for key, tmpfile, _ in results:
186
+ # dest = os.path.join(dest_dir, os.path.basename(key))
187
+ # shutil.move(tmpfile, dest)
188
+ return dest_dir
189
+
190
+ @timer
191
+ def create_conda_environment(prefix, conda_pkgs_dir):
192
+ cmd = f'''set -e;
193
+ tmpfile=$(mktemp);
194
+ echo "@EXPLICIT" > "$tmpfile";
195
+ ls -d {conda_pkgs_dir}/*/* >> "$tmpfile";
196
+ export PATH=$PATH:$(pwd)/micromamba;
197
+ export CONDA_PKGS_DIRS=$(pwd)/micromamba/pkgs;
198
+ export MAMBA_NO_LOW_SPEED_LIMIT=1;
199
+ export MAMBA_USE_INDEX_CACHE=1;
200
+ export MAMBA_NO_PROGRESS_BARS=1;
201
+ export CONDA_FETCH_THREADS=1;
202
+ micromamba create --yes --offline --no-deps \
203
+ --safety-checks=disabled --no-extra-safety-checks \
204
+ --prefix {prefix} --file "$tmpfile" \
205
+ --no-pyc --no-rc --always-copy;
206
+ rm "$tmpfile"'''
207
+ run_cmd(cmd)
208
+
209
+ @timer
210
+ def install_pypi_packages(prefix, pypi_pkgs_dir):
211
+
212
+ cmd = f"""set -e;
213
+ export PATH=$PATH:$(pwd)/micromamba;
214
+ export CONDA_PKGS_DIRS=$(pwd)/micromamba/pkgs;
215
+ micromamba run --prefix {prefix} python -m pip --disable-pip-version-check \
216
+ install --root-user-action=ignore --no-compile --no-index \
217
+ --no-cache-dir --no-deps --prefer-binary \
218
+ --find-links={pypi_pkgs_dir} --no-user \
219
+ --no-warn-script-location --no-input \
220
+ {pypi_pkgs_dir}/*.whl
221
+ """
222
+ run_cmd(cmd)
223
+
224
+ @timer
225
+ def setup_environment(
226
+ architecture, storage, env, prefix, conda_pkgs_dir, pypi_pkgs_dir
227
+ ):
228
+ with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
229
+ # install micromamba, download conda and pypi packages in parallel
230
+ futures = {
231
+ "micromamba": executor.submit(install_micromamba, architecture),
232
+ "conda_pkgs": executor.submit(
233
+ download_conda_packages, storage, env["conda"], conda_pkgs_dir
234
+ ),
235
+ }
236
+ if "pypi" in env:
237
+ futures["pypi_pkgs"] = executor.submit(
238
+ download_pypi_packages, storage, env["pypi"], pypi_pkgs_dir
239
+ )
240
+
241
+ # create conda environment after micromamba is installed and conda packages are downloaded
242
+ done, _ = concurrent.futures.wait(
243
+ [futures["micromamba"], futures["conda_pkgs"]],
244
+ return_when=concurrent.futures.ALL_COMPLETED,
245
+ )
246
+
247
+ for future in done:
248
+ future.result()
249
+
250
+ # start conda environment creation
251
+ futures["conda_env"] = executor.submit(
252
+ create_conda_environment, prefix, conda_pkgs_dir
253
+ )
254
+
255
+ if "pypi" in env:
256
+ # install pypi packages after conda environment is created and pypi packages are downloaded
257
+ done, _ = concurrent.futures.wait(
258
+ [futures["conda_env"], futures["pypi_pkgs"]],
259
+ return_when=concurrent.futures.ALL_COMPLETED,
260
+ )
261
+
262
+ for future in done:
263
+ future.result()
264
+
265
+ # install pypi packages
266
+ futures["pypi_install"] = executor.submit(
267
+ install_pypi_packages, prefix, pypi_pkgs_dir
268
+ )
269
+ # wait for pypi packages to be installed
270
+ futures["pypi_install"].result()
271
+ else:
272
+ # wait for conda environment to be created
273
+ futures["conda_env"].result()
274
+
275
+ setup_environment(architecture, storage, env, prefix, conda_pkgs_dir, pypi_pkgs_dir)
@@ -5,10 +5,11 @@ import functools
5
5
  import io
6
6
  import json
7
7
  import os
8
- import sys
9
8
  import tarfile
9
+ import threading
10
10
  import time
11
- from concurrent.futures import ThreadPoolExecutor
11
+ from concurrent.futures import ThreadPoolExecutor, as_completed
12
+ from functools import wraps
12
13
  from hashlib import sha256
13
14
  from io import BufferedIOBase, BytesIO
14
15
  from itertools import chain
@@ -50,7 +51,6 @@ class CondaEnvironment(MetaflowEnvironment):
50
51
 
51
52
  def validate_environment(self, logger, datastore_type):
52
53
  self.datastore_type = datastore_type
53
- self.logger = logger
54
54
 
55
55
  # Avoiding circular imports.
56
56
  from metaflow.plugins import DATASTORES
@@ -62,8 +62,21 @@ class CondaEnvironment(MetaflowEnvironment):
62
62
  from .micromamba import Micromamba
63
63
  from .pip import Pip
64
64
 
65
- micromamba = Micromamba()
66
- self.solvers = {"conda": micromamba, "pypi": Pip(micromamba)}
65
+ print_lock = threading.Lock()
66
+
67
+ def make_thread_safe(func):
68
+ @wraps(func)
69
+ def wrapper(*args, **kwargs):
70
+ with print_lock:
71
+ return func(*args, **kwargs)
72
+
73
+ return wrapper
74
+
75
+ self.logger = make_thread_safe(logger)
76
+
77
+ # TODO: Wire up logging
78
+ micromamba = Micromamba(self.logger)
79
+ self.solvers = {"conda": micromamba, "pypi": Pip(micromamba, self.logger)}
67
80
 
68
81
  def init_environment(self, echo, only_steps=None):
69
82
  # The implementation optimizes for latency to ensure as many operations can
@@ -150,6 +163,9 @@ class CondaEnvironment(MetaflowEnvironment):
150
163
  (
151
164
  package["path"],
152
165
  # Lazily fetch package from the interweb if needed.
166
+ # TODO: Depending on the len_hint, the package might be downloaded from
167
+ # the interweb prematurely. save_bytes needs to be adjusted to handle
168
+ # this scenario.
153
169
  LazyOpen(
154
170
  package["local_path"],
155
171
  "rb",
@@ -166,22 +182,60 @@ class CondaEnvironment(MetaflowEnvironment):
166
182
  if id_ in dirty:
167
183
  self.write_to_environment_manifest([id_, platform, type_], packages)
168
184
 
169
- # First resolve environments through Conda, before PyPI.
185
+ storage = None
186
+ if self.datastore_type not in ["local"]:
187
+ # Initialize storage for caching if using a remote datastore
188
+ storage = self.datastore(_datastore_packageroot(self.datastore, echo))
189
+
170
190
  self.logger("Bootstrapping virtual environment(s) ...")
171
- for solver in ["conda", "pypi"]:
172
- with ThreadPoolExecutor() as executor:
173
- results = list(
174
- executor.map(lambda x: solve(*x, solver), environments(solver))
175
- )
176
- _ = list(map(lambda x: self.solvers[solver].download(*x), results))
177
- with ThreadPoolExecutor() as executor:
178
- _ = list(
179
- executor.map(lambda x: self.solvers[solver].create(*x), results)
180
- )
181
- if self.datastore_type not in ["local"]:
182
- # Cache packages only when a remote datastore is in play.
183
- storage = self.datastore(_datastore_packageroot(self.datastore, echo))
184
- cache(storage, results, solver)
191
+ # Sequence of operations:
192
+ # 1. Start all conda solves in parallel
193
+ # 2. Download conda packages sequentially
194
+ # 3. Create and cache conda environments in parallel
195
+ # 4. Start PyPI solves in parallel after each conda environment is created
196
+ # 5. Download PyPI packages sequentially
197
+ # 6. Create and cache PyPI environments in parallel
198
+
199
+ with ThreadPoolExecutor() as executor:
200
+ # Start all conda solves in parallel
201
+ conda_futures = [
202
+ executor.submit(lambda x: solve(*x, "conda"), env)
203
+ for env in environments("conda")
204
+ ]
205
+
206
+ pypi_envs = {env[0]: env for env in environments("pypi")}
207
+ pypi_futures = []
208
+
209
+ # Process conda results sequentially for downloads
210
+ for future in as_completed(conda_futures):
211
+ result = future.result()
212
+ # Sequential conda download
213
+ self.solvers["conda"].download(*result)
214
+ # Parallel conda create and cache
215
+ create_future = executor.submit(self.solvers["conda"].create, *result)
216
+ if storage:
217
+ executor.submit(cache, storage, [result], "conda")
218
+
219
+ # Queue PyPI solve to start after conda create
220
+ if result[0] in pypi_envs:
221
+
222
+ def pypi_solve(env):
223
+ create_future.result() # Wait for conda create
224
+ return solve(*env, "pypi")
225
+
226
+ pypi_futures.append(
227
+ executor.submit(pypi_solve, pypi_envs[result[0]])
228
+ )
229
+
230
+ # Process PyPI results sequentially for downloads
231
+ for solve_future in pypi_futures:
232
+ result = solve_future.result()
233
+ # Sequential PyPI download
234
+ self.solvers["pypi"].download(*result)
235
+ # Parallel PyPI create and cache
236
+ executor.submit(self.solvers["pypi"].create, *result)
237
+ if storage:
238
+ executor.submit(cache, storage, [result], "pypi")
185
239
  self.logger("Virtual environment(s) bootstrapped!")
186
240
 
187
241
  def executable(self, step_name, default=None):
@@ -385,7 +439,8 @@ class CondaEnvironment(MetaflowEnvironment):
385
439
  'DISABLE_TRACING=True python -m metaflow.plugins.pypi.bootstrap "%s" %s "%s" linux-64'
386
440
  % (self.flow.name, id_, self.datastore_type),
387
441
  "echo 'Environment bootstrapped.'",
388
- "export PATH=$PATH:$(pwd)/micromamba",
442
+ # To avoid having to install micromamba in the PATH in micromamba.py, we add it to the PATH here.
443
+ "export PATH=$PATH:$(pwd)/micromamba/bin",
389
444
  ]
390
445
  else:
391
446
  # for @conda/@pypi(disabled=True).
@@ -1,7 +1,9 @@
1
+ import functools
1
2
  import json
2
3
  import os
3
4
  import subprocess
4
5
  import tempfile
6
+ import time
5
7
 
6
8
  from metaflow.exception import MetaflowException
7
9
  from metaflow.util import which
@@ -19,8 +21,11 @@ class MicromambaException(MetaflowException):
19
21
  super(MicromambaException, self).__init__(msg)
20
22
 
21
23
 
24
+ GLIBC_VERSION = os.environ.get("CONDA_OVERRIDE_GLIBC", "2.38")
25
+
26
+
22
27
  class Micromamba(object):
23
- def __init__(self):
28
+ def __init__(self, logger=None):
24
29
  # micromamba is a tiny version of the mamba package manager and comes with
25
30
  # metaflow specific performance enhancements.
26
31
 
@@ -33,6 +38,12 @@ class Micromamba(object):
33
38
  os.path.expanduser(_home),
34
39
  "micromamba",
35
40
  )
41
+
42
+ if logger:
43
+ self.logger = logger
44
+ else:
45
+ self.logger = lambda *args, **kwargs: None # No-op logger if not provided
46
+
36
47
  self.bin = (
37
48
  which(os.environ.get("METAFLOW_PATH_TO_MICROMAMBA") or "micromamba")
38
49
  or which("./micromamba") # to support remote execution
@@ -70,6 +81,9 @@ class Micromamba(object):
70
81
  "MAMBA_ADD_PIP_AS_PYTHON_DEPENDENCY": "true",
71
82
  "CONDA_SUBDIR": platform,
72
83
  # "CONDA_UNSATISFIABLE_HINTS_CHECK_DEPTH": "0" # https://github.com/conda/conda/issues/9862
84
+ # Add a default glibc version for linux-64 environments (ignored for other platforms)
85
+ # TODO: Make the version configurable
86
+ "CONDA_OVERRIDE_GLIBC": GLIBC_VERSION,
73
87
  }
74
88
  cmd = [
75
89
  "create",
@@ -78,6 +92,7 @@ class Micromamba(object):
78
92
  "--dry-run",
79
93
  "--no-extra-safety-checks",
80
94
  "--repodata-ttl=86400",
95
+ "--safety-checks=disabled",
81
96
  "--retry-clean-cache",
82
97
  "--prefix=%s/prefix" % tmp_dir,
83
98
  ]
@@ -91,10 +106,11 @@ class Micromamba(object):
91
106
  cmd.append("python==%s" % python)
92
107
  # TODO: Ensure a human readable message is returned when the environment
93
108
  # can't be resolved for any and all reasons.
94
- return [
109
+ solved_packages = [
95
110
  {k: v for k, v in item.items() if k in ["url"]}
96
111
  for item in self._call(cmd, env)["actions"]["LINK"]
97
112
  ]
113
+ return solved_packages
98
114
 
99
115
  def download(self, id_, packages, python, platform):
100
116
  # Unfortunately all the packages need to be catalogued in package cache
@@ -103,8 +119,6 @@ class Micromamba(object):
103
119
  # Micromamba is painfully slow in determining if many packages are infact
104
120
  # already cached. As a perf heuristic, we check if the environment already
105
121
  # exists to short circuit package downloads.
106
- if self.path_to_environment(id_, platform):
107
- return
108
122
 
109
123
  prefix = "{env_dirs}/{keyword}/{platform}/{id}".format(
110
124
  env_dirs=self.info()["envs_dirs"][0],
@@ -113,13 +127,18 @@ class Micromamba(object):
113
127
  id=id_,
114
128
  )
115
129
 
116
- # Another forced perf heuristic to skip cross-platform downloads.
130
+ # cheap check
117
131
  if os.path.exists(f"{prefix}/fake.done"):
118
132
  return
119
133
 
134
+ # somewhat expensive check
135
+ if self.path_to_environment(id_, platform):
136
+ return
137
+
120
138
  with tempfile.TemporaryDirectory() as tmp_dir:
121
139
  env = {
122
140
  "CONDA_SUBDIR": platform,
141
+ "CONDA_OVERRIDE_GLIBC": GLIBC_VERSION,
123
142
  }
124
143
  cmd = [
125
144
  "create",
@@ -159,6 +178,7 @@ class Micromamba(object):
159
178
  # use hardlinks when possible, otherwise copy files
160
179
  # disabled for now since it adds to environment creation latencies
161
180
  "CONDA_ALLOW_SOFTLINKS": "0",
181
+ "CONDA_OVERRIDE_GLIBC": GLIBC_VERSION,
162
182
  }
163
183
  cmd = [
164
184
  "create",
@@ -174,6 +194,7 @@ class Micromamba(object):
174
194
  cmd.append("{url}".format(**package))
175
195
  self._call(cmd, env)
176
196
 
197
+ @functools.lru_cache(maxsize=None)
177
198
  def info(self):
178
199
  return self._call(["config", "list", "-a"])
179
200
 
@@ -198,18 +219,24 @@ class Micromamba(object):
198
219
  }
199
220
  directories = self.info()["pkgs_dirs"]
200
221
  # search all package caches for packages
201
- metadata = {
202
- url: os.path.join(d, file)
222
+
223
+ file_to_path = {}
224
+ for d in directories:
225
+ if os.path.isdir(d):
226
+ try:
227
+ with os.scandir(d) as entries:
228
+ for entry in entries:
229
+ if entry.is_file():
230
+ # Prefer the first occurrence if the file exists in multiple directories
231
+ file_to_path.setdefault(entry.name, entry.path)
232
+ except OSError:
233
+ continue
234
+ ret = {
235
+ # set package tarball local paths to None if package tarballs are missing
236
+ url: file_to_path.get(file)
203
237
  for url, file in packages_to_filenames.items()
204
- for d in directories
205
- if os.path.isdir(d)
206
- and file in os.listdir(d)
207
- and os.path.isfile(os.path.join(d, file))
208
238
  }
209
- # set package tarball local paths to None if package tarballs are missing
210
- for url in packages_to_filenames:
211
- metadata.setdefault(url, None)
212
- return metadata
239
+ return ret
213
240
 
214
241
  def interpreter(self, id_):
215
242
  return os.path.join(self.path_to_environment(id_), "bin/python")
@@ -4,6 +4,7 @@ import re
4
4
  import shutil
5
5
  import subprocess
6
6
  import tempfile
7
+ import time
7
8
  from concurrent.futures import ThreadPoolExecutor
8
9
  from itertools import chain, product
9
10
  from urllib.parse import unquote
@@ -50,10 +51,14 @@ INSTALLATION_MARKER = "{prefix}/.pip/id"
50
51
 
51
52
 
52
53
  class Pip(object):
53
- def __init__(self, micromamba=None):
54
+ def __init__(self, micromamba=None, logger=None):
54
55
  # pip is assumed to be installed inside a conda environment managed by
55
56
  # micromamba. pip commands are executed using `micromamba run --prefix`
56
- self.micromamba = micromamba or Micromamba()
57
+ self.micromamba = micromamba or Micromamba(logger)
58
+ if logger:
59
+ self.logger = logger
60
+ else:
61
+ self.logger = lambda *args, **kwargs: None # No-op logger if not provided
57
62
 
58
63
  def solve(self, id_, packages, python, platform):
59
64
  prefix = self.micromamba.path_to_environment(id_)
@@ -123,7 +128,7 @@ class Pip(object):
123
128
  **res,
124
129
  subdir_str=(
125
130
  "#subdirectory=%s" % subdirectory if subdirectory else ""
126
- )
131
+ ),
127
132
  )
128
133
  # used to deduplicate the storage location in case wheel does not
129
134
  # build with enough unique identifiers.
@@ -111,6 +111,11 @@ def read_from_fifo_when_ready(
111
111
  poll.register(fifo_fd, select.POLLIN)
112
112
  max_timeout = 3 # Wait for 10 * 3 = 30 ms after last write
113
113
  while True:
114
+ if check_process_exited(command_obj) and command_obj.process.returncode != 0:
115
+ raise CalledProcessError(
116
+ command_obj.process.returncode, command_obj.command
117
+ )
118
+
114
119
  if timeout < 0:
115
120
  raise TimeoutError("Timeout while waiting for the file content")
116
121
 
@@ -0,0 +1 @@
1
+ metaflow_version = "2.12.39.1"