ob-metaflow 2.18.2.1__tar.gz → 2.18.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ob-metaflow might be problematic. Click here for more details.
- {ob_metaflow-2.18.2.1/ob_metaflow.egg-info → ob_metaflow-2.18.3.1}/PKG-INFO +2 -2
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/client/core.py +1 -1
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metaflow_config.py +5 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/argo_client.py +10 -6
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/argo_workflows.py +219 -42
- ob_metaflow-2.18.3.1/metaflow/plugins/argo/conditional_input_paths.py +35 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/batch/batch.py +42 -2
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/step_functions.py +6 -1
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/step_functions_cli.py +11 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/step_functions_deployer.py +3 -0
- ob_metaflow-2.18.3.1/metaflow/version.py +1 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1/ob_metaflow.egg-info}/PKG-INFO +2 -2
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/ob_metaflow.egg-info/requires.txt +1 -1
- ob_metaflow-2.18.2.1/metaflow/plugins/argo/conditional_input_paths.py +0 -21
- ob_metaflow-2.18.2.1/metaflow/version.py +0 -1
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/LICENSE +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/MANIFEST.in +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/devtools/Makefile +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/devtools/Tiltfile +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/devtools/pick_services.sh +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/R.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/_bashcomplete.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/_compat.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/_termui_impl.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/_textwrap.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/_unicodefun.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/_winconsole.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/core.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/decorators.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/exceptions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/formatting.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/globals.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/parser.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/termui.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/testing.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/types.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/click/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/imghdr/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/_adapters.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/_collections.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/_compat.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/_functools.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/_itertools.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/_meta.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/_text.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/importlib_metadata/py.typed +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/_elffile.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/_manylinux.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/_musllinux.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/_parser.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/_structures.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/_tokenizer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/markers.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/py.typed +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/requirements.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/specifiers.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/tags.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/packaging/version.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_checkers.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_config.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_decorators.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_exceptions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_functions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_importhook.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_memo.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_pytest_plugin.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_suppression.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_transformer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_union_transformer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typeguard/py.typed +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/typing_extensions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/_adapters.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/_collections.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/_compat.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/_functools.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/_itertools.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/_meta.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/_text.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/importlib_metadata/py.typed +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/typing_extensions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_6/zipp.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/_collections.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/_compat.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/_functools.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/_meta.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/_text.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_checkers.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_config.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_decorators.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_exceptions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_functions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_importhook.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_memo.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_suppression.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_transformer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_union_transformer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/typing_extensions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/v3_7/zipp.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/composer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/constructor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/cyaml.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/dumper.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/emitter.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/error.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/events.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/loader.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/nodes.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/parser.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/reader.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/representer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/resolver.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/scanner.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/serializer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/yaml/tokens.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/_vendor/zipp.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cards.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli_args.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli_components/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli_components/dump_cmd.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli_components/init_cmd.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli_components/run_cmds.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli_components/step_cmd.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cli_components/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/client/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/client/filecache.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/clone_util.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/code/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/configure_cmd.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/develop/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/develop/stub_generator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/develop/stubs.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/main_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/make_wrapper.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/tutorials_cmd.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd/util.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/cmd_with_io.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/content_addressed_store.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/datastore_set.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/datastore_storage.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/exceptions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/flow_datastore.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/inputs.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/datastore/task_datastore.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/debug.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/decorators.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/event_logger.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/events.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/exception.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/extension_support/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/extension_support/_empty_file.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/extension_support/cmd.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/extension_support/integrations.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/extension_support/plugins.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/flowspec.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/graph.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/includefile.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/integrations.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/lint.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/meta_files.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metadata_provider/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metadata_provider/heartbeat.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metadata_provider/metadata.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metadata_provider/util.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metaflow_config_funcs.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metaflow_current.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metaflow_environment.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metaflow_git.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metaflow_profile.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/metaflow_version.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/mflog/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/mflog/mflog.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/mflog/save_logs.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/mflog/save_logs_periodically.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/mflog/tee.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/monitor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/multicore_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/package/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/packaging_sys/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/packaging_sys/backend.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/packaging_sys/distribution_support.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/packaging_sys/tar_backend.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/packaging_sys/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/packaging_sys/v1.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/parameters.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/airflow.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/airflow_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/airflow_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/airflow_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/dag.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/exception.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/plumbing/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/plumbing/set_parameters.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/sensors/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/sensors/base_sensor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/sensors/external_task_sensor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/airflow/sensors/s3_sensor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/argo_events.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/argo_workflows_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/argo_workflows_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/argo_workflows_deployer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/argo_workflows_deployer_objects.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/capture_error.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/exit_hooks.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/generate_input_paths.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/argo/jobset_input_paths.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/aws_client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/aws_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/batch/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/batch/batch_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/batch/batch_client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/batch/batch_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/secrets_manager/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/event_bridge_client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/production_token.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/schedule_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/set_batch_environment.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/step_functions_client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/step_functions_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/azure_credential.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/azure_exceptions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/azure_tail.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/azure_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/blob_service_client_factory.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/azure/includefile_support.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_creator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_datastore.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/base.html +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/basic.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/bundle.css +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/card.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/chevron/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/chevron/main.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/chevron/metadata.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/chevron/renderer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/chevron/tokenizer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/components.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/convert_to_native_type.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/main.css +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/main.js +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/renderer_tools.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_modules/test_cards.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_resolver.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_server.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/card_viewer/viewer.html +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/component_serializer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/exception.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/cards/metadata.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/catch_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datastores/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datastores/azure_storage.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datastores/gs_storage.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datastores/local_storage.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datastores/s3_storage.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datatools/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datatools/local.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datatools/s3/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datatools/s3/s3.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datatools/s3/s3op.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datatools/s3/s3tail.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/datatools/s3/s3util.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/debug_logger.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/debug_monitor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/client_modules.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/communication/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/communication/bytestream.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/communication/channel.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/communication/socket_bytestream.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/communication/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/configurations/test_lib_impl/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/consts.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/data_transferer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/exception_transferer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/override_decorators.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/server.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/stub.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/env_escape/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/environment_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/events_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/exit_hook/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/exit_hook/exit_hook_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/exit_hook/exit_hook_script.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/frameworks/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/frameworks/pytorch.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/gcp/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/gcp/gs_exceptions.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/gcp/gs_storage_client_factory.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/gcp/gs_tail.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/gcp/gs_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/gcp/includefile_support.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/kube_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/kubernetes.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/kubernetes_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/kubernetes_client.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/kubernetes_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/kubernetes_job.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/kubernetes_jobsets.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/spot_metadata_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/kubernetes/spot_monitor_sidecar.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/logs_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/metadata_providers/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/metadata_providers/local.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/metadata_providers/service.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/package_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/parallel_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/project_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/bootstrap.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/conda_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/conda_environment.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/micromamba.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/parsers.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/pip.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/pypi_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/pypi_environment.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/pypi/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/resources_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/retry_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/secrets/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/secrets/inline_secrets_provider.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/secrets/secrets_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/secrets/secrets_func.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/secrets/secrets_spec.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/secrets/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/storage_executor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/tag_cli.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/test_unbounded_foreach_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/timeout_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/uv/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/uv/bootstrap.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/plugins/uv/uv_environment.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/procpoll.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/py.typed +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/pylint_wrapper.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/click_api.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/deployer.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/deployer_impl.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/metaflow_runner.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/nbdeploy.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/nbrun.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/subprocess_manager.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runner/utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/runtime.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/sidecar/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/sidecar/sidecar.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/sidecar/sidecar_messages.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/sidecar/sidecar_subprocess.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/sidecar/sidecar_worker.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/system/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/system/system_logger.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/system/system_monitor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/system/system_utils.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tagging_util.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/task.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tracing/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tracing/propagator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tracing/span_exporter.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tracing/tracing_modules.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tuple_util.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/00-helloworld/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/00-helloworld/helloworld.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/01-playlist/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/01-playlist/movies.csv +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/01-playlist/playlist.ipynb +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/01-playlist/playlist.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/02-statistics/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/02-statistics/movies.csv +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/02-statistics/stats.ipynb +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/02-statistics/stats.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/03-playlist-redux/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/03-playlist-redux/playlist.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/04-playlist-plus/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/04-playlist-plus/playlist.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/05-hello-cloud/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/05-hello-cloud/hello-cloud.ipynb +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/05-hello-cloud/hello-cloud.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/06-statistics-redux/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/06-statistics-redux/stats.ipynb +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/07-worldview/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/07-worldview/worldview.ipynb +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/08-autopilot/README.md +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/tutorials/08-autopilot/autopilot.ipynb +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/unbounded_foreach.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_configs/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_configs/config_options.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_configs/config_parameters.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_decorators/__init__.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_decorators/common.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_decorators/mutable_flow.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_decorators/mutable_step.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_decorators/user_flow_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/user_decorators/user_step_decorator.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/util.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/metaflow/vendor.py +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/ob_metaflow.egg-info/SOURCES.txt +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/ob_metaflow.egg-info/dependency_links.txt +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/ob_metaflow.egg-info/entry_points.txt +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/ob_metaflow.egg-info/top_level.txt +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/setup.cfg +0 -0
- {ob_metaflow-2.18.2.1 → ob_metaflow-2.18.3.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ob-metaflow
|
|
3
|
-
Version: 2.18.
|
|
3
|
+
Version: 2.18.3.1
|
|
4
4
|
Summary: Metaflow: More AI and ML, Less Engineering
|
|
5
5
|
Author: Netflix, Outerbounds & the Metaflow Community
|
|
6
6
|
Author-email: help@outerbounds.co
|
|
@@ -12,7 +12,7 @@ Requires-Dist: boto3
|
|
|
12
12
|
Requires-Dist: pylint
|
|
13
13
|
Requires-Dist: kubernetes
|
|
14
14
|
Provides-Extra: stubs
|
|
15
|
-
Requires-Dist: metaflow-stubs==2.18.
|
|
15
|
+
Requires-Dist: metaflow-stubs==2.18.3.1; extra == "stubs"
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: author-email
|
|
18
18
|
Dynamic: description
|
|
@@ -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:
|
|
@@ -345,6 +345,8 @@ SFN_S3_DISTRIBUTED_MAP_OUTPUT_PATH = from_conf(
|
|
|
345
345
|
else None
|
|
346
346
|
),
|
|
347
347
|
)
|
|
348
|
+
# Toggle for step command being part of the Step Function payload, or if it should be offloaded to S3
|
|
349
|
+
SFN_COMPRESS_STATE_MACHINE = from_conf("SFN_COMPRESS_STATE_MACHINE", False)
|
|
348
350
|
###
|
|
349
351
|
# Kubernetes configuration
|
|
350
352
|
###
|
|
@@ -410,6 +412,9 @@ ARGO_EVENTS_INTERNAL_WEBHOOK_URL = from_conf(
|
|
|
410
412
|
"ARGO_EVENTS_INTERNAL_WEBHOOK_URL", ARGO_EVENTS_WEBHOOK_URL
|
|
411
413
|
)
|
|
412
414
|
ARGO_EVENTS_WEBHOOK_AUTH = from_conf("ARGO_EVENTS_WEBHOOK_AUTH", "none")
|
|
415
|
+
ARGO_EVENTS_SENSOR_NAMESPACE = from_conf(
|
|
416
|
+
"ARGO_EVENTS_SENSOR_NAMESPACE", KUBERNETES_NAMESPACE
|
|
417
|
+
)
|
|
413
418
|
|
|
414
419
|
ARGO_WORKFLOWS_UI_URL = from_conf("ARGO_WORKFLOWS_UI_URL")
|
|
415
420
|
|
|
@@ -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,
|
|
@@ -74,6 +75,10 @@ class ArgoWorkflowsException(MetaflowException):
|
|
|
74
75
|
headline = "Argo Workflows error"
|
|
75
76
|
|
|
76
77
|
|
|
78
|
+
class ArgoWorkflowsSensorCleanupException(MetaflowException):
|
|
79
|
+
headline = "Argo Workflows sensor clean up error"
|
|
80
|
+
|
|
81
|
+
|
|
77
82
|
class ArgoWorkflowsSchedulingException(MetaflowException):
|
|
78
83
|
headline = "Argo Workflows scheduling error"
|
|
79
84
|
|
|
@@ -195,6 +200,7 @@ class ArgoWorkflows(object):
|
|
|
195
200
|
return str(self._workflow_template)
|
|
196
201
|
|
|
197
202
|
def deploy(self):
|
|
203
|
+
self.cleanup_previous_sensors()
|
|
198
204
|
try:
|
|
199
205
|
# Register workflow template.
|
|
200
206
|
ArgoClient(namespace=KUBERNETES_NAMESPACE).register_workflow_template(
|
|
@@ -203,6 +209,37 @@ class ArgoWorkflows(object):
|
|
|
203
209
|
except Exception as e:
|
|
204
210
|
raise ArgoWorkflowsException(str(e))
|
|
205
211
|
|
|
212
|
+
def cleanup_previous_sensors(self):
|
|
213
|
+
try:
|
|
214
|
+
client = ArgoClient(namespace=KUBERNETES_NAMESPACE)
|
|
215
|
+
# Check for existing deployment and do cleanup
|
|
216
|
+
old_template = client.get_workflow_template(self.name)
|
|
217
|
+
if not old_template:
|
|
218
|
+
return None
|
|
219
|
+
# Clean up old sensors
|
|
220
|
+
old_sensor_namespace = old_template["metadata"]["annotations"].get(
|
|
221
|
+
"metaflow/sensor_namespace"
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
if old_sensor_namespace is None:
|
|
225
|
+
# This workflow was created before sensor annotations
|
|
226
|
+
# and may have a sensor in the default namespace
|
|
227
|
+
# we will delete it and it'll get recreated if need be
|
|
228
|
+
old_sensor_name = ArgoWorkflows._sensor_name(self.name)
|
|
229
|
+
client.delete_sensor(old_sensor_name, client._namespace)
|
|
230
|
+
else:
|
|
231
|
+
# delete old sensor only if it was somewhere else, otherwise it'll get replaced
|
|
232
|
+
old_sensor_name = old_template["metadata"]["annotations"][
|
|
233
|
+
"metaflow/sensor_name"
|
|
234
|
+
]
|
|
235
|
+
if (
|
|
236
|
+
not self._sensor
|
|
237
|
+
or old_sensor_namespace != ARGO_EVENTS_SENSOR_NAMESPACE
|
|
238
|
+
):
|
|
239
|
+
client.delete_sensor(old_sensor_name, old_sensor_namespace)
|
|
240
|
+
except Exception as e:
|
|
241
|
+
raise ArgoWorkflowsSensorCleanupException(str(e))
|
|
242
|
+
|
|
206
243
|
@staticmethod
|
|
207
244
|
def _sanitize(name):
|
|
208
245
|
# Metaflow allows underscores in node names, which are disallowed in Argo
|
|
@@ -230,6 +267,17 @@ class ArgoWorkflows(object):
|
|
|
230
267
|
def delete(name):
|
|
231
268
|
client = ArgoClient(namespace=KUBERNETES_NAMESPACE)
|
|
232
269
|
|
|
270
|
+
workflow_template = client.get_workflow_template(name)
|
|
271
|
+
sensor_name = ArgoWorkflows._sensor_name(
|
|
272
|
+
workflow_template["metadata"]["annotations"].get(
|
|
273
|
+
"metaflow/sensor_name", name
|
|
274
|
+
)
|
|
275
|
+
)
|
|
276
|
+
# if below is missing then it was deployed before custom sensor namespaces
|
|
277
|
+
sensor_namespace = workflow_template["metadata"]["annotations"].get(
|
|
278
|
+
"metaflow/sensor_namespace", KUBERNETES_NAMESPACE
|
|
279
|
+
)
|
|
280
|
+
|
|
233
281
|
# Always try to delete the schedule. Failure in deleting the schedule should not
|
|
234
282
|
# be treated as an error, due to any of the following reasons
|
|
235
283
|
# - there might not have been a schedule, or it was deleted by some other means
|
|
@@ -239,7 +287,7 @@ class ArgoWorkflows(object):
|
|
|
239
287
|
|
|
240
288
|
# The workflow might have sensors attached to it, which consume actual resources.
|
|
241
289
|
# Try to delete these as well.
|
|
242
|
-
sensor_deleted = client.delete_sensor(
|
|
290
|
+
sensor_deleted = client.delete_sensor(sensor_name, sensor_namespace)
|
|
243
291
|
|
|
244
292
|
# After cleaning up related resources, delete the workflow in question.
|
|
245
293
|
# Failure in deleting is treated as critical and will be made visible to the user
|
|
@@ -408,11 +456,10 @@ class ArgoWorkflows(object):
|
|
|
408
456
|
# Metaflow will overwrite any existing sensor.
|
|
409
457
|
sensor_name = ArgoWorkflows._sensor_name(self.name)
|
|
410
458
|
if self._sensor:
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
argo_client.delete_sensor(sensor_name)
|
|
459
|
+
# The new sensor will go into the sensor namespace specified
|
|
460
|
+
ArgoClient(namespace=ARGO_EVENTS_SENSOR_NAMESPACE).register_sensor(
|
|
461
|
+
sensor_name, self._sensor.to_json(), ARGO_EVENTS_SENSOR_NAMESPACE
|
|
462
|
+
)
|
|
416
463
|
except Exception as e:
|
|
417
464
|
raise ArgoWorkflowsSchedulingException(str(e))
|
|
418
465
|
|
|
@@ -739,6 +786,7 @@ class ArgoWorkflows(object):
|
|
|
739
786
|
# references to them within the DAGTask.
|
|
740
787
|
|
|
741
788
|
annotations = {}
|
|
789
|
+
|
|
742
790
|
if self._schedule is not None:
|
|
743
791
|
# timezone is an optional field and json dumps on None will result in null
|
|
744
792
|
# hence configuring it to an empty string
|
|
@@ -761,7 +809,9 @@ class ArgoWorkflows(object):
|
|
|
761
809
|
{key: trigger.get(key) for key in ["name", "type"]}
|
|
762
810
|
for trigger in self.triggers
|
|
763
811
|
]
|
|
764
|
-
)
|
|
812
|
+
),
|
|
813
|
+
"metaflow/sensor_name": ArgoWorkflows._sensor_name(self.name),
|
|
814
|
+
"metaflow/sensor_namespace": ARGO_EVENTS_SENSOR_NAMESPACE,
|
|
765
815
|
}
|
|
766
816
|
)
|
|
767
817
|
if self.notify_on_error:
|
|
@@ -940,7 +990,7 @@ class ArgoWorkflows(object):
|
|
|
940
990
|
node_conditional_parents = {}
|
|
941
991
|
node_conditional_branches = {}
|
|
942
992
|
|
|
943
|
-
def _visit(node,
|
|
993
|
+
def _visit(node, conditional_branch, conditional_parents=None):
|
|
944
994
|
if not node.type == "split-switch" and not (
|
|
945
995
|
conditional_branch and conditional_parents
|
|
946
996
|
):
|
|
@@ -949,7 +999,10 @@ class ArgoWorkflows(object):
|
|
|
949
999
|
|
|
950
1000
|
if node.type == "split-switch":
|
|
951
1001
|
conditional_branch = conditional_branch + [node.name]
|
|
952
|
-
node_conditional_branches
|
|
1002
|
+
c_br = node_conditional_branches.get(node.name, [])
|
|
1003
|
+
node_conditional_branches[node.name] = c_br + [
|
|
1004
|
+
b for b in conditional_branch if b not in c_br
|
|
1005
|
+
]
|
|
953
1006
|
|
|
954
1007
|
conditional_parents = (
|
|
955
1008
|
[node.name]
|
|
@@ -967,21 +1020,36 @@ class ArgoWorkflows(object):
|
|
|
967
1020
|
if conditional_parents and not node.type == "split-switch":
|
|
968
1021
|
node_conditional_parents[node.name] = conditional_parents
|
|
969
1022
|
conditional_branch = conditional_branch + [node.name]
|
|
970
|
-
node_conditional_branches
|
|
1023
|
+
c_br = node_conditional_branches.get(node.name, [])
|
|
1024
|
+
node_conditional_branches[node.name] = c_br + [
|
|
1025
|
+
b for b in conditional_branch if b not in c_br
|
|
1026
|
+
]
|
|
971
1027
|
|
|
972
1028
|
self.conditional_nodes.add(node.name)
|
|
973
1029
|
|
|
974
1030
|
if conditional_branch and conditional_parents:
|
|
975
1031
|
for n in node.out_funcs:
|
|
976
1032
|
child = self.graph[n]
|
|
977
|
-
if
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
)
|
|
1033
|
+
if child.name == node.name:
|
|
1034
|
+
continue
|
|
1035
|
+
_visit(child, conditional_branch, conditional_parents)
|
|
981
1036
|
|
|
982
1037
|
# First we visit all nodes to determine conditional parents and branches
|
|
983
1038
|
for n in self.graph:
|
|
984
|
-
_visit(n, []
|
|
1039
|
+
_visit(n, [])
|
|
1040
|
+
|
|
1041
|
+
# helper to clean up conditional info for all children of a node, until a new split-switch is encountered.
|
|
1042
|
+
def _cleanup_conditional_status(node_name, seen):
|
|
1043
|
+
if self.graph[node_name].type == "split-switch":
|
|
1044
|
+
# stop recursive cleanup if we hit a new split-switch
|
|
1045
|
+
return
|
|
1046
|
+
if node_name in self.conditional_nodes:
|
|
1047
|
+
self.conditional_nodes.remove(node_name)
|
|
1048
|
+
node_conditional_parents[node_name] = []
|
|
1049
|
+
node_conditional_branches[node_name] = []
|
|
1050
|
+
for p in self.graph[node_name].out_funcs:
|
|
1051
|
+
if p not in seen:
|
|
1052
|
+
_cleanup_conditional_status(p, seen + [p])
|
|
985
1053
|
|
|
986
1054
|
# Then we traverse again in order to determine conditional join nodes, and matching conditional join info
|
|
987
1055
|
for node in self.graph:
|
|
@@ -1014,14 +1082,44 @@ class ArgoWorkflows(object):
|
|
|
1014
1082
|
last_conditional_split_nodes = self.graph[
|
|
1015
1083
|
last_split_switch
|
|
1016
1084
|
].out_funcs
|
|
1017
|
-
#
|
|
1018
|
-
if all
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1085
|
+
# NOTE: How do we define a conditional join step?
|
|
1086
|
+
# The idea here is that we check if the conditional branches(e.g. chains of conditional steps leading to) of all the in_funcs
|
|
1087
|
+
# manage to tick off every step name that follows a split-switch
|
|
1088
|
+
# For example, consider the following structure
|
|
1089
|
+
# switch_step -> A, B, C
|
|
1090
|
+
# A -> A2 -> A3 -> A4 -> B2
|
|
1091
|
+
# B -> B2 -> B3 -> C3
|
|
1092
|
+
# C -> C2 -> C3 -> end
|
|
1093
|
+
#
|
|
1094
|
+
# if we look at the in_funcs for C3, they are (C2, B3)
|
|
1095
|
+
# B3 closes off branches started by A and B
|
|
1096
|
+
# C3 closes off branches started by C
|
|
1097
|
+
# therefore C3 is a conditional join step for the 'switch_step'
|
|
1098
|
+
# NOTE: Then what about a skip step?
|
|
1099
|
+
# some switch cases might not introduce any distinct steps of their own, opting to instead skip ahead to a later common step.
|
|
1100
|
+
# Example:
|
|
1101
|
+
# switch_step -> A, B, C
|
|
1102
|
+
# A -> A1 -> B2 -> C
|
|
1103
|
+
# B -> B1 -> B2 -> C
|
|
1104
|
+
#
|
|
1105
|
+
# In this case, C is a skip step as it does not add any conditional branching of its own.
|
|
1106
|
+
# C is also a conditional join, as it closes all branches started by 'switch_step'
|
|
1107
|
+
|
|
1108
|
+
closes_branches = all(
|
|
1109
|
+
(
|
|
1110
|
+
# branch_root_node_name needs to be in at least one conditional_branch for it to be closed.
|
|
1111
|
+
any(
|
|
1112
|
+
branch_root_node_name
|
|
1113
|
+
in node_conditional_branches.get(in_func, [])
|
|
1114
|
+
for in_func in conditional_in_funcs
|
|
1115
|
+
)
|
|
1116
|
+
# need to account for a switch case skipping completely, not having a conditional-branch of its own.
|
|
1117
|
+
if branch_root_node_name != node.name
|
|
1118
|
+
else True
|
|
1022
1119
|
)
|
|
1023
|
-
for
|
|
1024
|
-
)
|
|
1120
|
+
for branch_root_node_name in last_conditional_split_nodes
|
|
1121
|
+
)
|
|
1122
|
+
if closes_branches:
|
|
1025
1123
|
closed_conditional_parents.append(last_split_switch)
|
|
1026
1124
|
|
|
1027
1125
|
self.conditional_join_nodes.add(node.name)
|
|
@@ -1035,25 +1133,45 @@ class ArgoWorkflows(object):
|
|
|
1035
1133
|
for p in node_conditional_parents.get(node.name, [])
|
|
1036
1134
|
if p not in closed_conditional_parents
|
|
1037
1135
|
]:
|
|
1038
|
-
|
|
1039
|
-
self.conditional_nodes.remove(node.name)
|
|
1040
|
-
node_conditional_parents[node.name] = []
|
|
1041
|
-
for p in node.out_funcs:
|
|
1042
|
-
if p in self.conditional_nodes:
|
|
1043
|
-
self.conditional_nodes.remove(p)
|
|
1044
|
-
node_conditional_parents[p] = []
|
|
1136
|
+
_cleanup_conditional_status(node.name, [])
|
|
1045
1137
|
|
|
1046
1138
|
def _is_conditional_node(self, node):
|
|
1047
1139
|
return node.name in self.conditional_nodes
|
|
1048
1140
|
|
|
1141
|
+
def _is_conditional_skip_node(self, node):
|
|
1142
|
+
return (
|
|
1143
|
+
self._is_conditional_node(node)
|
|
1144
|
+
and any(
|
|
1145
|
+
self.graph[in_func].type == "split-switch" for in_func in node.in_funcs
|
|
1146
|
+
)
|
|
1147
|
+
and len(
|
|
1148
|
+
[
|
|
1149
|
+
in_func
|
|
1150
|
+
for in_func in node.in_funcs
|
|
1151
|
+
if self._is_conditional_node(self.graph[in_func])
|
|
1152
|
+
or self.graph[in_func].type == "split-switch"
|
|
1153
|
+
]
|
|
1154
|
+
)
|
|
1155
|
+
> 1
|
|
1156
|
+
)
|
|
1157
|
+
|
|
1049
1158
|
def _is_conditional_join_node(self, node):
|
|
1050
1159
|
return node.name in self.conditional_join_nodes
|
|
1051
1160
|
|
|
1161
|
+
def _many_in_funcs_all_conditional(self, node):
|
|
1162
|
+
cond_in_funcs = [
|
|
1163
|
+
in_func
|
|
1164
|
+
for in_func in node.in_funcs
|
|
1165
|
+
if self._is_conditional_node(self.graph[in_func])
|
|
1166
|
+
]
|
|
1167
|
+
return len(cond_in_funcs) > 1 and len(cond_in_funcs) == len(node.in_funcs)
|
|
1168
|
+
|
|
1052
1169
|
def _is_recursive_node(self, node):
|
|
1053
1170
|
return node.name in self.recursive_nodes
|
|
1054
1171
|
|
|
1055
1172
|
def _matching_conditional_join(self, node):
|
|
1056
|
-
|
|
1173
|
+
# If no earlier conditional join step is found during parsing, then 'end' is always one.
|
|
1174
|
+
return self.matching_conditional_join_dict.get(node.name, "end")
|
|
1057
1175
|
|
|
1058
1176
|
# Visit every node and yield the uber DAGTemplate(s).
|
|
1059
1177
|
def _dag_templates(self):
|
|
@@ -1233,12 +1351,24 @@ class ArgoWorkflows(object):
|
|
|
1233
1351
|
"%s.Succeeded" % self._sanitize(in_func)
|
|
1234
1352
|
for in_func in node.in_funcs
|
|
1235
1353
|
if self._is_conditional_node(self.graph[in_func])
|
|
1354
|
+
or self.graph[in_func].type == "split-switch"
|
|
1236
1355
|
]
|
|
1237
1356
|
required_deps = [
|
|
1238
1357
|
"%s.Succeeded" % self._sanitize(in_func)
|
|
1239
1358
|
for in_func in node.in_funcs
|
|
1240
1359
|
if not self._is_conditional_node(self.graph[in_func])
|
|
1360
|
+
and self.graph[in_func].type != "split-switch"
|
|
1241
1361
|
]
|
|
1362
|
+
if self._is_conditional_skip_node(
|
|
1363
|
+
node
|
|
1364
|
+
) or self._many_in_funcs_all_conditional(node):
|
|
1365
|
+
# skip nodes need unique condition handling
|
|
1366
|
+
conditional_deps = [
|
|
1367
|
+
"%s.Succeeded" % self._sanitize(in_func)
|
|
1368
|
+
for in_func in node.in_funcs
|
|
1369
|
+
]
|
|
1370
|
+
required_deps = []
|
|
1371
|
+
|
|
1242
1372
|
both_conditions = required_deps and conditional_deps
|
|
1243
1373
|
|
|
1244
1374
|
depends_str = "{required}{_and}{conditional}".format(
|
|
@@ -1256,16 +1386,46 @@ class ArgoWorkflows(object):
|
|
|
1256
1386
|
)
|
|
1257
1387
|
|
|
1258
1388
|
# Add conditional if this is the first step in a conditional branch
|
|
1389
|
+
switch_in_funcs = [
|
|
1390
|
+
in_func
|
|
1391
|
+
for in_func in node.in_funcs
|
|
1392
|
+
if self.graph[in_func].type == "split-switch"
|
|
1393
|
+
]
|
|
1259
1394
|
if (
|
|
1260
1395
|
self._is_conditional_node(node)
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1396
|
+
or self._is_conditional_skip_node(node)
|
|
1397
|
+
or self._is_conditional_join_node(node)
|
|
1398
|
+
) and switch_in_funcs:
|
|
1399
|
+
conditional_when = "||".join(
|
|
1400
|
+
[
|
|
1401
|
+
"{{tasks.%s.outputs.parameters.switch-step}}==%s"
|
|
1402
|
+
% (self._sanitize(switch_in_func), node.name)
|
|
1403
|
+
for switch_in_func in switch_in_funcs
|
|
1404
|
+
]
|
|
1267
1405
|
)
|
|
1268
1406
|
|
|
1407
|
+
non_switch_in_funcs = [
|
|
1408
|
+
in_func
|
|
1409
|
+
for in_func in node.in_funcs
|
|
1410
|
+
if in_func not in switch_in_funcs
|
|
1411
|
+
]
|
|
1412
|
+
status_when = ""
|
|
1413
|
+
if non_switch_in_funcs:
|
|
1414
|
+
status_when = "||".join(
|
|
1415
|
+
[
|
|
1416
|
+
"{{tasks.%s.status}}==Succeeded"
|
|
1417
|
+
% self._sanitize(in_func)
|
|
1418
|
+
for in_func in non_switch_in_funcs
|
|
1419
|
+
]
|
|
1420
|
+
)
|
|
1421
|
+
|
|
1422
|
+
total_when = (
|
|
1423
|
+
f"({status_when}) || ({conditional_when})"
|
|
1424
|
+
if status_when
|
|
1425
|
+
else conditional_when
|
|
1426
|
+
)
|
|
1427
|
+
dag_task.when(total_when)
|
|
1428
|
+
|
|
1269
1429
|
dag_tasks.append(dag_task)
|
|
1270
1430
|
# End the workflow if we have reached the end of the flow
|
|
1271
1431
|
if node.type == "end":
|
|
@@ -1708,7 +1868,11 @@ class ArgoWorkflows(object):
|
|
|
1708
1868
|
input_paths_expr = (
|
|
1709
1869
|
"export INPUT_PATHS={{inputs.parameters.input-paths}}"
|
|
1710
1870
|
)
|
|
1711
|
-
if
|
|
1871
|
+
if (
|
|
1872
|
+
self._is_conditional_join_node(node)
|
|
1873
|
+
or self._many_in_funcs_all_conditional(node)
|
|
1874
|
+
or self._is_conditional_skip_node(node)
|
|
1875
|
+
):
|
|
1712
1876
|
# NOTE: Argo template expressions that fail to resolve, output the expression itself as a value.
|
|
1713
1877
|
# With conditional steps, some of the input-paths are therefore 'broken' due to containing a nil expression
|
|
1714
1878
|
# e.g. "{{ tasks['A'].outputs.parameters.task-id }}" when task A never executed.
|
|
@@ -1888,20 +2052,33 @@ class ArgoWorkflows(object):
|
|
|
1888
2052
|
)
|
|
1889
2053
|
input_paths = "%s/_parameters/%s" % (run_id, task_id_params)
|
|
1890
2054
|
# Only for static joins and conditional_joins
|
|
1891
|
-
elif
|
|
2055
|
+
elif (
|
|
2056
|
+
self._is_conditional_join_node(node)
|
|
2057
|
+
or self._many_in_funcs_all_conditional(node)
|
|
2058
|
+
or self._is_conditional_skip_node(node)
|
|
2059
|
+
) and not (
|
|
1892
2060
|
node.type == "join"
|
|
1893
2061
|
and self.graph[node.split_parents[-1]].type == "foreach"
|
|
1894
2062
|
):
|
|
2063
|
+
# 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,
|
|
2064
|
+
# non-conditional input-paths need to be ignored in favour of conditional ones when they have executed.
|
|
2065
|
+
skippable_input_steps = ",".join(
|
|
2066
|
+
[
|
|
2067
|
+
in_func
|
|
2068
|
+
for in_func in node.in_funcs
|
|
2069
|
+
if self.graph[in_func].type == "split-switch"
|
|
2070
|
+
]
|
|
2071
|
+
)
|
|
1895
2072
|
input_paths = (
|
|
1896
|
-
"$(python -m metaflow.plugins.argo.conditional_input_paths %s)"
|
|
1897
|
-
% input_paths
|
|
2073
|
+
"$(python -m metaflow.plugins.argo.conditional_input_paths %s %s)"
|
|
2074
|
+
% (input_paths, skippable_input_steps)
|
|
1898
2075
|
)
|
|
1899
2076
|
elif (
|
|
1900
2077
|
node.type == "join"
|
|
1901
2078
|
and self.graph[node.split_parents[-1]].type == "foreach"
|
|
1902
2079
|
):
|
|
1903
2080
|
# foreach-joins straight out of conditional branches are not yet supported
|
|
1904
|
-
if self._is_conditional_join_node(node):
|
|
2081
|
+
if self._is_conditional_join_node(node) and len(node.in_funcs) > 1:
|
|
1905
2082
|
raise ArgoWorkflowsException(
|
|
1906
2083
|
"Conditional steps inside a foreach that transition directly into a join step are not currently supported.\n"
|
|
1907
2084
|
"As a workaround, add a common step after the conditional steps %s "
|
|
@@ -3572,7 +3749,7 @@ class ArgoWorkflows(object):
|
|
|
3572
3749
|
# Sensor metadata.
|
|
3573
3750
|
ObjectMeta()
|
|
3574
3751
|
.name(ArgoWorkflows._sensor_name(self.name))
|
|
3575
|
-
.namespace(
|
|
3752
|
+
.namespace(ARGO_EVENTS_SENSOR_NAMESPACE)
|
|
3576
3753
|
.labels(self._base_labels)
|
|
3577
3754
|
.label("app.kubernetes.io/name", "metaflow-sensor")
|
|
3578
3755
|
.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)
|