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.
- {metaflow-2.18.2/metaflow.egg-info → metaflow-2.18.4}/PKG-INFO +2 -2
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/client/core.py +1 -1
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_config.py +5 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_client.py +10 -6
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows.py +222 -42
- metaflow-2.18.4/metaflow/plugins/argo/conditional_input_paths.py +35 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch.py +42 -2
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions.py +6 -1
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_cli.py +11 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_deployer.py +3 -0
- metaflow-2.18.4/metaflow/version.py +1 -0
- {metaflow-2.18.2 → metaflow-2.18.4/metaflow.egg-info}/PKG-INFO +2 -2
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/requires.txt +1 -1
- metaflow-2.18.2/metaflow/plugins/argo/conditional_input_paths.py +0 -21
- metaflow-2.18.2/metaflow/version.py +0 -1
- {metaflow-2.18.2 → metaflow-2.18.4}/LICENSE +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/MANIFEST.in +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/devtools/Makefile +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/devtools/Tiltfile +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/devtools/pick_services.sh +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/R.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_bashcomplete.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_compat.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_termui_impl.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_textwrap.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_unicodefun.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/_winconsole.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/core.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/decorators.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/exceptions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/formatting.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/globals.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/parser.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/termui.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/testing.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/types.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/click/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/imghdr/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_adapters.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_collections.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_compat.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_functools.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_itertools.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_meta.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/_text.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/importlib_metadata/py.typed +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_elffile.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_manylinux.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_musllinux.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_parser.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_structures.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/_tokenizer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/markers.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/py.typed +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/requirements.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/specifiers.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/tags.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/packaging/version.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_checkers.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_config.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_decorators.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_exceptions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_functions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_importhook.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_memo.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_pytest_plugin.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_suppression.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_transformer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_union_transformer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typeguard/py.typed +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/typing_extensions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_adapters.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_collections.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_compat.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_functools.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_itertools.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_meta.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/_text.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/importlib_metadata/py.typed +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/typing_extensions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_6/zipp.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_collections.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_compat.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_functools.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_meta.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/_text.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_checkers.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_config.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_decorators.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_exceptions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_functions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_importhook.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_memo.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_suppression.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_transformer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_union_transformer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/typing_extensions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/v3_7/zipp.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/composer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/constructor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/cyaml.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/dumper.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/emitter.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/error.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/events.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/loader.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/nodes.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/parser.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/reader.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/representer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/resolver.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/scanner.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/serializer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/yaml/tokens.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/_vendor/zipp.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cards.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_args.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/dump_cmd.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/init_cmd.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/run_cmds.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/step_cmd.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cli_components/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/client/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/client/filecache.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/clone_util.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/code/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/configure_cmd.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/develop/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/develop/stub_generator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/develop/stubs.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/main_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/make_wrapper.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/tutorials_cmd.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd/util.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/cmd_with_io.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/content_addressed_store.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/datastore_set.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/datastore_storage.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/exceptions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/flow_datastore.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/inputs.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/datastore/task_datastore.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/debug.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/decorators.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/event_logger.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/events.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/exception.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/_empty_file.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/cmd.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/integrations.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/extension_support/plugins.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/flowspec.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/graph.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/includefile.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/integrations.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/lint.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/meta_files.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/heartbeat.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/metadata.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metadata_provider/util.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_config_funcs.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_current.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_environment.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_git.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_profile.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/metaflow_version.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/mflog.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/save_logs.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/save_logs_periodically.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/mflog/tee.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/monitor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/multicore_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/package/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/backend.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/distribution_support.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/tar_backend.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/packaging_sys/v1.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/parameters.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/airflow_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/dag.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/exception.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/plumbing/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/plumbing/set_parameters.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/base_sensor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/external_task_sensor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/airflow/sensors/s3_sensor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_events.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_deployer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/argo_workflows_deployer_objects.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/capture_error.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/exit_hooks.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/generate_input_paths.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/argo/jobset_input_paths.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/aws_client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/aws_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch_client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/batch/batch_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/secrets_manager/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/event_bridge_client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/production_token.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/schedule_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/set_batch_environment.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_credential.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_exceptions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_tail.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/azure_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/blob_service_client_factory.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/azure/includefile_support.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_creator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_datastore.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/base.html +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/basic.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/bundle.css +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/card.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/main.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/metadata.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/renderer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/chevron/tokenizer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/components.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/convert_to_native_type.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/main.css +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/main.js +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/renderer_tools.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_modules/test_cards.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_resolver.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_server.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/card_viewer/viewer.html +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/component_serializer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/exception.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/cards/metadata.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/catch_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/azure_storage.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/gs_storage.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/local_storage.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datastores/s3_storage.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/local.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3op.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3tail.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/datatools/s3/s3util.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/debug_logger.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/debug_monitor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/client_modules.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/bytestream.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/channel.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/socket_bytestream.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/communication/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/emulate_test_lib/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/test_lib_impl/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/consts.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/data_transferer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/exception_transferer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/override_decorators.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/server.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/stub.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/env_escape/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/environment_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/events_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/exit_hook/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/exit_hook/exit_hook_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/exit_hook/exit_hook_script.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/frameworks/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/frameworks/pytorch.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_exceptions.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_storage_client_factory.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_tail.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/gs_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/gcp/includefile_support.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kube_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_client.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_job.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/kubernetes_jobsets.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/spot_metadata_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/kubernetes/spot_monitor_sidecar.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/logs_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/metadata_providers/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/metadata_providers/local.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/metadata_providers/service.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/package_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/parallel_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/project_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/bootstrap.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/conda_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/conda_environment.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/micromamba.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/parsers.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/pip.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/pypi_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/pypi_environment.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/pypi/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/resources_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/retry_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/inline_secrets_provider.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/secrets_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/secrets_func.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/secrets_spec.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/secrets/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/storage_executor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/tag_cli.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/test_unbounded_foreach_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/timeout_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/uv/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/uv/bootstrap.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/plugins/uv/uv_environment.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/procpoll.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/py.typed +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/pylint_wrapper.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/click_api.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/deployer.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/deployer_impl.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/metaflow_runner.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/nbdeploy.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/nbrun.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/subprocess_manager.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runner/utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/runtime.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar_messages.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar_subprocess.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/sidecar/sidecar_worker.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/system_logger.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/system_monitor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/system/system_utils.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tagging_util.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/task.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/propagator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/span_exporter.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tracing/tracing_modules.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tuple_util.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/00-helloworld/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/00-helloworld/helloworld.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/movies.csv +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/playlist.ipynb +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/01-playlist/playlist.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/movies.csv +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/stats.ipynb +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/02-statistics/stats.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/03-playlist-redux/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/03-playlist-redux/playlist.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/04-playlist-plus/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/04-playlist-plus/playlist.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/05-hello-cloud/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/05-hello-cloud/hello-cloud.ipynb +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/05-hello-cloud/hello-cloud.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/06-statistics-redux/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/06-statistics-redux/stats.ipynb +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/07-worldview/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/07-worldview/worldview.ipynb +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/08-autopilot/README.md +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/tutorials/08-autopilot/autopilot.ipynb +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/unbounded_foreach.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_configs/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_configs/config_options.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_configs/config_parameters.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/__init__.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/common.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/mutable_flow.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/mutable_step.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/user_flow_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/user_decorators/user_step_decorator.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/util.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow/vendor.py +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/SOURCES.txt +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/dependency_links.txt +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/entry_points.txt +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/metaflow.egg-info/top_level.txt +0 -0
- {metaflow-2.18.2 → metaflow-2.18.4}/setup.cfg +0 -0
- {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.
|
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.
|
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(
|
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=
|
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=
|
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=
|
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=
|
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(
|
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
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
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,
|
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
|
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
|
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
|
969
|
-
|
970
|
-
|
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
|
-
#
|
1009
|
-
if all
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
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
|
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
|
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(
|
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
|
-
|
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)
|