metaflow 2.15.7__tar.gz → 2.15.9__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 (411) hide show
  1. {metaflow-2.15.7/metaflow.egg-info → metaflow-2.15.9}/PKG-INFO +2 -2
  2. {metaflow-2.15.7 → metaflow-2.15.9}/devtools/Makefile +2 -0
  3. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli.py +8 -0
  4. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli_components/run_cmds.py +2 -2
  5. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/main_cli.py +1 -1
  6. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metadata_provider/metadata.py +35 -0
  7. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metaflow_config.py +6 -0
  8. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metaflow_environment.py +6 -1
  9. metaflow-2.15.9/metaflow/metaflow_git.py +115 -0
  10. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metaflow_version.py +2 -2
  11. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/__init__.py +1 -0
  12. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/argo_workflows.py +43 -6
  13. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/argo_workflows_cli.py +11 -0
  14. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/aws_client.py +4 -3
  15. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datatools/s3/s3.py +46 -44
  16. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datatools/s3/s3op.py +133 -63
  17. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/kubernetes.py +4 -0
  18. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/kubernetes_cli.py +8 -0
  19. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/kubernetes_decorator.py +10 -0
  20. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/kubernetes_job.py +8 -0
  21. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/kubernetes_jobsets.py +7 -0
  22. metaflow-2.15.9/metaflow/plugins/uv/bootstrap.py +100 -0
  23. metaflow-2.15.9/metaflow/plugins/uv/uv_environment.py +70 -0
  24. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/deployer.py +8 -2
  25. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/deployer_impl.py +6 -2
  26. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/metaflow_runner.py +7 -2
  27. metaflow-2.15.9/metaflow/user_configs/__init__.py +0 -0
  28. metaflow-2.15.9/metaflow/version.py +1 -0
  29. {metaflow-2.15.7 → metaflow-2.15.9/metaflow.egg-info}/PKG-INFO +2 -2
  30. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow.egg-info/SOURCES.txt +4 -0
  31. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow.egg-info/requires.txt +1 -1
  32. metaflow-2.15.7/metaflow/version.py +0 -1
  33. {metaflow-2.15.7 → metaflow-2.15.9}/LICENSE +0 -0
  34. {metaflow-2.15.7 → metaflow-2.15.9}/MANIFEST.in +0 -0
  35. {metaflow-2.15.7 → metaflow-2.15.9}/README.md +0 -0
  36. {metaflow-2.15.7 → metaflow-2.15.9}/devtools/Tiltfile +0 -0
  37. {metaflow-2.15.7 → metaflow-2.15.9}/devtools/pick_services.sh +0 -0
  38. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/R.py +0 -0
  39. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/__init__.py +0 -0
  40. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/__init__.py +0 -0
  41. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/__init__.py +0 -0
  42. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/_bashcomplete.py +0 -0
  43. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/_compat.py +0 -0
  44. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/_termui_impl.py +0 -0
  45. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/_textwrap.py +0 -0
  46. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/_unicodefun.py +0 -0
  47. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/_winconsole.py +0 -0
  48. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/core.py +0 -0
  49. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/decorators.py +0 -0
  50. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/exceptions.py +0 -0
  51. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/formatting.py +0 -0
  52. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/globals.py +0 -0
  53. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/parser.py +0 -0
  54. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/termui.py +0 -0
  55. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/testing.py +0 -0
  56. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/types.py +0 -0
  57. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/click/utils.py +0 -0
  58. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/__init__.py +0 -0
  59. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/_adapters.py +0 -0
  60. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/_collections.py +0 -0
  61. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/_compat.py +0 -0
  62. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/_functools.py +0 -0
  63. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/_itertools.py +0 -0
  64. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/_meta.py +0 -0
  65. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/_text.py +0 -0
  66. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/importlib_metadata/py.typed +0 -0
  67. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/__init__.py +0 -0
  68. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/_elffile.py +0 -0
  69. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/_manylinux.py +0 -0
  70. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/_musllinux.py +0 -0
  71. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/_parser.py +0 -0
  72. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/_structures.py +0 -0
  73. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/_tokenizer.py +0 -0
  74. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/markers.py +0 -0
  75. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/py.typed +0 -0
  76. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/requirements.py +0 -0
  77. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/specifiers.py +0 -0
  78. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/tags.py +0 -0
  79. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/utils.py +0 -0
  80. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/packaging/version.py +0 -0
  81. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/__init__.py +0 -0
  82. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_checkers.py +0 -0
  83. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_config.py +0 -0
  84. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_decorators.py +0 -0
  85. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_exceptions.py +0 -0
  86. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_functions.py +0 -0
  87. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_importhook.py +0 -0
  88. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_memo.py +0 -0
  89. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_pytest_plugin.py +0 -0
  90. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_suppression.py +0 -0
  91. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_transformer.py +0 -0
  92. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_union_transformer.py +0 -0
  93. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/_utils.py +0 -0
  94. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typeguard/py.typed +0 -0
  95. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/typing_extensions.py +0 -0
  96. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_5/__init__.py +0 -0
  97. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -0
  98. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -0
  99. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_5/zipp.py +0 -0
  100. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/__init__.py +0 -0
  101. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/__init__.py +0 -0
  102. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/_adapters.py +0 -0
  103. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/_collections.py +0 -0
  104. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/_compat.py +0 -0
  105. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/_functools.py +0 -0
  106. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/_itertools.py +0 -0
  107. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/_meta.py +0 -0
  108. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/_text.py +0 -0
  109. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/importlib_metadata/py.typed +0 -0
  110. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/typing_extensions.py +0 -0
  111. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_6/zipp.py +0 -0
  112. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/__init__.py +0 -0
  113. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/__init__.py +0 -0
  114. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +0 -0
  115. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/_collections.py +0 -0
  116. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/_compat.py +0 -0
  117. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/_functools.py +0 -0
  118. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +0 -0
  119. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/_meta.py +0 -0
  120. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/_text.py +0 -0
  121. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
  122. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/__init__.py +0 -0
  123. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_checkers.py +0 -0
  124. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_config.py +0 -0
  125. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_decorators.py +0 -0
  126. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_exceptions.py +0 -0
  127. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_functions.py +0 -0
  128. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_importhook.py +0 -0
  129. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_memo.py +0 -0
  130. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +0 -0
  131. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_suppression.py +0 -0
  132. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_transformer.py +0 -0
  133. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_union_transformer.py +0 -0
  134. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/_utils.py +0 -0
  135. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
  136. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/typing_extensions.py +0 -0
  137. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/v3_7/zipp.py +0 -0
  138. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/_vendor/zipp.py +0 -0
  139. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cards.py +0 -0
  140. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli_args.py +0 -0
  141. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli_components/__init__.py +0 -0
  142. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli_components/dump_cmd.py +0 -0
  143. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli_components/init_cmd.py +0 -0
  144. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli_components/step_cmd.py +0 -0
  145. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cli_components/utils.py +0 -0
  146. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/client/__init__.py +0 -0
  147. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/client/core.py +0 -0
  148. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/client/filecache.py +0 -0
  149. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/clone_util.py +0 -0
  150. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/__init__.py +0 -0
  151. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/code/__init__.py +0 -0
  152. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/configure_cmd.py +0 -0
  153. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/develop/__init__.py +0 -0
  154. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/develop/stub_generator.py +0 -0
  155. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/develop/stubs.py +0 -0
  156. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/make_wrapper.py +0 -0
  157. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/tutorials_cmd.py +0 -0
  158. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd/util.py +0 -0
  159. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/cmd_with_io.py +0 -0
  160. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/__init__.py +0 -0
  161. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/content_addressed_store.py +0 -0
  162. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/datastore_set.py +0 -0
  163. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/datastore_storage.py +0 -0
  164. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/exceptions.py +0 -0
  165. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/flow_datastore.py +0 -0
  166. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/inputs.py +0 -0
  167. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/datastore/task_datastore.py +0 -0
  168. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/debug.py +0 -0
  169. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/decorators.py +0 -0
  170. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/event_logger.py +0 -0
  171. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/events.py +0 -0
  172. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/exception.py +0 -0
  173. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/extension_support/__init__.py +0 -0
  174. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/extension_support/_empty_file.py +0 -0
  175. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/extension_support/cmd.py +0 -0
  176. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/extension_support/integrations.py +0 -0
  177. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/extension_support/plugins.py +0 -0
  178. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/flowspec.py +0 -0
  179. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/graph.py +0 -0
  180. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/includefile.py +0 -0
  181. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/info_file.py +0 -0
  182. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/integrations.py +0 -0
  183. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/lint.py +0 -0
  184. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metadata_provider/__init__.py +0 -0
  185. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metadata_provider/heartbeat.py +0 -0
  186. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metadata_provider/util.py +0 -0
  187. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metaflow_config_funcs.py +0 -0
  188. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metaflow_current.py +0 -0
  189. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/metaflow_profile.py +0 -0
  190. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/mflog/__init__.py +0 -0
  191. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/mflog/mflog.py +0 -0
  192. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/mflog/save_logs.py +0 -0
  193. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/mflog/save_logs_periodically.py +0 -0
  194. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/mflog/tee.py +0 -0
  195. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/monitor.py +0 -0
  196. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/multicore_utils.py +0 -0
  197. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/package.py +0 -0
  198. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/parameters.py +0 -0
  199. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/__init__.py +0 -0
  200. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/airflow.py +0 -0
  201. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/airflow_cli.py +0 -0
  202. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/airflow_decorator.py +0 -0
  203. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/airflow_utils.py +0 -0
  204. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/dag.py +0 -0
  205. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/exception.py +0 -0
  206. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/plumbing/__init__.py +0 -0
  207. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/plumbing/set_parameters.py +0 -0
  208. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/sensors/__init__.py +0 -0
  209. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/sensors/base_sensor.py +0 -0
  210. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/sensors/external_task_sensor.py +0 -0
  211. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/airflow/sensors/s3_sensor.py +0 -0
  212. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/__init__.py +0 -0
  213. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/argo_client.py +0 -0
  214. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/argo_events.py +0 -0
  215. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/argo_workflows_decorator.py +0 -0
  216. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/argo_workflows_deployer.py +0 -0
  217. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/argo_workflows_deployer_objects.py +0 -0
  218. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/capture_error.py +0 -0
  219. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/generate_input_paths.py +0 -0
  220. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/argo/jobset_input_paths.py +0 -0
  221. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/__init__.py +0 -0
  222. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/aws_utils.py +0 -0
  223. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/batch/__init__.py +0 -0
  224. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/batch/batch.py +0 -0
  225. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/batch/batch_cli.py +0 -0
  226. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/batch/batch_client.py +0 -0
  227. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/batch/batch_decorator.py +0 -0
  228. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/secrets_manager/__init__.py +0 -0
  229. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +0 -0
  230. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/__init__.py +0 -0
  231. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -0
  232. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/event_bridge_client.py +0 -0
  233. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/production_token.py +0 -0
  234. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/schedule_decorator.py +0 -0
  235. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/set_batch_environment.py +0 -0
  236. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/step_functions.py +0 -0
  237. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/step_functions_cli.py +0 -0
  238. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/step_functions_client.py +0 -0
  239. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/step_functions_decorator.py +0 -0
  240. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/step_functions_deployer.py +0 -0
  241. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +0 -0
  242. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/__init__.py +0 -0
  243. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/azure_credential.py +0 -0
  244. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/azure_exceptions.py +0 -0
  245. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +0 -0
  246. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/azure_tail.py +0 -0
  247. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/azure_utils.py +0 -0
  248. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/blob_service_client_factory.py +0 -0
  249. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/azure/includefile_support.py +0 -0
  250. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/__init__.py +0 -0
  251. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_cli.py +0 -0
  252. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_client.py +0 -0
  253. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_creator.py +0 -0
  254. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_datastore.py +0 -0
  255. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_decorator.py +0 -0
  256. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/__init__.py +0 -0
  257. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/base.html +0 -0
  258. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/basic.py +0 -0
  259. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/bundle.css +0 -0
  260. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/card.py +0 -0
  261. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/chevron/__init__.py +0 -0
  262. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/chevron/main.py +0 -0
  263. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/chevron/metadata.py +0 -0
  264. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/chevron/renderer.py +0 -0
  265. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/chevron/tokenizer.py +0 -0
  266. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/components.py +0 -0
  267. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/convert_to_native_type.py +0 -0
  268. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/main.js +0 -0
  269. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/renderer_tools.py +0 -0
  270. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_modules/test_cards.py +0 -0
  271. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_resolver.py +0 -0
  272. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_server.py +0 -0
  273. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/card_viewer/viewer.html +0 -0
  274. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/component_serializer.py +0 -0
  275. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/cards/exception.py +0 -0
  276. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/catch_decorator.py +0 -0
  277. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datastores/__init__.py +0 -0
  278. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datastores/azure_storage.py +0 -0
  279. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datastores/gs_storage.py +0 -0
  280. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datastores/local_storage.py +0 -0
  281. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datastores/s3_storage.py +0 -0
  282. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datatools/__init__.py +0 -0
  283. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datatools/local.py +0 -0
  284. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datatools/s3/__init__.py +0 -0
  285. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datatools/s3/s3tail.py +0 -0
  286. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/datatools/s3/s3util.py +0 -0
  287. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/debug_logger.py +0 -0
  288. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/debug_monitor.py +0 -0
  289. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/__init__.py +0 -0
  290. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/client.py +0 -0
  291. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/client_modules.py +0 -0
  292. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/communication/__init__.py +0 -0
  293. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/communication/bytestream.py +0 -0
  294. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/communication/channel.py +0 -0
  295. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/communication/socket_bytestream.py +0 -0
  296. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/communication/utils.py +0 -0
  297. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/configurations/emulate_test_lib/__init__.py +0 -0
  298. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +0 -0
  299. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +0 -0
  300. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/configurations/test_lib_impl/__init__.py +0 -0
  301. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +0 -0
  302. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/consts.py +0 -0
  303. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/data_transferer.py +0 -0
  304. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/exception_transferer.py +0 -0
  305. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/override_decorators.py +0 -0
  306. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/server.py +0 -0
  307. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/stub.py +0 -0
  308. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/env_escape/utils.py +0 -0
  309. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/environment_decorator.py +0 -0
  310. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/events_decorator.py +0 -0
  311. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/frameworks/__init__.py +0 -0
  312. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/frameworks/pytorch.py +0 -0
  313. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/gcp/__init__.py +0 -0
  314. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +0 -0
  315. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/gcp/gs_exceptions.py +0 -0
  316. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/gcp/gs_storage_client_factory.py +0 -0
  317. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/gcp/gs_tail.py +0 -0
  318. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/gcp/gs_utils.py +0 -0
  319. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/gcp/includefile_support.py +0 -0
  320. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/__init__.py +0 -0
  321. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/kube_utils.py +0 -0
  322. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/kubernetes_client.py +0 -0
  323. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/spot_metadata_cli.py +0 -0
  324. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/kubernetes/spot_monitor_sidecar.py +0 -0
  325. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/logs_cli.py +0 -0
  326. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/metadata_providers/__init__.py +0 -0
  327. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/metadata_providers/local.py +0 -0
  328. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/metadata_providers/service.py +0 -0
  329. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/package_cli.py +0 -0
  330. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/parallel_decorator.py +0 -0
  331. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/project_decorator.py +0 -0
  332. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/__init__.py +0 -0
  333. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/bootstrap.py +0 -0
  334. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/conda_decorator.py +0 -0
  335. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/conda_environment.py +0 -0
  336. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/micromamba.py +0 -0
  337. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/parsers.py +0 -0
  338. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/pip.py +0 -0
  339. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/pypi_decorator.py +0 -0
  340. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/pypi_environment.py +0 -0
  341. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/pypi/utils.py +0 -0
  342. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/resources_decorator.py +0 -0
  343. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/retry_decorator.py +0 -0
  344. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/secrets/__init__.py +0 -0
  345. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/secrets/inline_secrets_provider.py +0 -0
  346. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/secrets/secrets_decorator.py +0 -0
  347. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/storage_executor.py +0 -0
  348. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/tag_cli.py +0 -0
  349. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/test_unbounded_foreach_decorator.py +0 -0
  350. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/plugins/timeout_decorator.py +0 -0
  351. {metaflow-2.15.7/metaflow/runner → metaflow-2.15.9/metaflow/plugins/uv}/__init__.py +0 -0
  352. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/procpoll.py +0 -0
  353. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/py.typed +0 -0
  354. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/pylint_wrapper.py +0 -0
  355. {metaflow-2.15.7/metaflow/user_configs → metaflow-2.15.9/metaflow/runner}/__init__.py +0 -0
  356. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/click_api.py +0 -0
  357. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/nbdeploy.py +0 -0
  358. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/nbrun.py +0 -0
  359. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/subprocess_manager.py +0 -0
  360. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runner/utils.py +0 -0
  361. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/runtime.py +0 -0
  362. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/sidecar/__init__.py +0 -0
  363. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/sidecar/sidecar.py +0 -0
  364. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/sidecar/sidecar_messages.py +0 -0
  365. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/sidecar/sidecar_subprocess.py +0 -0
  366. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/sidecar/sidecar_worker.py +0 -0
  367. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/system/__init__.py +0 -0
  368. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/system/system_logger.py +0 -0
  369. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/system/system_monitor.py +0 -0
  370. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/system/system_utils.py +0 -0
  371. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tagging_util.py +0 -0
  372. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/task.py +0 -0
  373. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tracing/__init__.py +0 -0
  374. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tracing/propagator.py +0 -0
  375. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tracing/span_exporter.py +0 -0
  376. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tracing/tracing_modules.py +0 -0
  377. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tuple_util.py +0 -0
  378. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/00-helloworld/README.md +0 -0
  379. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/00-helloworld/helloworld.py +0 -0
  380. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/01-playlist/README.md +0 -0
  381. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/01-playlist/movies.csv +0 -0
  382. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/01-playlist/playlist.ipynb +0 -0
  383. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/01-playlist/playlist.py +0 -0
  384. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/02-statistics/README.md +0 -0
  385. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/02-statistics/movies.csv +0 -0
  386. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/02-statistics/stats.ipynb +0 -0
  387. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/02-statistics/stats.py +0 -0
  388. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/03-playlist-redux/README.md +0 -0
  389. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/03-playlist-redux/playlist.py +0 -0
  390. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/04-playlist-plus/README.md +0 -0
  391. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/04-playlist-plus/playlist.py +0 -0
  392. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/05-hello-cloud/README.md +0 -0
  393. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/05-hello-cloud/hello-cloud.ipynb +0 -0
  394. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/05-hello-cloud/hello-cloud.py +0 -0
  395. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/06-statistics-redux/README.md +0 -0
  396. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/06-statistics-redux/stats.ipynb +0 -0
  397. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/07-worldview/README.md +0 -0
  398. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/07-worldview/worldview.ipynb +0 -0
  399. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/08-autopilot/README.md +0 -0
  400. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/tutorials/08-autopilot/autopilot.ipynb +0 -0
  401. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/unbounded_foreach.py +0 -0
  402. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/user_configs/config_decorators.py +0 -0
  403. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/user_configs/config_options.py +0 -0
  404. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/user_configs/config_parameters.py +0 -0
  405. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/util.py +0 -0
  406. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow/vendor.py +0 -0
  407. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow.egg-info/dependency_links.txt +0 -0
  408. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow.egg-info/entry_points.txt +0 -0
  409. {metaflow-2.15.7 → metaflow-2.15.9}/metaflow.egg-info/top_level.txt +0 -0
  410. {metaflow-2.15.7 → metaflow-2.15.9}/setup.cfg +0 -0
  411. {metaflow-2.15.7 → metaflow-2.15.9}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaflow
3
- Version: 2.15.7
3
+ Version: 2.15.9
4
4
  Summary: Metaflow: More AI and ML, Less Engineering
5
5
  Author: Metaflow Developers
6
6
  Author-email: help@metaflow.org
@@ -26,7 +26,7 @@ License-File: LICENSE
26
26
  Requires-Dist: requests
27
27
  Requires-Dist: boto3
28
28
  Provides-Extra: stubs
29
- Requires-Dist: metaflow-stubs==2.15.7; extra == "stubs"
29
+ Requires-Dist: metaflow-stubs==2.15.9; extra == "stubs"
30
30
  Dynamic: author
31
31
  Dynamic: author-email
32
32
  Dynamic: classifier
@@ -260,6 +260,7 @@ shell: setup-tilt
260
260
  env METAFLOW_HOME="$(DEVTOOLS_DIR)" \
261
261
  METAFLOW_PROFILE=local \
262
262
  AWS_CONFIG_FILE="$(DEVTOOLS_DIR)/aws_config" \
263
+ AWS_SHARED_CREDENTIALS_FILE= \
263
264
  "$$user_shell" -i; \
264
265
  else \
265
266
  env METAFLOW_HOME="$(DEVTOOLS_DIR)" \
@@ -301,6 +302,7 @@ create-dev-shell: setup-tilt
301
302
  echo " env METAFLOW_HOME=\"$(DEVTOOLS_DIR)\" \\" >> $$SHELL_PATH && \
302
303
  echo " METAFLOW_PROFILE=local \\" >> $$SHELL_PATH && \
303
304
  echo " AWS_CONFIG_FILE=\"$(DEVTOOLS_DIR)/aws_config\" \\" >> $$SHELL_PATH && \
305
+ echo " AWS_SHARED_CREDENTIALS_FILE= \\" >> $$SHELL_PATH && \
304
306
  echo " \"\$$user_shell\" -i" >> $$SHELL_PATH && \
305
307
  echo "else" >> $$SHELL_PATH && \
306
308
  echo " env METAFLOW_HOME=\"$(DEVTOOLS_DIR)\" \\" >> $$SHELL_PATH && \
@@ -17,6 +17,7 @@ from .flowspec import _FlowState
17
17
  from .graph import FlowGraph
18
18
  from .metaflow_config import (
19
19
  DEFAULT_DATASTORE,
20
+ DEFAULT_DECOSPECS,
20
21
  DEFAULT_ENVIRONMENT,
21
22
  DEFAULT_EVENT_LOGGER,
22
23
  DEFAULT_METADATA,
@@ -509,9 +510,16 @@ def start(
509
510
  ):
510
511
  # run/resume are special cases because they can add more decorators with --with,
511
512
  # so they have to take care of themselves.
513
+
512
514
  all_decospecs = ctx.obj.tl_decospecs + list(
513
515
  ctx.obj.environment.decospecs() or []
514
516
  )
517
+
518
+ # We add the default decospecs for everything except init and step since in those
519
+ # cases, the decospecs will already have been handled by either a run/resume
520
+ # or a scheduler setting them up in their own way.
521
+ if ctx.saved_args[0] not in ("step", "init"):
522
+ all_decospecs += DEFAULT_DECOSPECS.split()
515
523
  if all_decospecs:
516
524
  decorators._attach_decorators(ctx.obj.flow, all_decospecs)
517
525
  decorators._init(ctx.obj.flow)
@@ -71,7 +71,7 @@ def write_file(file_path, content):
71
71
  f.write(str(content))
72
72
 
73
73
 
74
- def config_merge_cb(ctx, param, value):
74
+ def config_callback(ctx, param, value):
75
75
  # Callback to:
76
76
  # - read the Click auto_envvar variable from both the
77
77
  # environment AND the configuration
@@ -127,7 +127,7 @@ def common_run_options(func):
127
127
  help="Add a decorator to all steps. You can specify this "
128
128
  "option multiple times to attach multiple decorators "
129
129
  "in steps.",
130
- callback=config_merge_cb,
130
+ callback=config_callback,
131
131
  )
132
132
  @click.option(
133
133
  "--run-id-file",
@@ -94,7 +94,7 @@ def start(ctx):
94
94
  echo("(%s)\n" % version, fg="magenta", bold=False)
95
95
 
96
96
  if ctx.invoked_subcommand is None:
97
- echo("More data science, less engineering\n", fg="magenta")
97
+ echo("More AI, less engineering\n", fg="magenta")
98
98
 
99
99
  lnk_sz = max(len(lnk) for lnk in CONTACT_INFO.values()) + 1
100
100
  for what, lnk in CONTACT_INFO.items():
@@ -630,6 +630,20 @@ class MetadataProvider(object):
630
630
  sys_info["r_version"] = env["r_version_code"]
631
631
  return sys_info
632
632
 
633
+ def _get_git_info_as_dict(self):
634
+ git_info = {}
635
+ env = self._environment.get_environment_info()
636
+ for key in [
637
+ "repo_url",
638
+ "branch_name",
639
+ "commit_sha",
640
+ "has_uncommitted_changes",
641
+ ]:
642
+ if key in env and env[key]:
643
+ git_info[key] = env[key]
644
+
645
+ return git_info
646
+
633
647
  def _get_system_tags(self):
634
648
  """Convert system info dictionary into a list of system tags"""
635
649
  return [
@@ -670,6 +684,27 @@ class MetadataProvider(object):
670
684
  tags=["attempt_id:{0}".format(attempt)],
671
685
  )
672
686
  )
687
+ # Add script name as metadata
688
+ script_name = self._environment.get_environment_info()["script"]
689
+ metadata.append(
690
+ MetaDatum(
691
+ field="script-name",
692
+ value=script_name,
693
+ type="script-name",
694
+ tags=["attempt_id:{0}".format(attempt)],
695
+ )
696
+ )
697
+ # And add git metadata
698
+ git_info = self._get_git_info_as_dict()
699
+ if git_info:
700
+ metadata.append(
701
+ MetaDatum(
702
+ field="git-info",
703
+ value=json.dumps(git_info),
704
+ type="git-info",
705
+ tags=["attempt_id:{0}".format(attempt)],
706
+ )
707
+ )
673
708
  if metadata:
674
709
  self.register_metadata(run_id, step_name, task_id, metadata)
675
710
 
@@ -109,6 +109,12 @@ S3_WORKER_COUNT = from_conf("S3_WORKER_COUNT", 64)
109
109
  # top-level retries)
110
110
  S3_TRANSIENT_RETRY_COUNT = from_conf("S3_TRANSIENT_RETRY_COUNT", 20)
111
111
 
112
+ # S3 retry configuration used in the aws client
113
+ # Use the adaptive retry strategy by default
114
+ S3_CLIENT_RETRY_CONFIG = from_conf(
115
+ "S3_CLIENT_RETRY_CONFIG", {"max_attempts": 10, "mode": "adaptive"}
116
+ )
117
+
112
118
  # Threshold to start printing warnings for an AWS retry
113
119
  RETRY_WARNING_THRESHOLD = 3
114
120
 
@@ -4,6 +4,7 @@ import sys
4
4
 
5
5
  from .util import get_username
6
6
  from . import metaflow_version
7
+ from . import metaflow_git
7
8
  from metaflow.exception import MetaflowException
8
9
  from metaflow.extension_support import dump_module_info
9
10
  from metaflow.mflog import BASH_MFLOG, BASH_FLUSH_LOGS
@@ -197,6 +198,10 @@ class MetaflowEnvironment(object):
197
198
  "python_version_code": "%d.%d.%d" % sys.version_info[:3],
198
199
  "metaflow_version": metaflow_version.get_version(),
199
200
  "script": os.path.basename(os.path.abspath(sys.argv[0])),
201
+ # Add git info
202
+ **metaflow_git.get_repository_info(
203
+ path=os.path.dirname(os.path.abspath(sys.argv[0]))
204
+ ),
200
205
  }
201
206
  if R.use_r():
202
207
  env["metaflow_r_version"] = R.metaflow_r_version()
@@ -206,7 +211,7 @@ class MetaflowEnvironment(object):
206
211
  # Information about extension modules (to load them in the proper order)
207
212
  ext_key, ext_val = dump_module_info()
208
213
  env[ext_key] = ext_val
209
- return env
214
+ return {k: v for k, v in env.items() if v is not None and v != ""}
210
215
 
211
216
  def executable(self, step_name, default=None):
212
217
  if default is not None:
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env python
2
+ """Get git repository information for the package
3
+
4
+ Functions to retrieve git repository details like URL, branch name,
5
+ and commit SHA for Metaflow code provenance tracking.
6
+ """
7
+
8
+ import os
9
+ import subprocess
10
+ from typing import Dict, List, Optional, Tuple, Union
11
+
12
+ # Cache for git information to avoid repeated subprocess calls
13
+ _git_info_cache = None
14
+
15
+ __all__ = ("get_repository_info",)
16
+
17
+
18
+ def _call_git(
19
+ args: List[str], path=Union[str, os.PathLike]
20
+ ) -> Tuple[Optional[str], Optional[int], bool]:
21
+ """
22
+ Call git with provided args.
23
+
24
+ Returns
25
+ -------
26
+ tuple : Tuple containing
27
+ (stdout, exitcode, failure) of the call
28
+ """
29
+ try:
30
+ result = subprocess.run(
31
+ ["git", *args],
32
+ cwd=path,
33
+ capture_output=True,
34
+ text=True,
35
+ check=False,
36
+ )
37
+ return result.stdout.strip(), result.returncode, False
38
+ except (OSError, subprocess.SubprocessError):
39
+ # Covers subprocess timeouts and other errors which would not lead to an exit code
40
+ return None, None, True
41
+
42
+
43
+ def _get_repo_url(path: Union[str, os.PathLike]) -> Optional[str]:
44
+ """Get the repository URL from git config"""
45
+ stdout, returncode, _failed = _call_git(
46
+ ["config", "--get", "remote.origin.url"], path
47
+ )
48
+ if returncode == 0:
49
+ url = stdout
50
+ # Convert SSH URLs to HTTPS for clickable links
51
+ if url.startswith("git@"):
52
+ parts = url.split(":", 1)
53
+ if len(parts) == 2:
54
+ domain = parts[0].replace("git@", "")
55
+ repo_path = parts[1]
56
+ url = f"https://{domain}/{repo_path}"
57
+ return url
58
+ return None
59
+
60
+
61
+ def _get_branch_name(path: Union[str, os.PathLike]) -> Optional[str]:
62
+ """Get the current git branch name"""
63
+ stdout, returncode, _failed = _call_git(["rev-parse", "--abbrev-ref", "HEAD"], path)
64
+ return stdout if returncode == 0 else None
65
+
66
+
67
+ def _get_commit_sha(path: Union[str, os.PathLike]) -> Optional[str]:
68
+ """Get the current git commit SHA"""
69
+ stdout, returncode, _failed = _call_git(["rev-parse", "HEAD"], path)
70
+ return stdout if returncode == 0 else None
71
+
72
+
73
+ def _is_in_git_repo(path: Union[str, os.PathLike]) -> bool:
74
+ """Check if we're currently in a git repository"""
75
+ stdout, returncode, _failed = _call_git(
76
+ ["rev-parse", "--is-inside-work-tree"], path
77
+ )
78
+ return returncode == 0 and stdout == "true"
79
+
80
+
81
+ def _has_uncommitted_changes(path: Union[str, os.PathLike]) -> Optional[bool]:
82
+ """Check if the git repository has uncommitted changes"""
83
+ _stdout, returncode, failed = _call_git(
84
+ ["diff-index", "--quiet", "HEAD", "--"], path
85
+ )
86
+ if failed:
87
+ return None
88
+ return returncode != 0
89
+
90
+
91
+ def get_repository_info(path: Union[str, os.PathLike]) -> Dict[str, Union[str, bool]]:
92
+ """Get git repository information for a path
93
+
94
+ Returns:
95
+ dict: Dictionary containing:
96
+ repo_url: Repository URL (converted to HTTPS if from SSH)
97
+ branch_name: Current branch name
98
+ commit_sha: Current commit SHA
99
+ has_uncommitted_changes: Boolean indicating if there are uncommitted changes
100
+ """
101
+ global _git_info_cache
102
+
103
+ if _git_info_cache is not None:
104
+ return _git_info_cache
105
+
106
+ _git_info_cache = {}
107
+ if _is_in_git_repo(path):
108
+ _git_info_cache = {
109
+ "repo_url": _get_repo_url(path),
110
+ "branch_name": _get_branch_name(path),
111
+ "commit_sha": _get_commit_sha(path),
112
+ "has_uncommitted_changes": _has_uncommitted_changes(path),
113
+ }
114
+
115
+ return _git_info_cache
@@ -27,11 +27,11 @@ if name == "nt":
27
27
  """find the path to the git executable on Windows"""
28
28
  # first see if git is in the path
29
29
  try:
30
- check_output(["where", "/Q", "git"])
30
+ subprocess.check_output(["where", "/Q", "git"])
31
31
  # if this command succeeded, git is in the path
32
32
  return "git"
33
33
  # catch the exception thrown if git was not found
34
- except CalledProcessError:
34
+ except subprocess.CalledProcessError:
35
35
  pass
36
36
  # There are several locations where git.exe may be hiding
37
37
  possible_locations = []
@@ -75,6 +75,7 @@ FLOW_DECORATORS_DESC = [
75
75
  ENVIRONMENTS_DESC = [
76
76
  ("conda", ".pypi.conda_environment.CondaEnvironment"),
77
77
  ("pypi", ".pypi.pypi_environment.PyPIEnvironment"),
78
+ ("uv", ".uv.uv_environment.UVEnvironment"),
78
79
  ]
79
80
 
80
81
  # Add metadata providers here
@@ -7,6 +7,7 @@ import sys
7
7
  from collections import defaultdict
8
8
  from hashlib import sha1
9
9
  from math import inf
10
+ from typing import List
10
11
 
11
12
  from metaflow import JSONType, current
12
13
  from metaflow.decorators import flow_decorators
@@ -110,6 +111,7 @@ class ArgoWorkflows(object):
110
111
  notify_pager_duty_integration_key=None,
111
112
  notify_incident_io_api_key=None,
112
113
  incident_io_alert_source_config_id=None,
114
+ incident_io_metadata: List[str] = None,
113
115
  enable_heartbeat_daemon=True,
114
116
  enable_error_msg_capture=False,
115
117
  ):
@@ -161,6 +163,9 @@ class ArgoWorkflows(object):
161
163
  self.notify_pager_duty_integration_key = notify_pager_duty_integration_key
162
164
  self.notify_incident_io_api_key = notify_incident_io_api_key
163
165
  self.incident_io_alert_source_config_id = incident_io_alert_source_config_id
166
+ self.incident_io_metadata = self.parse_incident_io_metadata(
167
+ incident_io_metadata
168
+ )
164
169
  self.enable_heartbeat_daemon = enable_heartbeat_daemon
165
170
  self.enable_error_msg_capture = enable_error_msg_capture
166
171
  self.parameters = self._process_parameters()
@@ -287,6 +292,21 @@ class ArgoWorkflows(object):
287
292
 
288
293
  return True
289
294
 
295
+ @staticmethod
296
+ def parse_incident_io_metadata(metadata: List[str] = None):
297
+ "parse key value pairs into a dict for incident.io metadata if given"
298
+ parsed_metadata = None
299
+ if metadata is not None:
300
+ parsed_metadata = {}
301
+ for kv in metadata:
302
+ key, value = kv.split("=", 1)
303
+ if key in parsed_metadata:
304
+ raise MetaflowException(
305
+ "Incident.io Metadata *%s* provided multiple times" % key
306
+ )
307
+ parsed_metadata[key] = value
308
+ return parsed_metadata
309
+
290
310
  @classmethod
291
311
  def trigger(cls, name, parameters=None):
292
312
  if parameters is None:
@@ -1958,6 +1978,15 @@ class ArgoWorkflows(object):
1958
1978
  resources["disk"],
1959
1979
  )
1960
1980
 
1981
+ security_context = resources.get("security_context", None)
1982
+ _security_context = {}
1983
+ if security_context is not None and len(security_context) > 0:
1984
+ _security_context = {
1985
+ "security_context": kubernetes_sdk.V1SecurityContext(
1986
+ **security_context
1987
+ )
1988
+ }
1989
+
1961
1990
  # Create a ContainerTemplate for this node. Ideally, we would have
1962
1991
  # liked to inline this ContainerTemplate and avoid scanning the workflow
1963
1992
  # twice, but due to issues with variable substitution, we will have to
@@ -2014,6 +2043,7 @@ class ArgoWorkflows(object):
2014
2043
  shared_memory=shared_memory,
2015
2044
  port=port,
2016
2045
  qos=resources["qos"],
2046
+ security_context=security_context,
2017
2047
  )
2018
2048
 
2019
2049
  for k, v in env.items():
@@ -2290,6 +2320,7 @@ class ArgoWorkflows(object):
2290
2320
  is not None
2291
2321
  else []
2292
2322
  ),
2323
+ **_security_context,
2293
2324
  ).to_dict()
2294
2325
  )
2295
2326
  )
@@ -2552,9 +2583,12 @@ class ArgoWorkflows(object):
2552
2583
  else None
2553
2584
  ),
2554
2585
  "metadata": {
2555
- "run_status": "failed",
2556
- "flow_name": self.flow.name,
2557
- "run_id": "argo-{{workflow.name}}",
2586
+ **(self.incident_io_metadata or {}),
2587
+ **{
2588
+ "run_status": "failed",
2589
+ "flow_name": self.flow.name,
2590
+ "run_id": "argo-{{workflow.name}}",
2591
+ },
2558
2592
  },
2559
2593
  }
2560
2594
  )
@@ -2603,9 +2637,12 @@ class ArgoWorkflows(object):
2603
2637
  else None
2604
2638
  ),
2605
2639
  "metadata": {
2606
- "run_status": "succeeded",
2607
- "flow_name": self.flow.name,
2608
- "run_id": "argo-{{workflow.name}}",
2640
+ **(self.incident_io_metadata or {}),
2641
+ **{
2642
+ "run_status": "succeeded",
2643
+ "flow_name": self.flow.name,
2644
+ "run_id": "argo-{{workflow.name}}",
2645
+ },
2609
2646
  },
2610
2647
  }
2611
2648
  )
@@ -187,6 +187,13 @@ def argo_workflows(obj, name=None):
187
187
  default=None,
188
188
  help="Incident.io Alert source config ID. Example '01GW2G3V0S59R238FAHPDS1R66'",
189
189
  )
190
+ @click.option(
191
+ "--incident-io-metadata",
192
+ default=None,
193
+ type=str,
194
+ multiple=True,
195
+ help="Incident.io Alert Custom Metadata field in the form of Key=Value",
196
+ )
190
197
  @click.option(
191
198
  "--enable-heartbeat-daemon/--no-enable-heartbeat-daemon",
192
199
  default=False,
@@ -226,6 +233,7 @@ def create(
226
233
  notify_pager_duty_integration_key=None,
227
234
  notify_incident_io_api_key=None,
228
235
  incident_io_alert_source_config_id=None,
236
+ incident_io_metadata=None,
229
237
  enable_heartbeat_daemon=True,
230
238
  deployer_attribute_file=None,
231
239
  enable_error_msg_capture=False,
@@ -283,6 +291,7 @@ def create(
283
291
  notify_pager_duty_integration_key,
284
292
  notify_incident_io_api_key,
285
293
  incident_io_alert_source_config_id,
294
+ incident_io_metadata,
286
295
  enable_heartbeat_daemon,
287
296
  enable_error_msg_capture,
288
297
  )
@@ -459,6 +468,7 @@ def make_flow(
459
468
  notify_pager_duty_integration_key,
460
469
  notify_incident_io_api_key,
461
470
  incident_io_alert_source_config_id,
471
+ incident_io_metadata,
462
472
  enable_heartbeat_daemon,
463
473
  enable_error_msg_capture,
464
474
  ):
@@ -538,6 +548,7 @@ def make_flow(
538
548
  notify_pager_duty_integration_key=notify_pager_duty_integration_key,
539
549
  notify_incident_io_api_key=notify_incident_io_api_key,
540
550
  incident_io_alert_source_config_id=incident_io_alert_source_config_id,
551
+ incident_io_metadata=incident_io_metadata,
541
552
  enable_heartbeat_daemon=enable_heartbeat_daemon,
542
553
  enable_error_msg_capture=enable_error_msg_capture,
543
554
  )
@@ -14,6 +14,7 @@ class Boto3ClientProvider(object):
14
14
  AWS_SANDBOX_ENABLED,
15
15
  AWS_SANDBOX_STS_ENDPOINT_URL,
16
16
  AWS_SANDBOX_API_KEY,
17
+ S3_CLIENT_RETRY_CONFIG,
17
18
  )
18
19
 
19
20
  if session_vars is None:
@@ -37,10 +38,10 @@ class Boto3ClientProvider(object):
37
38
  if module == "s3" and (
38
39
  "config" not in client_params or client_params["config"].retries is None
39
40
  ):
40
- # Use the adaptive retry strategy by default -- do not set anything if
41
- # the user has already set something
41
+ # do not set anything if the user has already set something
42
42
  config = client_params.get("config", Config())
43
- config.retries = {"max_attempts": 10, "mode": "adaptive"}
43
+ config.retries = S3_CLIENT_RETRY_CONFIG
44
+ client_params["config"] = config
44
45
 
45
46
  if AWS_SANDBOX_ENABLED:
46
47
  # role is ignored in the sandbox
@@ -18,6 +18,7 @@ from metaflow.metaflow_config import (
18
18
  S3_RETRY_COUNT,
19
19
  S3_TRANSIENT_RETRY_COUNT,
20
20
  S3_SERVER_SIDE_ENCRYPTION,
21
+ S3_WORKER_COUNT,
21
22
  TEMPDIR,
22
23
  )
23
24
  from metaflow.util import (
@@ -1390,9 +1391,31 @@ class S3(object):
1390
1391
  )
1391
1392
 
1392
1393
  # add some jitter to make sure retries are not synchronized
1393
- def _jitter_sleep(self, trynum, multiplier=2):
1394
- interval = multiplier**trynum + random.randint(0, 10)
1395
- time.sleep(interval)
1394
+ def _jitter_sleep(
1395
+ self, trynum: int, base: int = 2, cap: int = 360, jitter: float = 0.1
1396
+ ) -> None:
1397
+ """
1398
+ Sleep for an exponentially increasing interval with added jitter.
1399
+
1400
+ Parameters
1401
+ ----------
1402
+ trynum: The current retry attempt number.
1403
+ base: The base multiplier for the exponential backoff.
1404
+ cap: The maximum interval to sleep.
1405
+ jitter: The maximum jitter percentage to add to the interval.
1406
+ """
1407
+ # Calculate the exponential backoff interval
1408
+ interval = min(cap, base**trynum)
1409
+
1410
+ # Add random jitter
1411
+ jitter_value = interval * jitter * random.uniform(-1, 1)
1412
+ interval_with_jitter = interval + jitter_value
1413
+
1414
+ # Ensure the interval is not negative
1415
+ interval_with_jitter = max(0, interval_with_jitter)
1416
+
1417
+ # Sleep for the calculated interval
1418
+ time.sleep(interval_with_jitter)
1396
1419
 
1397
1420
  # NOTE: re: _read_many_files and _put_many_files
1398
1421
  # All file IO is through binary files - we write bytes, we read
@@ -1480,20 +1503,17 @@ class S3(object):
1480
1503
  # - a known transient failure (SlowDown for example) in which case we will
1481
1504
  # retry *only* the inputs that have this transient failure.
1482
1505
  # - an unknown failure (something went wrong but we cannot say if it was
1483
- # a known permanent failure or something else). In this case, we retry
1484
- # the operation completely.
1485
- #
1486
- # There are therefore two retry counts:
1487
- # - the transient failure retry count: how many times do we try on known
1488
- # transient errors
1489
- # - the top-level retry count: how many times do we try on unknown failures
1506
+ # a known permanent failure or something else). In this case, we assume
1507
+ # it's a transient failure and retry only those inputs (same as above).
1490
1508
  #
1491
- # Note that, if the operation runs out of transient failure retries, it will
1492
- # count as an "unknown" failure (ie: it will be retried according to the
1493
- # outer top-level retry count). In other words, you can potentially have
1494
- # transient_retry_count * retry_count tries).
1495
- # Finally, if on transient failures, we make NO progress (ie: no input is
1496
- # successfully processed), that counts as an "unknown" failure.
1509
+ # NOTES(npow): 2025-05-13
1510
+ # Previously, this code would also retry the fatal failures, including no_progress
1511
+ # and unknown failures, from the beginning. This is not ideal because:
1512
+ # 1. Fatal errors are not supposed to be retried.
1513
+ # 2. Retrying from the beginning does not improve the situation, and is
1514
+ # wasteful since we have already uploaded some files.
1515
+ # 3. The number of transient errors is far more than fatal errors, so we
1516
+ # can be optimistic and assume the unknown errors are transient.
1497
1517
  cmdline = [sys.executable, os.path.abspath(s3op.__file__), mode]
1498
1518
  recursive_get = False
1499
1519
  for key, value in options.items():
@@ -1528,7 +1548,6 @@ class S3(object):
1528
1548
  # Otherwise, we cap the failure rate at 90%
1529
1549
  return min(90, self._s3_inject_failures)
1530
1550
 
1531
- retry_count = 0 # Number of retries (excluding transient failures)
1532
1551
  transient_retry_count = 0 # Number of transient retries (per top-level retry)
1533
1552
  inject_failures = _inject_failure_rate()
1534
1553
  out_lines = [] # List to contain the lines returned by _s3op_with_retries
@@ -1595,7 +1614,12 @@ class S3(object):
1595
1614
  # things, this will shrink more and more until we are doing a
1596
1615
  # single operation at a time. If things start going better, it
1597
1616
  # will increase by 20% every round.
1598
- max_count = min(int(last_ok_count * 1.2), len(pending_retries))
1617
+ #
1618
+ # If we made no progress (last_ok_count == 0) we retry at most
1619
+ # 2*S3_WORKER_COUNT from whatever is left in `pending_retries`
1620
+ max_count = min(
1621
+ int(last_ok_count * 1.2), len(pending_retries)
1622
+ ) or min(2 * S3_WORKER_COUNT, len(pending_retries))
1599
1623
  tmp_input.writelines(pending_retries[:max_count])
1600
1624
  tmp_input.flush()
1601
1625
  debug.s3client_exec(
@@ -1712,38 +1736,16 @@ class S3(object):
1712
1736
  _update_out_lines(out_lines, ok_lines, resize=loop_count == 0)
1713
1737
  return 0, 0, inject_failures, err_out
1714
1738
 
1715
- while retry_count <= S3_RETRY_COUNT:
1739
+ while transient_retry_count <= S3_TRANSIENT_RETRY_COUNT:
1716
1740
  (
1717
1741
  last_ok_count,
1718
1742
  last_retry_count,
1719
1743
  inject_failures,
1720
1744
  err_out,
1721
1745
  ) = try_s3_op(last_ok_count, pending_retries, out_lines, inject_failures)
1722
- if err_out or (
1723
- last_retry_count != 0
1724
- and (
1725
- last_ok_count == 0
1726
- or transient_retry_count > S3_TRANSIENT_RETRY_COUNT
1727
- )
1728
- ):
1729
- # We had a fatal failure (err_out is not None)
1730
- # or we made no progress (last_ok_count is 0)
1731
- # or we are out of transient retries
1732
- # so we will restart from scratch (being very conservative)
1733
- retry_count += 1
1734
- err_msg = err_out
1735
- if err_msg is None and last_ok_count == 0:
1736
- err_msg = "No progress"
1737
- if err_msg is None:
1738
- err_msg = "Too many transient errors"
1739
- print(
1740
- "S3 non-transient error (attempt #%d): %s" % (retry_count, err_msg)
1741
- )
1742
- _reset()
1743
- if retry_count <= S3_RETRY_COUNT:
1744
- self._jitter_sleep(retry_count)
1745
- continue
1746
- elif last_retry_count != 0:
1746
+ if err_out:
1747
+ break
1748
+ if last_retry_count != 0:
1747
1749
  # During our last try, we did not manage to process everything we wanted
1748
1750
  # due to a transient failure so we try again.
1749
1751
  transient_retry_count += 1