metaflow 2.18.2__tar.gz → 2.18.4__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 (447) hide show
  1. {metaflow-2.18.2/metaflow.egg-info → metaflow-2.18.4}/PKG-INFO +2 -2
  2. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/client/core.py +1 -1
  3. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_config.py +5 -0
  4. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_client.py +10 -6
  5. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows.py +222 -42
  6. metaflow-2.18.4/metaflow/plugins/argo/conditional_input_paths.py +35 -0
  7. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch.py +42 -2
  8. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions.py +6 -1
  9. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_cli.py +11 -0
  10. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_deployer.py +3 -0
  11. metaflow-2.18.4/metaflow/version.py +1 -0
  12. {metaflow-2.18.2 → metaflow-2.18.4/metaflow.egg-info}/PKG-INFO +2 -2
  13. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/requires.txt +1 -1
  14. metaflow-2.18.2/metaflow/plugins/argo/conditional_input_paths.py +0 -21
  15. metaflow-2.18.2/metaflow/version.py +0 -1
  16. {metaflow-2.18.2 → metaflow-2.18.4}/LICENSE +0 -0
  17. {metaflow-2.18.2 → metaflow-2.18.4}/MANIFEST.in +0 -0
  18. {metaflow-2.18.2 → metaflow-2.18.4}/README.md +0 -0
  19. {metaflow-2.18.2 → metaflow-2.18.4}/devtools/Makefile +0 -0
  20. {metaflow-2.18.2 → metaflow-2.18.4}/devtools/Tiltfile +0 -0
  21. {metaflow-2.18.2 → metaflow-2.18.4}/devtools/pick_services.sh +0 -0
  22. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/R.py +0 -0
  23. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/__init__.py +0 -0
  24. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/__init__.py +0 -0
  25. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/__init__.py +0 -0
  26. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_bashcomplete.py +0 -0
  27. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_compat.py +0 -0
  28. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_termui_impl.py +0 -0
  29. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_textwrap.py +0 -0
  30. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_unicodefun.py +0 -0
  31. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_winconsole.py +0 -0
  32. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/core.py +0 -0
  33. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/decorators.py +0 -0
  34. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/exceptions.py +0 -0
  35. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/formatting.py +0 -0
  36. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/globals.py +0 -0
  37. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/parser.py +0 -0
  38. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/termui.py +0 -0
  39. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/testing.py +0 -0
  40. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/types.py +0 -0
  41. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/utils.py +0 -0
  42. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/imghdr/__init__.py +0 -0
  43. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/__init__.py +0 -0
  44. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_adapters.py +0 -0
  45. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_collections.py +0 -0
  46. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_compat.py +0 -0
  47. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_functools.py +0 -0
  48. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_itertools.py +0 -0
  49. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_meta.py +0 -0
  50. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_text.py +0 -0
  51. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/py.typed +0 -0
  52. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/__init__.py +0 -0
  53. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_elffile.py +0 -0
  54. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_manylinux.py +0 -0
  55. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_musllinux.py +0 -0
  56. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_parser.py +0 -0
  57. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_structures.py +0 -0
  58. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_tokenizer.py +0 -0
  59. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/markers.py +0 -0
  60. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/py.typed +0 -0
  61. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/requirements.py +0 -0
  62. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/specifiers.py +0 -0
  63. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/tags.py +0 -0
  64. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/utils.py +0 -0
  65. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/version.py +0 -0
  66. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/__init__.py +0 -0
  67. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_checkers.py +0 -0
  68. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_config.py +0 -0
  69. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_decorators.py +0 -0
  70. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_exceptions.py +0 -0
  71. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_functions.py +0 -0
  72. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_importhook.py +0 -0
  73. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_memo.py +0 -0
  74. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_pytest_plugin.py +0 -0
  75. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_suppression.py +0 -0
  76. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_transformer.py +0 -0
  77. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_union_transformer.py +0 -0
  78. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_utils.py +0 -0
  79. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/py.typed +0 -0
  80. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typing_extensions.py +0 -0
  81. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/__init__.py +0 -0
  82. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/__init__.py +0 -0
  83. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_adapters.py +0 -0
  84. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_collections.py +0 -0
  85. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_compat.py +0 -0
  86. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_functools.py +0 -0
  87. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_itertools.py +0 -0
  88. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_meta.py +0 -0
  89. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_text.py +0 -0
  90. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/py.typed +0 -0
  91. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/typing_extensions.py +0 -0
  92. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/zipp.py +0 -0
  93. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/__init__.py +0 -0
  94. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/__init__.py +0 -0
  95. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +0 -0
  96. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_collections.py +0 -0
  97. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_compat.py +0 -0
  98. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_functools.py +0 -0
  99. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +0 -0
  100. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_meta.py +0 -0
  101. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_text.py +0 -0
  102. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
  103. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/__init__.py +0 -0
  104. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_checkers.py +0 -0
  105. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_config.py +0 -0
  106. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_decorators.py +0 -0
  107. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_exceptions.py +0 -0
  108. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_functions.py +0 -0
  109. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_importhook.py +0 -0
  110. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_memo.py +0 -0
  111. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +0 -0
  112. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_suppression.py +0 -0
  113. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_transformer.py +0 -0
  114. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_union_transformer.py +0 -0
  115. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_utils.py +0 -0
  116. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
  117. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typing_extensions.py +0 -0
  118. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/zipp.py +0 -0
  119. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/__init__.py +0 -0
  120. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/composer.py +0 -0
  121. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/constructor.py +0 -0
  122. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/cyaml.py +0 -0
  123. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/dumper.py +0 -0
  124. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/emitter.py +0 -0
  125. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/error.py +0 -0
  126. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/events.py +0 -0
  127. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/loader.py +0 -0
  128. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/nodes.py +0 -0
  129. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/parser.py +0 -0
  130. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/reader.py +0 -0
  131. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/representer.py +0 -0
  132. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/resolver.py +0 -0
  133. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/scanner.py +0 -0
  134. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/serializer.py +0 -0
  135. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/tokens.py +0 -0
  136. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/zipp.py +0 -0
  137. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cards.py +0 -0
  138. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli.py +0 -0
  139. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_args.py +0 -0
  140. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/__init__.py +0 -0
  141. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/dump_cmd.py +0 -0
  142. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/init_cmd.py +0 -0
  143. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/run_cmds.py +0 -0
  144. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/step_cmd.py +0 -0
  145. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/utils.py +0 -0
  146. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/client/__init__.py +0 -0
  147. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/client/filecache.py +0 -0
  148. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/clone_util.py +0 -0
  149. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/__init__.py +0 -0
  150. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/code/__init__.py +0 -0
  151. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/configure_cmd.py +0 -0
  152. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/develop/__init__.py +0 -0
  153. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/develop/stub_generator.py +0 -0
  154. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/develop/stubs.py +0 -0
  155. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/main_cli.py +0 -0
  156. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/make_wrapper.py +0 -0
  157. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/tutorials_cmd.py +0 -0
  158. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/util.py +0 -0
  159. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd_with_io.py +0 -0
  160. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/__init__.py +0 -0
  161. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/content_addressed_store.py +0 -0
  162. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/datastore_set.py +0 -0
  163. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/datastore_storage.py +0 -0
  164. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/exceptions.py +0 -0
  165. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/flow_datastore.py +0 -0
  166. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/inputs.py +0 -0
  167. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/task_datastore.py +0 -0
  168. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/debug.py +0 -0
  169. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/decorators.py +0 -0
  170. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/event_logger.py +0 -0
  171. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/events.py +0 -0
  172. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/exception.py +0 -0
  173. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/__init__.py +0 -0
  174. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/_empty_file.py +0 -0
  175. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/cmd.py +0 -0
  176. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/integrations.py +0 -0
  177. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/plugins.py +0 -0
  178. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/flowspec.py +0 -0
  179. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/graph.py +0 -0
  180. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/includefile.py +0 -0
  181. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/integrations.py +0 -0
  182. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/lint.py +0 -0
  183. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/meta_files.py +0 -0
  184. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/__init__.py +0 -0
  185. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/heartbeat.py +0 -0
  186. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/metadata.py +0 -0
  187. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/util.py +0 -0
  188. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_config_funcs.py +0 -0
  189. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_current.py +0 -0
  190. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_environment.py +0 -0
  191. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_git.py +0 -0
  192. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_profile.py +0 -0
  193. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_version.py +0 -0
  194. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/__init__.py +0 -0
  195. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/mflog.py +0 -0
  196. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/save_logs.py +0 -0
  197. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/save_logs_periodically.py +0 -0
  198. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/tee.py +0 -0
  199. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/monitor.py +0 -0
  200. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/multicore_utils.py +0 -0
  201. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/package/__init__.py +0 -0
  202. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/__init__.py +0 -0
  203. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/backend.py +0 -0
  204. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/distribution_support.py +0 -0
  205. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/tar_backend.py +0 -0
  206. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/utils.py +0 -0
  207. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/v1.py +0 -0
  208. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/parameters.py +0 -0
  209. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/__init__.py +0 -0
  210. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/__init__.py +0 -0
  211. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow.py +0 -0
  212. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow_cli.py +0 -0
  213. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow_decorator.py +0 -0
  214. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow_utils.py +0 -0
  215. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/dag.py +0 -0
  216. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/exception.py +0 -0
  217. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/plumbing/__init__.py +0 -0
  218. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/plumbing/set_parameters.py +0 -0
  219. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/__init__.py +0 -0
  220. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/base_sensor.py +0 -0
  221. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/external_task_sensor.py +0 -0
  222. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/s3_sensor.py +0 -0
  223. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/__init__.py +0 -0
  224. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_events.py +0 -0
  225. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_cli.py +0 -0
  226. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_decorator.py +0 -0
  227. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_deployer.py +0 -0
  228. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_deployer_objects.py +0 -0
  229. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/capture_error.py +0 -0
  230. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/exit_hooks.py +0 -0
  231. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/generate_input_paths.py +0 -0
  232. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/jobset_input_paths.py +0 -0
  233. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/__init__.py +0 -0
  234. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/aws_client.py +0 -0
  235. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/aws_utils.py +0 -0
  236. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/__init__.py +0 -0
  237. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch_cli.py +0 -0
  238. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch_client.py +0 -0
  239. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch_decorator.py +0 -0
  240. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/secrets_manager/__init__.py +0 -0
  241. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +0 -0
  242. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/__init__.py +0 -0
  243. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -0
  244. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/event_bridge_client.py +0 -0
  245. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/production_token.py +0 -0
  246. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/schedule_decorator.py +0 -0
  247. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/set_batch_environment.py +0 -0
  248. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_client.py +0 -0
  249. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_decorator.py +0 -0
  250. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +0 -0
  251. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/__init__.py +0 -0
  252. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_credential.py +0 -0
  253. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_exceptions.py +0 -0
  254. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +0 -0
  255. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_tail.py +0 -0
  256. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_utils.py +0 -0
  257. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/blob_service_client_factory.py +0 -0
  258. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/includefile_support.py +0 -0
  259. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/__init__.py +0 -0
  260. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_cli.py +0 -0
  261. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_client.py +0 -0
  262. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_creator.py +0 -0
  263. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_datastore.py +0 -0
  264. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_decorator.py +0 -0
  265. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/__init__.py +0 -0
  266. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/base.html +0 -0
  267. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/basic.py +0 -0
  268. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/bundle.css +0 -0
  269. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/card.py +0 -0
  270. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/__init__.py +0 -0
  271. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/main.py +0 -0
  272. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/metadata.py +0 -0
  273. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/renderer.py +0 -0
  274. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/tokenizer.py +0 -0
  275. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/components.py +0 -0
  276. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/convert_to_native_type.py +0 -0
  277. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/main.css +0 -0
  278. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/main.js +0 -0
  279. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/renderer_tools.py +0 -0
  280. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/test_cards.py +0 -0
  281. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_resolver.py +0 -0
  282. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_server.py +0 -0
  283. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_viewer/viewer.html +0 -0
  284. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/component_serializer.py +0 -0
  285. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/exception.py +0 -0
  286. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/metadata.py +0 -0
  287. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/catch_decorator.py +0 -0
  288. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/__init__.py +0 -0
  289. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/azure_storage.py +0 -0
  290. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/gs_storage.py +0 -0
  291. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/local_storage.py +0 -0
  292. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/s3_storage.py +0 -0
  293. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/__init__.py +0 -0
  294. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/local.py +0 -0
  295. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/__init__.py +0 -0
  296. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3.py +0 -0
  297. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3op.py +0 -0
  298. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3tail.py +0 -0
  299. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3util.py +0 -0
  300. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/debug_logger.py +0 -0
  301. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/debug_monitor.py +0 -0
  302. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/__init__.py +0 -0
  303. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/client.py +0 -0
  304. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/client_modules.py +0 -0
  305. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/__init__.py +0 -0
  306. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/bytestream.py +0 -0
  307. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/channel.py +0 -0
  308. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/socket_bytestream.py +0 -0
  309. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/utils.py +0 -0
  310. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/emulate_test_lib/__init__.py +0 -0
  311. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +0 -0
  312. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +0 -0
  313. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/test_lib_impl/__init__.py +0 -0
  314. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +0 -0
  315. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/consts.py +0 -0
  316. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/data_transferer.py +0 -0
  317. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/exception_transferer.py +0 -0
  318. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/override_decorators.py +0 -0
  319. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/server.py +0 -0
  320. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/stub.py +0 -0
  321. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/utils.py +0 -0
  322. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/environment_decorator.py +0 -0
  323. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/events_decorator.py +0 -0
  324. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/exit_hook/__init__.py +0 -0
  325. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/exit_hook/exit_hook_decorator.py +0 -0
  326. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/exit_hook/exit_hook_script.py +0 -0
  327. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/frameworks/__init__.py +0 -0
  328. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/frameworks/pytorch.py +0 -0
  329. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/__init__.py +0 -0
  330. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +0 -0
  331. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_exceptions.py +0 -0
  332. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_storage_client_factory.py +0 -0
  333. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_tail.py +0 -0
  334. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_utils.py +0 -0
  335. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/includefile_support.py +0 -0
  336. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/__init__.py +0 -0
  337. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kube_utils.py +0 -0
  338. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes.py +0 -0
  339. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_cli.py +0 -0
  340. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_client.py +0 -0
  341. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_decorator.py +0 -0
  342. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_job.py +0 -0
  343. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_jobsets.py +0 -0
  344. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/spot_metadata_cli.py +0 -0
  345. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/spot_monitor_sidecar.py +0 -0
  346. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/logs_cli.py +0 -0
  347. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/metadata_providers/__init__.py +0 -0
  348. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/metadata_providers/local.py +0 -0
  349. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/metadata_providers/service.py +0 -0
  350. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/package_cli.py +0 -0
  351. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/parallel_decorator.py +0 -0
  352. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/project_decorator.py +0 -0
  353. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/__init__.py +0 -0
  354. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/bootstrap.py +0 -0
  355. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/conda_decorator.py +0 -0
  356. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/conda_environment.py +0 -0
  357. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/micromamba.py +0 -0
  358. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/parsers.py +0 -0
  359. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/pip.py +0 -0
  360. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/pypi_decorator.py +0 -0
  361. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/pypi_environment.py +0 -0
  362. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/utils.py +0 -0
  363. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/resources_decorator.py +0 -0
  364. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/retry_decorator.py +0 -0
  365. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/__init__.py +0 -0
  366. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/inline_secrets_provider.py +0 -0
  367. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/secrets_decorator.py +0 -0
  368. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/secrets_func.py +0 -0
  369. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/secrets_spec.py +0 -0
  370. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/utils.py +0 -0
  371. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/storage_executor.py +0 -0
  372. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/tag_cli.py +0 -0
  373. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/test_unbounded_foreach_decorator.py +0 -0
  374. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/timeout_decorator.py +0 -0
  375. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/uv/__init__.py +0 -0
  376. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/uv/bootstrap.py +0 -0
  377. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/uv/uv_environment.py +0 -0
  378. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/procpoll.py +0 -0
  379. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/py.typed +0 -0
  380. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/pylint_wrapper.py +0 -0
  381. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/__init__.py +0 -0
  382. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/click_api.py +0 -0
  383. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/deployer.py +0 -0
  384. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/deployer_impl.py +0 -0
  385. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/metaflow_runner.py +0 -0
  386. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/nbdeploy.py +0 -0
  387. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/nbrun.py +0 -0
  388. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/subprocess_manager.py +0 -0
  389. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/utils.py +0 -0
  390. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runtime.py +0 -0
  391. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/__init__.py +0 -0
  392. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar.py +0 -0
  393. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar_messages.py +0 -0
  394. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar_subprocess.py +0 -0
  395. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar_worker.py +0 -0
  396. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/__init__.py +0 -0
  397. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/system_logger.py +0 -0
  398. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/system_monitor.py +0 -0
  399. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/system_utils.py +0 -0
  400. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tagging_util.py +0 -0
  401. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/task.py +0 -0
  402. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/__init__.py +0 -0
  403. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/propagator.py +0 -0
  404. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/span_exporter.py +0 -0
  405. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/tracing_modules.py +0 -0
  406. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tuple_util.py +0 -0
  407. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/00-helloworld/README.md +0 -0
  408. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/00-helloworld/helloworld.py +0 -0
  409. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/README.md +0 -0
  410. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/movies.csv +0 -0
  411. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/playlist.ipynb +0 -0
  412. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/playlist.py +0 -0
  413. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/README.md +0 -0
  414. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/movies.csv +0 -0
  415. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/stats.ipynb +0 -0
  416. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/stats.py +0 -0
  417. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/03-playlist-redux/README.md +0 -0
  418. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/03-playlist-redux/playlist.py +0 -0
  419. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/04-playlist-plus/README.md +0 -0
  420. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/04-playlist-plus/playlist.py +0 -0
  421. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/05-hello-cloud/README.md +0 -0
  422. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/05-hello-cloud/hello-cloud.ipynb +0 -0
  423. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/05-hello-cloud/hello-cloud.py +0 -0
  424. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/06-statistics-redux/README.md +0 -0
  425. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/06-statistics-redux/stats.ipynb +0 -0
  426. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/07-worldview/README.md +0 -0
  427. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/07-worldview/worldview.ipynb +0 -0
  428. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/08-autopilot/README.md +0 -0
  429. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/08-autopilot/autopilot.ipynb +0 -0
  430. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/unbounded_foreach.py +0 -0
  431. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_configs/__init__.py +0 -0
  432. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_configs/config_options.py +0 -0
  433. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_configs/config_parameters.py +0 -0
  434. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/__init__.py +0 -0
  435. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/common.py +0 -0
  436. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/mutable_flow.py +0 -0
  437. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/mutable_step.py +0 -0
  438. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/user_flow_decorator.py +0 -0
  439. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/user_step_decorator.py +0 -0
  440. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/util.py +0 -0
  441. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/vendor.py +0 -0
  442. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/SOURCES.txt +0 -0
  443. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/dependency_links.txt +0 -0
  444. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/entry_points.txt +0 -0
  445. {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/top_level.txt +0 -0
  446. {metaflow-2.18.2 → metaflow-2.18.4}/setup.cfg +0 -0
  447. {metaflow-2.18.2 → metaflow-2.18.4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaflow
3
- Version: 2.18.2
3
+ Version: 2.18.4
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.18.2; extra == "stubs"
29
+ Requires-Dist: metaflow-stubs==2.18.4; extra == "stubs"
30
30
  Dynamic: author
31
31
  Dynamic: author-email
32
32
  Dynamic: classifier
@@ -303,7 +303,7 @@ class MetaflowObject(object):
303
303
  # distinguish between "attempt will happen" and "no such
304
304
  # attempt exists".
305
305
 
306
- if pathspec:
306
+ if pathspec and _object is None:
307
307
  ids = pathspec.split("/")
308
308
 
309
309
  if self._NAME == "flow" and len(ids) != 1:
@@ -344,6 +344,8 @@ SFN_S3_DISTRIBUTED_MAP_OUTPUT_PATH = from_conf(
344
344
  else None
345
345
  ),
346
346
  )
347
+ # Toggle for step command being part of the Step Function payload, or if it should be offloaded to S3
348
+ SFN_COMPRESS_STATE_MACHINE = from_conf("SFN_COMPRESS_STATE_MACHINE", False)
347
349
  ###
348
350
  # Kubernetes configuration
349
351
  ###
@@ -409,6 +411,9 @@ ARGO_EVENTS_INTERNAL_WEBHOOK_URL = from_conf(
409
411
  "ARGO_EVENTS_INTERNAL_WEBHOOK_URL", ARGO_EVENTS_WEBHOOK_URL
410
412
  )
411
413
  ARGO_EVENTS_WEBHOOK_AUTH = from_conf("ARGO_EVENTS_WEBHOOK_AUTH", "none")
414
+ ARGO_EVENTS_SENSOR_NAMESPACE = from_conf(
415
+ "ARGO_EVENTS_SENSOR_NAMESPACE", KUBERNETES_NAMESPACE
416
+ )
412
417
 
413
418
  ARGO_WORKFLOWS_UI_URL = from_conf("ARGO_WORKFLOWS_UI_URL")
414
419
 
@@ -1,5 +1,6 @@
1
1
  import json
2
2
 
3
+ from metaflow.metaflow_config import ARGO_EVENTS_SENSOR_NAMESPACE
3
4
  from metaflow.exception import MetaflowException
4
5
  from metaflow.plugins.kubernetes.kubernetes_client import KubernetesClient
5
6
 
@@ -377,12 +378,15 @@ class ArgoClient(object):
377
378
  json.loads(e.body)["message"] if e.body is not None else e.reason
378
379
  )
379
380
 
380
- def register_sensor(self, name, sensor=None):
381
+ def register_sensor(
382
+ self, name, sensor=None, sensor_namespace=ARGO_EVENTS_SENSOR_NAMESPACE
383
+ ):
381
384
  if sensor is None:
382
385
  sensor = {}
383
386
  # Unfortunately, Kubernetes client does not handle optimistic
384
387
  # concurrency control by itself unlike kubectl
385
388
  client = self._client.get()
389
+
386
390
  if not sensor:
387
391
  sensor["metadata"] = {}
388
392
 
@@ -392,7 +396,7 @@ class ArgoClient(object):
392
396
  ] = client.CustomObjectsApi().get_namespaced_custom_object(
393
397
  group=self._group,
394
398
  version=self._version,
395
- namespace=self._namespace,
399
+ namespace=sensor_namespace,
396
400
  plural="sensors",
397
401
  name=name,
398
402
  )[
@@ -407,7 +411,7 @@ class ArgoClient(object):
407
411
  return client.CustomObjectsApi().create_namespaced_custom_object(
408
412
  group=self._group,
409
413
  version=self._version,
410
- namespace=self._namespace,
414
+ namespace=sensor_namespace,
411
415
  plural="sensors",
412
416
  body=sensor,
413
417
  )
@@ -425,7 +429,7 @@ class ArgoClient(object):
425
429
  return client.CustomObjectsApi().replace_namespaced_custom_object(
426
430
  group=self._group,
427
431
  version=self._version,
428
- namespace=self._namespace,
432
+ namespace=sensor_namespace,
429
433
  plural="sensors",
430
434
  body=sensor,
431
435
  name=name,
@@ -435,7 +439,7 @@ class ArgoClient(object):
435
439
  json.loads(e.body)["message"] if e.body is not None else e.reason
436
440
  )
437
441
 
438
- def delete_sensor(self, name):
442
+ def delete_sensor(self, name, sensor_namespace):
439
443
  """
440
444
  Issues an API call for deleting a sensor
441
445
 
@@ -447,7 +451,7 @@ class ArgoClient(object):
447
451
  return client.CustomObjectsApi().delete_namespaced_custom_object(
448
452
  group=self._group,
449
453
  version=self._version,
450
- namespace=self._namespace,
454
+ namespace=sensor_namespace,
451
455
  plural="sensors",
452
456
  name=name,
453
457
  )
@@ -19,6 +19,7 @@ from metaflow.metaflow_config import (
19
19
  ARGO_EVENTS_EVENT_BUS,
20
20
  ARGO_EVENTS_EVENT_SOURCE,
21
21
  ARGO_EVENTS_INTERNAL_WEBHOOK_URL,
22
+ ARGO_EVENTS_SENSOR_NAMESPACE,
22
23
  ARGO_EVENTS_SERVICE_ACCOUNT,
23
24
  ARGO_EVENTS_WEBHOOK_AUTH,
24
25
  ARGO_WORKFLOWS_CAPTURE_ERROR_SCRIPT,
@@ -73,6 +74,10 @@ class ArgoWorkflowsException(MetaflowException):
73
74
  headline = "Argo Workflows error"
74
75
 
75
76
 
77
+ class ArgoWorkflowsSensorCleanupException(MetaflowException):
78
+ headline = "Argo Workflows sensor clean up error"
79
+
80
+
76
81
  class ArgoWorkflowsSchedulingException(MetaflowException):
77
82
  headline = "Argo Workflows scheduling error"
78
83
 
@@ -186,6 +191,7 @@ class ArgoWorkflows(object):
186
191
  return str(self._workflow_template)
187
192
 
188
193
  def deploy(self):
194
+ self.cleanup_previous_sensors()
189
195
  try:
190
196
  # Register workflow template.
191
197
  ArgoClient(namespace=KUBERNETES_NAMESPACE).register_workflow_template(
@@ -194,6 +200,37 @@ class ArgoWorkflows(object):
194
200
  except Exception as e:
195
201
  raise ArgoWorkflowsException(str(e))
196
202
 
203
+ def cleanup_previous_sensors(self):
204
+ try:
205
+ client = ArgoClient(namespace=KUBERNETES_NAMESPACE)
206
+ # Check for existing deployment and do cleanup
207
+ old_template = client.get_workflow_template(self.name)
208
+ if not old_template:
209
+ return None
210
+ # Clean up old sensors
211
+ old_sensor_namespace = old_template["metadata"]["annotations"].get(
212
+ "metaflow/sensor_namespace"
213
+ )
214
+
215
+ if old_sensor_namespace is None:
216
+ # This workflow was created before sensor annotations
217
+ # and may have a sensor in the default namespace
218
+ # we will delete it and it'll get recreated if need be
219
+ old_sensor_name = ArgoWorkflows._sensor_name(self.name)
220
+ client.delete_sensor(old_sensor_name, client._namespace)
221
+ else:
222
+ # delete old sensor only if it was somewhere else, otherwise it'll get replaced
223
+ old_sensor_name = old_template["metadata"]["annotations"][
224
+ "metaflow/sensor_name"
225
+ ]
226
+ if (
227
+ not self._sensor
228
+ or old_sensor_namespace != ARGO_EVENTS_SENSOR_NAMESPACE
229
+ ):
230
+ client.delete_sensor(old_sensor_name, old_sensor_namespace)
231
+ except Exception as e:
232
+ raise ArgoWorkflowsSensorCleanupException(str(e))
233
+
197
234
  @staticmethod
198
235
  def _sanitize(name):
199
236
  # Metaflow allows underscores in node names, which are disallowed in Argo
@@ -221,6 +258,20 @@ class ArgoWorkflows(object):
221
258
  def delete(name):
222
259
  client = ArgoClient(namespace=KUBERNETES_NAMESPACE)
223
260
 
261
+ # the workflow template might not exist, but we still want to try clean up associated sensors and schedules.
262
+ workflow_template = client.get_workflow_template(name) or {}
263
+ workflow_annotations = workflow_template.get("metadata", {}).get(
264
+ "annotations", {}
265
+ )
266
+
267
+ sensor_name = ArgoWorkflows._sensor_name(
268
+ workflow_annotations.get("metaflow/sensor_name", name)
269
+ )
270
+ # if below is missing then it was deployed before custom sensor namespaces
271
+ sensor_namespace = workflow_annotations.get(
272
+ "metaflow/sensor_namespace", KUBERNETES_NAMESPACE
273
+ )
274
+
224
275
  # Always try to delete the schedule. Failure in deleting the schedule should not
225
276
  # be treated as an error, due to any of the following reasons
226
277
  # - there might not have been a schedule, or it was deleted by some other means
@@ -230,7 +281,7 @@ class ArgoWorkflows(object):
230
281
 
231
282
  # The workflow might have sensors attached to it, which consume actual resources.
232
283
  # Try to delete these as well.
233
- sensor_deleted = client.delete_sensor(ArgoWorkflows._sensor_name(name))
284
+ sensor_deleted = client.delete_sensor(sensor_name, sensor_namespace)
234
285
 
235
286
  # After cleaning up related resources, delete the workflow in question.
236
287
  # Failure in deleting is treated as critical and will be made visible to the user
@@ -399,11 +450,10 @@ class ArgoWorkflows(object):
399
450
  # Metaflow will overwrite any existing sensor.
400
451
  sensor_name = ArgoWorkflows._sensor_name(self.name)
401
452
  if self._sensor:
402
- argo_client.register_sensor(sensor_name, self._sensor.to_json())
403
- else:
404
- # Since sensors occupy real resources, delete existing sensor if needed
405
- # Deregister sensors that might have existed before this deployment
406
- argo_client.delete_sensor(sensor_name)
453
+ # The new sensor will go into the sensor namespace specified
454
+ ArgoClient(namespace=ARGO_EVENTS_SENSOR_NAMESPACE).register_sensor(
455
+ sensor_name, self._sensor.to_json(), ARGO_EVENTS_SENSOR_NAMESPACE
456
+ )
407
457
  except Exception as e:
408
458
  raise ArgoWorkflowsSchedulingException(str(e))
409
459
 
@@ -730,6 +780,7 @@ class ArgoWorkflows(object):
730
780
  # references to them within the DAGTask.
731
781
 
732
782
  annotations = {}
783
+
733
784
  if self._schedule is not None:
734
785
  # timezone is an optional field and json dumps on None will result in null
735
786
  # hence configuring it to an empty string
@@ -752,7 +803,9 @@ class ArgoWorkflows(object):
752
803
  {key: trigger.get(key) for key in ["name", "type"]}
753
804
  for trigger in self.triggers
754
805
  ]
755
- )
806
+ ),
807
+ "metaflow/sensor_name": ArgoWorkflows._sensor_name(self.name),
808
+ "metaflow/sensor_namespace": ARGO_EVENTS_SENSOR_NAMESPACE,
756
809
  }
757
810
  )
758
811
  if self.notify_on_error:
@@ -931,7 +984,7 @@ class ArgoWorkflows(object):
931
984
  node_conditional_parents = {}
932
985
  node_conditional_branches = {}
933
986
 
934
- def _visit(node, seen, conditional_branch, conditional_parents=None):
987
+ def _visit(node, conditional_branch, conditional_parents=None):
935
988
  if not node.type == "split-switch" and not (
936
989
  conditional_branch and conditional_parents
937
990
  ):
@@ -940,7 +993,10 @@ class ArgoWorkflows(object):
940
993
 
941
994
  if node.type == "split-switch":
942
995
  conditional_branch = conditional_branch + [node.name]
943
- node_conditional_branches[node.name] = conditional_branch
996
+ c_br = node_conditional_branches.get(node.name, [])
997
+ node_conditional_branches[node.name] = c_br + [
998
+ b for b in conditional_branch if b not in c_br
999
+ ]
944
1000
 
945
1001
  conditional_parents = (
946
1002
  [node.name]
@@ -958,21 +1014,36 @@ class ArgoWorkflows(object):
958
1014
  if conditional_parents and not node.type == "split-switch":
959
1015
  node_conditional_parents[node.name] = conditional_parents
960
1016
  conditional_branch = conditional_branch + [node.name]
961
- node_conditional_branches[node.name] = conditional_branch
1017
+ c_br = node_conditional_branches.get(node.name, [])
1018
+ node_conditional_branches[node.name] = c_br + [
1019
+ b for b in conditional_branch if b not in c_br
1020
+ ]
962
1021
 
963
1022
  self.conditional_nodes.add(node.name)
964
1023
 
965
1024
  if conditional_branch and conditional_parents:
966
1025
  for n in node.out_funcs:
967
1026
  child = self.graph[n]
968
- if n not in seen:
969
- _visit(
970
- child, seen + [n], conditional_branch, conditional_parents
971
- )
1027
+ if child.name == node.name:
1028
+ continue
1029
+ _visit(child, conditional_branch, conditional_parents)
972
1030
 
973
1031
  # First we visit all nodes to determine conditional parents and branches
974
1032
  for n in self.graph:
975
- _visit(n, [], [])
1033
+ _visit(n, [])
1034
+
1035
+ # helper to clean up conditional info for all children of a node, until a new split-switch is encountered.
1036
+ def _cleanup_conditional_status(node_name, seen):
1037
+ if self.graph[node_name].type == "split-switch":
1038
+ # stop recursive cleanup if we hit a new split-switch
1039
+ return
1040
+ if node_name in self.conditional_nodes:
1041
+ self.conditional_nodes.remove(node_name)
1042
+ node_conditional_parents[node_name] = []
1043
+ node_conditional_branches[node_name] = []
1044
+ for p in self.graph[node_name].out_funcs:
1045
+ if p not in seen:
1046
+ _cleanup_conditional_status(p, seen + [p])
976
1047
 
977
1048
  # Then we traverse again in order to determine conditional join nodes, and matching conditional join info
978
1049
  for node in self.graph:
@@ -1005,14 +1076,44 @@ class ArgoWorkflows(object):
1005
1076
  last_conditional_split_nodes = self.graph[
1006
1077
  last_split_switch
1007
1078
  ].out_funcs
1008
- # p needs to be in at least one conditional_branch for it to be closed.
1009
- if all(
1010
- any(
1011
- p in node_conditional_branches.get(in_func, [])
1012
- for in_func in conditional_in_funcs
1079
+ # NOTE: How do we define a conditional join step?
1080
+ # The idea here is that we check if the conditional branches(e.g. chains of conditional steps leading to) of all the in_funcs
1081
+ # manage to tick off every step name that follows a split-switch
1082
+ # For example, consider the following structure
1083
+ # switch_step -> A, B, C
1084
+ # A -> A2 -> A3 -> A4 -> B2
1085
+ # B -> B2 -> B3 -> C3
1086
+ # C -> C2 -> C3 -> end
1087
+ #
1088
+ # if we look at the in_funcs for C3, they are (C2, B3)
1089
+ # B3 closes off branches started by A and B
1090
+ # C3 closes off branches started by C
1091
+ # therefore C3 is a conditional join step for the 'switch_step'
1092
+ # NOTE: Then what about a skip step?
1093
+ # some switch cases might not introduce any distinct steps of their own, opting to instead skip ahead to a later common step.
1094
+ # Example:
1095
+ # switch_step -> A, B, C
1096
+ # A -> A1 -> B2 -> C
1097
+ # B -> B1 -> B2 -> C
1098
+ #
1099
+ # In this case, C is a skip step as it does not add any conditional branching of its own.
1100
+ # C is also a conditional join, as it closes all branches started by 'switch_step'
1101
+
1102
+ closes_branches = all(
1103
+ (
1104
+ # branch_root_node_name needs to be in at least one conditional_branch for it to be closed.
1105
+ any(
1106
+ branch_root_node_name
1107
+ in node_conditional_branches.get(in_func, [])
1108
+ for in_func in conditional_in_funcs
1109
+ )
1110
+ # need to account for a switch case skipping completely, not having a conditional-branch of its own.
1111
+ if branch_root_node_name != node.name
1112
+ else True
1013
1113
  )
1014
- for p in last_conditional_split_nodes
1015
- ):
1114
+ for branch_root_node_name in last_conditional_split_nodes
1115
+ )
1116
+ if closes_branches:
1016
1117
  closed_conditional_parents.append(last_split_switch)
1017
1118
 
1018
1119
  self.conditional_join_nodes.add(node.name)
@@ -1026,25 +1127,45 @@ class ArgoWorkflows(object):
1026
1127
  for p in node_conditional_parents.get(node.name, [])
1027
1128
  if p not in closed_conditional_parents
1028
1129
  ]:
1029
- if node.name in self.conditional_nodes:
1030
- self.conditional_nodes.remove(node.name)
1031
- node_conditional_parents[node.name] = []
1032
- for p in node.out_funcs:
1033
- if p in self.conditional_nodes:
1034
- self.conditional_nodes.remove(p)
1035
- node_conditional_parents[p] = []
1130
+ _cleanup_conditional_status(node.name, [])
1036
1131
 
1037
1132
  def _is_conditional_node(self, node):
1038
1133
  return node.name in self.conditional_nodes
1039
1134
 
1135
+ def _is_conditional_skip_node(self, node):
1136
+ return (
1137
+ self._is_conditional_node(node)
1138
+ and any(
1139
+ self.graph[in_func].type == "split-switch" for in_func in node.in_funcs
1140
+ )
1141
+ and len(
1142
+ [
1143
+ in_func
1144
+ for in_func in node.in_funcs
1145
+ if self._is_conditional_node(self.graph[in_func])
1146
+ or self.graph[in_func].type == "split-switch"
1147
+ ]
1148
+ )
1149
+ > 1
1150
+ )
1151
+
1040
1152
  def _is_conditional_join_node(self, node):
1041
1153
  return node.name in self.conditional_join_nodes
1042
1154
 
1155
+ def _many_in_funcs_all_conditional(self, node):
1156
+ cond_in_funcs = [
1157
+ in_func
1158
+ for in_func in node.in_funcs
1159
+ if self._is_conditional_node(self.graph[in_func])
1160
+ ]
1161
+ return len(cond_in_funcs) > 1 and len(cond_in_funcs) == len(node.in_funcs)
1162
+
1043
1163
  def _is_recursive_node(self, node):
1044
1164
  return node.name in self.recursive_nodes
1045
1165
 
1046
1166
  def _matching_conditional_join(self, node):
1047
- return self.matching_conditional_join_dict.get(node.name, None)
1167
+ # If no earlier conditional join step is found during parsing, then 'end' is always one.
1168
+ return self.matching_conditional_join_dict.get(node.name, "end")
1048
1169
 
1049
1170
  # Visit every node and yield the uber DAGTemplate(s).
1050
1171
  def _dag_templates(self):
@@ -1224,12 +1345,24 @@ class ArgoWorkflows(object):
1224
1345
  "%s.Succeeded" % self._sanitize(in_func)
1225
1346
  for in_func in node.in_funcs
1226
1347
  if self._is_conditional_node(self.graph[in_func])
1348
+ or self.graph[in_func].type == "split-switch"
1227
1349
  ]
1228
1350
  required_deps = [
1229
1351
  "%s.Succeeded" % self._sanitize(in_func)
1230
1352
  for in_func in node.in_funcs
1231
1353
  if not self._is_conditional_node(self.graph[in_func])
1354
+ and self.graph[in_func].type != "split-switch"
1232
1355
  ]
1356
+ if self._is_conditional_skip_node(
1357
+ node
1358
+ ) or self._many_in_funcs_all_conditional(node):
1359
+ # skip nodes need unique condition handling
1360
+ conditional_deps = [
1361
+ "%s.Succeeded" % self._sanitize(in_func)
1362
+ for in_func in node.in_funcs
1363
+ ]
1364
+ required_deps = []
1365
+
1233
1366
  both_conditions = required_deps and conditional_deps
1234
1367
 
1235
1368
  depends_str = "{required}{_and}{conditional}".format(
@@ -1247,15 +1380,45 @@ class ArgoWorkflows(object):
1247
1380
  )
1248
1381
 
1249
1382
  # Add conditional if this is the first step in a conditional branch
1383
+ switch_in_funcs = [
1384
+ in_func
1385
+ for in_func in node.in_funcs
1386
+ if self.graph[in_func].type == "split-switch"
1387
+ ]
1250
1388
  if (
1251
1389
  self._is_conditional_node(node)
1252
- and self.graph[node.in_funcs[0]].type == "split-switch"
1253
- ):
1254
- in_func = node.in_funcs[0]
1255
- dag_task.when(
1256
- "{{tasks.%s.outputs.parameters.switch-step}}==%s"
1257
- % (self._sanitize(in_func), node.name)
1390
+ or self._is_conditional_skip_node(node)
1391
+ or self._is_conditional_join_node(node)
1392
+ ) and switch_in_funcs:
1393
+ conditional_when = "||".join(
1394
+ [
1395
+ "{{tasks.%s.outputs.parameters.switch-step}}==%s"
1396
+ % (self._sanitize(switch_in_func), node.name)
1397
+ for switch_in_func in switch_in_funcs
1398
+ ]
1399
+ )
1400
+
1401
+ non_switch_in_funcs = [
1402
+ in_func
1403
+ for in_func in node.in_funcs
1404
+ if in_func not in switch_in_funcs
1405
+ ]
1406
+ status_when = ""
1407
+ if non_switch_in_funcs:
1408
+ status_when = "||".join(
1409
+ [
1410
+ "{{tasks.%s.status}}==Succeeded"
1411
+ % self._sanitize(in_func)
1412
+ for in_func in non_switch_in_funcs
1413
+ ]
1414
+ )
1415
+
1416
+ total_when = (
1417
+ f"({status_when}) || ({conditional_when})"
1418
+ if status_when
1419
+ else conditional_when
1258
1420
  )
1421
+ dag_task.when(total_when)
1259
1422
 
1260
1423
  dag_tasks.append(dag_task)
1261
1424
  # End the workflow if we have reached the end of the flow
@@ -1699,7 +1862,11 @@ class ArgoWorkflows(object):
1699
1862
  input_paths_expr = (
1700
1863
  "export INPUT_PATHS={{inputs.parameters.input-paths}}"
1701
1864
  )
1702
- if self._is_conditional_join_node(node):
1865
+ if (
1866
+ self._is_conditional_join_node(node)
1867
+ or self._many_in_funcs_all_conditional(node)
1868
+ or self._is_conditional_skip_node(node)
1869
+ ):
1703
1870
  # NOTE: Argo template expressions that fail to resolve, output the expression itself as a value.
1704
1871
  # With conditional steps, some of the input-paths are therefore 'broken' due to containing a nil expression
1705
1872
  # e.g. "{{ tasks['A'].outputs.parameters.task-id }}" when task A never executed.
@@ -1879,20 +2046,33 @@ class ArgoWorkflows(object):
1879
2046
  )
1880
2047
  input_paths = "%s/_parameters/%s" % (run_id, task_id_params)
1881
2048
  # Only for static joins and conditional_joins
1882
- elif self._is_conditional_join_node(node) and not (
2049
+ elif (
2050
+ self._is_conditional_join_node(node)
2051
+ or self._many_in_funcs_all_conditional(node)
2052
+ or self._is_conditional_skip_node(node)
2053
+ ) and not (
1883
2054
  node.type == "join"
1884
2055
  and self.graph[node.split_parents[-1]].type == "foreach"
1885
2056
  ):
2057
+ # we need to pass in the set of conditional in_funcs to the pathspec generating script as in the case of split-switch skipping cases,
2058
+ # non-conditional input-paths need to be ignored in favour of conditional ones when they have executed.
2059
+ skippable_input_steps = ",".join(
2060
+ [
2061
+ in_func
2062
+ for in_func in node.in_funcs
2063
+ if self.graph[in_func].type == "split-switch"
2064
+ ]
2065
+ )
1886
2066
  input_paths = (
1887
- "$(python -m metaflow.plugins.argo.conditional_input_paths %s)"
1888
- % input_paths
2067
+ "$(python -m metaflow.plugins.argo.conditional_input_paths %s %s)"
2068
+ % (input_paths, skippable_input_steps)
1889
2069
  )
1890
2070
  elif (
1891
2071
  node.type == "join"
1892
2072
  and self.graph[node.split_parents[-1]].type == "foreach"
1893
2073
  ):
1894
2074
  # foreach-joins straight out of conditional branches are not yet supported
1895
- if self._is_conditional_join_node(node):
2075
+ if self._is_conditional_join_node(node) and len(node.in_funcs) > 1:
1896
2076
  raise ArgoWorkflowsException(
1897
2077
  "Conditional steps inside a foreach that transition directly into a join step are not currently supported.\n"
1898
2078
  "As a workaround, add a common step after the conditional steps %s "
@@ -3521,7 +3701,7 @@ class ArgoWorkflows(object):
3521
3701
  # Sensor metadata.
3522
3702
  ObjectMeta()
3523
3703
  .name(ArgoWorkflows._sensor_name(self.name))
3524
- .namespace(KUBERNETES_NAMESPACE)
3704
+ .namespace(ARGO_EVENTS_SENSOR_NAMESPACE)
3525
3705
  .labels(self._base_labels)
3526
3706
  .label("app.kubernetes.io/name", "metaflow-sensor")
3527
3707
  .annotations(self._base_annotations)
@@ -0,0 +1,35 @@
1
+ from math import inf
2
+ import sys
3
+ from metaflow.util import decompress_list, compress_list
4
+ import base64
5
+
6
+
7
+ def generate_input_paths(input_paths, skippable_steps):
8
+ # => run_id/step/:foo,bar
9
+ # input_paths are base64 encoded due to Argo shenanigans
10
+ decoded = base64.b64decode(input_paths).decode("utf-8")
11
+ paths = decompress_list(decoded)
12
+
13
+ # some of the paths are going to be malformed due to never having executed per conditional.
14
+ # strip these out of the list.
15
+
16
+ # all pathspecs of leading steps that executed.
17
+ trimmed = [path for path in paths if not "{{" in path]
18
+
19
+ # pathspecs of leading steps that are conditional, and should be used instead of non-conditional ones
20
+ # e.g. the case of skipping switches: start -> case_step -> conditional_a or end
21
+ conditionals = [
22
+ path for path in trimmed if not any(step in path for step in skippable_steps)
23
+ ]
24
+ pathspecs_to_use = conditionals if conditionals else trimmed
25
+ return compress_list(pathspecs_to_use, zlibmin=inf)
26
+
27
+
28
+ if __name__ == "__main__":
29
+ input_paths = sys.argv[1]
30
+ try:
31
+ skippable_steps = sys.argv[2].split(",")
32
+ except IndexError:
33
+ skippable_steps = []
34
+
35
+ print(generate_input_paths(input_paths, skippable_steps))
@@ -53,9 +53,10 @@ class BatchKilledException(MetaflowException):
53
53
 
54
54
 
55
55
  class Batch(object):
56
- def __init__(self, metadata, environment):
56
+ def __init__(self, metadata, environment, flow_datastore=None):
57
57
  self.metadata = metadata
58
58
  self.environment = environment
59
+ self.flow_datastore = flow_datastore
59
60
  self._client = BatchClient()
60
61
  atexit.register(lambda: self.job.kill() if hasattr(self, "job") else None)
61
62
 
@@ -67,6 +68,7 @@ class Batch(object):
67
68
  step_name,
68
69
  step_cmds,
69
70
  task_spec,
71
+ offload_command_to_s3,
70
72
  ):
71
73
  mflog_expr = export_mflog_env_vars(
72
74
  datastore_type="s3",
@@ -104,7 +106,43 @@ class Batch(object):
104
106
  # We lose the last logs in this scenario (although they are visible
105
107
  # still through AWS CloudWatch console).
106
108
  cmd_str += "c=$?; %s; exit $c" % BASH_SAVE_LOGS
107
- return shlex.split('bash -c "%s"' % cmd_str)
109
+ command = shlex.split('bash -c "%s"' % cmd_str)
110
+
111
+ if not offload_command_to_s3:
112
+ return command
113
+
114
+ # If S3 upload is enabled, we need to modify the command after it's created
115
+ if self.flow_datastore is None:
116
+ raise MetaflowException(
117
+ "Can not offload Batch command to S3 without a datastore configured."
118
+ )
119
+
120
+ from metaflow.plugins.aws.aws_utils import parse_s3_full_path
121
+
122
+ # Get the command that was created
123
+ # Upload the command to S3 during deployment
124
+ try:
125
+ command_bytes = cmd_str.encode("utf-8")
126
+ result_paths = self.flow_datastore.save_data([command_bytes], len_hint=1)
127
+ s3_path, _key = result_paths[0]
128
+
129
+ bucket, s3_object = parse_s3_full_path(s3_path)
130
+ download_script = "{python} -c '{script}'".format(
131
+ python=self.environment._python(),
132
+ script='import boto3, os; ep=os.getenv(\\"METAFLOW_S3_ENDPOINT_URL\\"); boto3.client(\\"s3\\", **({\\"endpoint_url\\":ep} if ep else {})).download_file(\\"%s\\", \\"%s\\", \\"/tmp/step_command.sh\\")'
133
+ % (bucket, s3_object),
134
+ )
135
+ download_cmd = (
136
+ f"{self.environment._get_install_dependencies_cmd('s3')} && " # required for boto3 due to the original dependencies cmd getting packaged, and not being downloaded in time.
137
+ f"{download_script} && "
138
+ f"chmod +x /tmp/step_command.sh && "
139
+ f"bash /tmp/step_command.sh"
140
+ )
141
+ new_cmd = shlex.split('bash -c "%s"' % download_cmd)
142
+ return new_cmd
143
+ except Exception as e:
144
+ print(f"Warning: Failed to upload command to S3: {e}")
145
+ print("Falling back to inline command")
108
146
 
109
147
  def _search_jobs(self, flow_name, run_id, user):
110
148
  if user is None:
@@ -207,6 +245,7 @@ class Batch(object):
207
245
  ephemeral_storage=None,
208
246
  log_driver=None,
209
247
  log_options=None,
248
+ offload_command_to_s3=False,
210
249
  ):
211
250
  job_name = self._job_name(
212
251
  attrs.get("metaflow.user"),
@@ -228,6 +267,7 @@ class Batch(object):
228
267
  step_name,
229
268
  [step_cli],
230
269
  task_spec,
270
+ offload_command_to_s3,
231
271
  )
232
272
  )
233
273
  .image(image)