ob-metaflow 2.13.4.1__tar.gz → 2.13.7.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.13.4.1/ob_metaflow.egg-info → ob_metaflow-2.13.7.1}/PKG-INFO +2 -2
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/decorators.py +6 -2
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/flowspec.py +30 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/parameters.py +1 -1
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/__init__.py +5 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/argo_workflows.py +24 -8
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/events_decorator.py +79 -142
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kubernetes.py +0 -9
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kubernetes_cli.py +1 -1
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kubernetes_decorator.py +8 -0
- ob_metaflow-2.13.7.1/metaflow/plugins/kubernetes/spot_metadata_cli.py +69 -0
- ob_metaflow-2.13.7.1/metaflow/plugins/kubernetes/spot_monitor_sidecar.py +109 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/click_api.py +2 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/user_configs/config_options.py +7 -4
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/user_configs/config_parameters.py +7 -7
- ob_metaflow-2.13.7.1/metaflow/version.py +1 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1/ob_metaflow.egg-info}/PKG-INFO +2 -2
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/ob_metaflow.egg-info/SOURCES.txt +2 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/ob_metaflow.egg-info/requires.txt +1 -1
- ob_metaflow-2.13.4.1/metaflow/version.py +0 -1
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/LICENSE +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/MANIFEST.in +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/R.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/_bashcomplete.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/_compat.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/_termui_impl.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/_textwrap.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/_unicodefun.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/_winconsole.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/core.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/decorators.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/exceptions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/formatting.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/globals.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/parser.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/termui.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/testing.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/types.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/click/utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/_adapters.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/_collections.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/_compat.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/_functools.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/_itertools.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/_meta.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/_text.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/importlib_metadata/py.typed +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/_elffile.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/_manylinux.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/_musllinux.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/_parser.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/_structures.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/_tokenizer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/markers.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/py.typed +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/requirements.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/specifiers.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/tags.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/packaging/version.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_checkers.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_config.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_decorators.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_exceptions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_functions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_importhook.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_memo.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_pytest_plugin.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_suppression.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_transformer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_union_transformer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typeguard/py.typed +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/typing_extensions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_5/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_5/zipp.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/_adapters.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/_collections.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/_compat.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/_functools.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/_itertools.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/_meta.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/_text.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/importlib_metadata/py.typed +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/typing_extensions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/v3_6/zipp.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/_vendor/zipp.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cards.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli_args.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli_components/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli_components/dump_cmd.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli_components/init_cmd.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli_components/run_cmds.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli_components/step_cmd.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cli_components/utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/client/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/client/core.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/client/filecache.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/clone_util.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/configure_cmd.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/develop/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/develop/stub_generator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/develop/stubs.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/main_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/tutorials_cmd.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd/util.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/cmd_with_io.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/content_addressed_store.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/datastore_set.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/datastore_storage.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/exceptions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/flow_datastore.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/inputs.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/datastore/task_datastore.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/debug.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/event_logger.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/events.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/exception.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/extension_support/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/extension_support/_empty_file.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/extension_support/cmd.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/extension_support/integrations.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/extension_support/plugins.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/graph.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/includefile.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/info_file.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/integrations.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/lint.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metadata_provider/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metadata_provider/heartbeat.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metadata_provider/metadata.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metadata_provider/util.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metaflow_config.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metaflow_config_funcs.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metaflow_current.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metaflow_environment.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metaflow_profile.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/metaflow_version.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/mflog/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/mflog/mflog.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/mflog/save_logs.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/mflog/save_logs_periodically.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/mflog/tee.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/monitor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/multicore_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/package.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/airflow.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/airflow_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/airflow_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/airflow_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/dag.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/exception.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/plumbing/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/plumbing/set_parameters.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/sensors/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/sensors/base_sensor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/sensors/external_task_sensor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/airflow/sensors/s3_sensor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/argo_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/argo_events.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/argo_workflows_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/argo_workflows_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/argo_workflows_deployer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/argo_workflows_deployer_objects.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/capture_error.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/generate_input_paths.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/argo/jobset_input_paths.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/aws_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/aws_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/batch/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/batch/batch.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/batch/batch_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/batch/batch_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/batch/batch_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/secrets_manager/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/event_bridge_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/production_token.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/schedule_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/set_batch_environment.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/step_functions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/step_functions_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/step_functions_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/step_functions_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/step_functions_deployer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/azure_credential.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/azure_exceptions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/azure_tail.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/azure_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/blob_service_client_factory.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/azure/includefile_support.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_creator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_datastore.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/base.html +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/basic.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/bundle.css +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/card.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/chevron/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/chevron/main.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/chevron/metadata.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/chevron/renderer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/chevron/tokenizer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/components.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/convert_to_native_type.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/main.js +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/renderer_tools.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_modules/test_cards.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_resolver.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_server.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/card_viewer/viewer.html +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/component_serializer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/cards/exception.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/catch_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datastores/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datastores/azure_storage.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datastores/gs_storage.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datastores/local_storage.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datastores/s3_storage.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datatools/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datatools/local.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datatools/s3/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datatools/s3/s3.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datatools/s3/s3op.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datatools/s3/s3tail.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/datatools/s3/s3util.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/debug_logger.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/debug_monitor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/client_modules.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/communication/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/communication/bytestream.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/communication/channel.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/communication/socket_bytestream.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/communication/utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/configurations/test_lib_impl/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/consts.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/data_transferer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/exception_transferer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/override_decorators.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/server.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/stub.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/env_escape/utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/environment_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/frameworks/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/frameworks/pytorch.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/gcp/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/gcp/gs_exceptions.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/gcp/gs_storage_client_factory.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/gcp/gs_tail.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/gcp/gs_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/gcp/includefile_support.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kube_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kubernetes_client.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kubernetes_job.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kubernetes_jobsets.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/logs_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/metadata_providers/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/metadata_providers/local.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/metadata_providers/service.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/package_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/parallel_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/project_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/bootstrap.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/conda_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/conda_environment.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/micromamba.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/pip.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/pypi_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/pypi_environment.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/pypi/utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/resources_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/retry_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/secrets/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/secrets/inline_secrets_provider.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/secrets/secrets_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/storage_executor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/tag_cli.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/test_unbounded_foreach_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/timeout_decorator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/procpoll.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/py.typed +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/pylint_wrapper.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/deployer.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/deployer_impl.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/metaflow_runner.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/nbdeploy.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/nbrun.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/subprocess_manager.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runner/utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/runtime.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/sidecar/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/sidecar/sidecar.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/sidecar/sidecar_messages.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/sidecar/sidecar_subprocess.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/sidecar/sidecar_worker.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/system/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/system/system_logger.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/system/system_monitor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/system/system_utils.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tagging_util.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/task.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tracing/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tracing/propagator.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tracing/span_exporter.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tracing/tracing_modules.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tuple_util.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/00-helloworld/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/00-helloworld/helloworld.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/01-playlist/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/01-playlist/movies.csv +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/01-playlist/playlist.ipynb +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/01-playlist/playlist.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/02-statistics/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/02-statistics/movies.csv +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/02-statistics/stats.ipynb +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/02-statistics/stats.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/03-playlist-redux/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/03-playlist-redux/playlist.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/04-playlist-plus/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/04-playlist-plus/playlist.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/05-hello-cloud/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/05-hello-cloud/hello-cloud.ipynb +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/05-hello-cloud/hello-cloud.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/06-statistics-redux/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/06-statistics-redux/stats.ipynb +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/07-worldview/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/07-worldview/worldview.ipynb +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/08-autopilot/README.md +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/tutorials/08-autopilot/autopilot.ipynb +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/unbounded_foreach.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/user_configs/__init__.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/user_configs/config_decorators.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/util.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/vendor.py +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/ob_metaflow.egg-info/dependency_links.txt +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/ob_metaflow.egg-info/entry_points.txt +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/ob_metaflow.egg-info/top_level.txt +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/setup.cfg +0 -0
- {ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: ob-metaflow
|
|
3
|
-
Version: 2.13.
|
|
3
|
+
Version: 2.13.7.1
|
|
4
4
|
Summary: Metaflow: More Data Science, Less Engineering
|
|
5
5
|
Author: Netflix, Outerbounds & the Metaflow Community
|
|
6
6
|
Author-email: help@outerbounds.co
|
|
@@ -12,7 +12,7 @@ Requires-Dist: boto3
|
|
|
12
12
|
Requires-Dist: pylint
|
|
13
13
|
Requires-Dist: kubernetes
|
|
14
14
|
Provides-Extra: stubs
|
|
15
|
-
Requires-Dist: metaflow-stubs==2.13.
|
|
15
|
+
Requires-Dist: metaflow-stubs==2.13.7.1; extra == "stubs"
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: author-email
|
|
18
18
|
Dynamic: description
|
|
@@ -591,9 +591,13 @@ def _init_flow_decorators(
|
|
|
591
591
|
)
|
|
592
592
|
else:
|
|
593
593
|
# Each "non-multiple" flow decorator is only allowed to have one set of options
|
|
594
|
+
# Note that there may be no deco_options if a MutableFlow config injected
|
|
595
|
+
# the decorator.
|
|
594
596
|
deco_flow_init_options = {
|
|
595
|
-
option: deco_options
|
|
596
|
-
|
|
597
|
+
option: deco_options.get(
|
|
598
|
+
option.replace("-", "_"), option_info["default"]
|
|
599
|
+
)
|
|
600
|
+
for option, option_info in deco.options.items()
|
|
597
601
|
}
|
|
598
602
|
for deco in decorators:
|
|
599
603
|
deco.flow_init(
|
|
@@ -86,6 +86,11 @@ class FlowSpecMeta(type):
|
|
|
86
86
|
super().__init__(name, bases, attrs)
|
|
87
87
|
if name == "FlowSpec":
|
|
88
88
|
return
|
|
89
|
+
|
|
90
|
+
from .decorators import (
|
|
91
|
+
DuplicateFlowDecoratorException,
|
|
92
|
+
) # Prevent circular import
|
|
93
|
+
|
|
89
94
|
# We store some state in the flow class itself. This is primarily used to
|
|
90
95
|
# attach global state to a flow. It is *not* an actual global because of
|
|
91
96
|
# Runner/NBRunner. This is also created here in the meta class to avoid it being
|
|
@@ -98,6 +103,31 @@ class FlowSpecMeta(type):
|
|
|
98
103
|
# Keys are _FlowState enum values
|
|
99
104
|
cls._flow_state = {}
|
|
100
105
|
|
|
106
|
+
# We inherit stuff from our parent classes as well -- we need to be careful
|
|
107
|
+
# in terms of the order; we will follow the MRO with the following rules:
|
|
108
|
+
# - decorators (cls._flow_decorators) will cause an error if they do not
|
|
109
|
+
# support multiple and we see multiple instances of the same
|
|
110
|
+
# - config decorators will be joined
|
|
111
|
+
# - configs will be added later directly by the class; base class configs will
|
|
112
|
+
# be taken into account as they would be inherited.
|
|
113
|
+
|
|
114
|
+
# We only need to do this for the base classes since the current class will
|
|
115
|
+
# get updated as decorators are parsed.
|
|
116
|
+
for base in cls.__mro__:
|
|
117
|
+
if base != cls and base != FlowSpec and issubclass(base, FlowSpec):
|
|
118
|
+
# Take care of decorators
|
|
119
|
+
for deco_name, deco in base._flow_decorators.items():
|
|
120
|
+
if deco_name in cls._flow_decorators and not deco.allow_multiple:
|
|
121
|
+
raise DuplicateFlowDecoratorException(deco_name)
|
|
122
|
+
cls._flow_decorators.setdefault(deco_name, []).extend(deco)
|
|
123
|
+
|
|
124
|
+
# Take care of configs and config decorators
|
|
125
|
+
base_configs = base._flow_state.get(_FlowState.CONFIG_DECORATORS)
|
|
126
|
+
if base_configs:
|
|
127
|
+
cls._flow_state.setdefault(_FlowState.CONFIG_DECORATORS, []).extend(
|
|
128
|
+
base_configs
|
|
129
|
+
)
|
|
130
|
+
|
|
101
131
|
cls._init_attrs()
|
|
102
132
|
|
|
103
133
|
def _init_attrs(cls):
|
|
@@ -316,7 +316,7 @@ class Parameter(object):
|
|
|
316
316
|
help : str, optional, default None
|
|
317
317
|
Help text to show in `run --help`.
|
|
318
318
|
required : bool, optional, default None
|
|
319
|
-
Require that the user
|
|
319
|
+
Require that the user specifies a value for the parameter. Note that if
|
|
320
320
|
a default is provide, the required flag is ignored.
|
|
321
321
|
A value of None is equivalent to False.
|
|
322
322
|
show_default : bool, optional, default None
|
|
@@ -16,6 +16,7 @@ CLIS_DESC = [
|
|
|
16
16
|
("argo-workflows", ".argo.argo_workflows_cli.cli"),
|
|
17
17
|
("card", ".cards.card_cli.cli"),
|
|
18
18
|
("tag", ".tag_cli.cli"),
|
|
19
|
+
("spot-metadata", ".kubernetes.spot_metadata_cli.cli"),
|
|
19
20
|
("logs", ".logs_cli.cli"),
|
|
20
21
|
]
|
|
21
22
|
|
|
@@ -104,6 +105,10 @@ SIDECARS_DESC = [
|
|
|
104
105
|
"save_logs_periodically",
|
|
105
106
|
"..mflog.save_logs_periodically.SaveLogsPeriodicallySidecar",
|
|
106
107
|
),
|
|
108
|
+
(
|
|
109
|
+
"spot_termination_monitor",
|
|
110
|
+
".kubernetes.spot_monitor_sidecar.SpotTerminationMonitorSidecar",
|
|
111
|
+
),
|
|
107
112
|
("heartbeat", "metaflow.metadata_provider.heartbeat.MetadataHeartBeat"),
|
|
108
113
|
]
|
|
109
114
|
|
|
@@ -625,6 +625,16 @@ class ArgoWorkflows(object):
|
|
|
625
625
|
for event in trigger_on_finish_deco.triggers:
|
|
626
626
|
# Actual filters are deduced here since we don't have access to
|
|
627
627
|
# the current object in the @trigger_on_finish decorator.
|
|
628
|
+
project_name = event.get("project") or current.get("project_name")
|
|
629
|
+
branch_name = event.get("branch") or current.get("branch_name")
|
|
630
|
+
# validate that we have complete project info for an event name
|
|
631
|
+
if project_name or branch_name:
|
|
632
|
+
if not (project_name and branch_name):
|
|
633
|
+
# if one of the two is missing, we would end up listening to an event that will never be broadcast.
|
|
634
|
+
raise ArgoWorkflowsException(
|
|
635
|
+
"Incomplete project info. Please specify both 'project' and 'project_branch' or use the @project decorator"
|
|
636
|
+
)
|
|
637
|
+
|
|
628
638
|
triggers.append(
|
|
629
639
|
{
|
|
630
640
|
# Make sure this remains consistent with the event name format
|
|
@@ -633,18 +643,16 @@ class ArgoWorkflows(object):
|
|
|
633
643
|
% ".".join(
|
|
634
644
|
v
|
|
635
645
|
for v in [
|
|
636
|
-
|
|
637
|
-
|
|
646
|
+
project_name,
|
|
647
|
+
branch_name,
|
|
638
648
|
event["flow"],
|
|
639
649
|
]
|
|
640
650
|
if v
|
|
641
651
|
),
|
|
642
652
|
"filters": {
|
|
643
653
|
"auto-generated-by-metaflow": True,
|
|
644
|
-
"project_name":
|
|
645
|
-
|
|
646
|
-
"branch_name": event.get("branch")
|
|
647
|
-
or current.get("branch_name"),
|
|
654
|
+
"project_name": project_name,
|
|
655
|
+
"branch_name": branch_name,
|
|
648
656
|
# TODO: Add a time filters to guard against cached events
|
|
649
657
|
},
|
|
650
658
|
"type": "run",
|
|
@@ -842,8 +850,15 @@ class ArgoWorkflows(object):
|
|
|
842
850
|
Metadata()
|
|
843
851
|
.labels(self._base_labels)
|
|
844
852
|
.label("app.kubernetes.io/name", "metaflow-task")
|
|
845
|
-
.annotations(
|
|
846
|
-
|
|
853
|
+
.annotations(
|
|
854
|
+
{
|
|
855
|
+
**annotations,
|
|
856
|
+
**self._base_annotations,
|
|
857
|
+
**{
|
|
858
|
+
"metaflow/run_id": "argo-{{workflow.name}}"
|
|
859
|
+
}, # we want pods of the workflow to have the run_id as an annotation as well
|
|
860
|
+
}
|
|
861
|
+
)
|
|
847
862
|
)
|
|
848
863
|
# Set the entrypoint to flow name
|
|
849
864
|
.entrypoint(self.flow.name)
|
|
@@ -1706,6 +1721,7 @@ class ArgoWorkflows(object):
|
|
|
1706
1721
|
},
|
|
1707
1722
|
**{
|
|
1708
1723
|
# Some optional values for bookkeeping
|
|
1724
|
+
"METAFLOW_FLOW_FILENAME": os.path.basename(sys.argv[0]),
|
|
1709
1725
|
"METAFLOW_FLOW_NAME": self.flow.name,
|
|
1710
1726
|
"METAFLOW_STEP_NAME": node.name,
|
|
1711
1727
|
"METAFLOW_RUN_ID": run_id,
|
|
@@ -398,111 +398,23 @@ class TriggerOnFinishDecorator(FlowDecorator):
|
|
|
398
398
|
)
|
|
399
399
|
elif self.attributes["flow"]:
|
|
400
400
|
# flow supports the format @trigger_on_finish(flow='FooFlow')
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
{
|
|
404
|
-
"fq_name": self.attributes["flow"],
|
|
405
|
-
}
|
|
406
|
-
)
|
|
407
|
-
elif isinstance(self.attributes["flow"], dict):
|
|
408
|
-
if "name" not in self.attributes["flow"]:
|
|
409
|
-
raise MetaflowException(
|
|
410
|
-
"The *flow* attribute for *@trigger_on_finish* is missing the "
|
|
411
|
-
"*name* key."
|
|
412
|
-
)
|
|
413
|
-
flow_name = self.attributes["flow"]["name"]
|
|
414
|
-
|
|
415
|
-
if not is_stringish(flow_name) or "." in flow_name:
|
|
416
|
-
raise MetaflowException(
|
|
417
|
-
"The *name* attribute of the *flow* is not a valid string"
|
|
418
|
-
)
|
|
419
|
-
result = {"fq_name": flow_name}
|
|
420
|
-
if "project" in self.attributes["flow"]:
|
|
421
|
-
if is_stringish(self.attributes["flow"]["project"]):
|
|
422
|
-
result["project"] = self.attributes["flow"]["project"]
|
|
423
|
-
else:
|
|
424
|
-
raise MetaflowException(
|
|
425
|
-
"The *project* attribute of the *flow* is not a string"
|
|
426
|
-
)
|
|
427
|
-
if "project_branch" in self.attributes["flow"]:
|
|
428
|
-
if is_stringish(self.attributes["flow"]["project_branch"]):
|
|
429
|
-
result["branch"] = self.attributes["flow"]["project_branch"]
|
|
430
|
-
else:
|
|
431
|
-
raise MetaflowException(
|
|
432
|
-
"The *project_branch* attribute of the *flow* is not a string"
|
|
433
|
-
)
|
|
434
|
-
self.triggers.append(result)
|
|
435
|
-
elif callable(self.attributes["flow"]) and not isinstance(
|
|
401
|
+
flow = self.attributes["flow"]
|
|
402
|
+
if callable(flow) and not isinstance(
|
|
436
403
|
self.attributes["flow"], DeployTimeField
|
|
437
404
|
):
|
|
438
|
-
trig = DeployTimeField(
|
|
439
|
-
"fq_name", [str, dict], None, self.attributes["flow"], False
|
|
440
|
-
)
|
|
405
|
+
trig = DeployTimeField("fq_name", [str, dict], None, flow, False)
|
|
441
406
|
self.triggers.append(trig)
|
|
442
407
|
else:
|
|
443
|
-
|
|
444
|
-
"Incorrect type for *flow* attribute in *@trigger_on_finish* "
|
|
445
|
-
" decorator. Supported type is string or Dict[str, str] - \n"
|
|
446
|
-
"@trigger_on_finish(flow='FooFlow') or "
|
|
447
|
-
"@trigger_on_finish(flow={'name':'FooFlow', 'project_branch': 'branch'})"
|
|
448
|
-
)
|
|
408
|
+
self.triggers.extend(self._parse_static_triggers([flow]))
|
|
449
409
|
elif self.attributes["flows"]:
|
|
450
410
|
# flows attribute supports the following formats -
|
|
451
411
|
# 1. flows=['FooFlow', 'BarFlow']
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
self.triggers.append(
|
|
456
|
-
{
|
|
457
|
-
"fq_name": flow,
|
|
458
|
-
}
|
|
459
|
-
)
|
|
460
|
-
elif isinstance(flow, dict):
|
|
461
|
-
if "name" not in flow:
|
|
462
|
-
raise MetaflowException(
|
|
463
|
-
"One or more flows in the *flows* attribute for "
|
|
464
|
-
"*@trigger_on_finish* is missing the "
|
|
465
|
-
"*name* key."
|
|
466
|
-
)
|
|
467
|
-
flow_name = flow["name"]
|
|
468
|
-
|
|
469
|
-
if not is_stringish(flow_name) or "." in flow_name:
|
|
470
|
-
raise MetaflowException(
|
|
471
|
-
"The *name* attribute '%s' is not a valid string"
|
|
472
|
-
% str(flow_name)
|
|
473
|
-
)
|
|
474
|
-
result = {"fq_name": flow_name}
|
|
475
|
-
if "project" in flow:
|
|
476
|
-
if is_stringish(flow["project"]):
|
|
477
|
-
result["project"] = flow["project"]
|
|
478
|
-
else:
|
|
479
|
-
raise MetaflowException(
|
|
480
|
-
"The *project* attribute of the *flow* '%s' is not "
|
|
481
|
-
"a string" % flow_name
|
|
482
|
-
)
|
|
483
|
-
if "project_branch" in flow:
|
|
484
|
-
if is_stringish(flow["project_branch"]):
|
|
485
|
-
result["branch"] = flow["project_branch"]
|
|
486
|
-
else:
|
|
487
|
-
raise MetaflowException(
|
|
488
|
-
"The *project_branch* attribute of the *flow* %s "
|
|
489
|
-
"is not a string" % flow_name
|
|
490
|
-
)
|
|
491
|
-
self.triggers.append(result)
|
|
492
|
-
else:
|
|
493
|
-
raise MetaflowException(
|
|
494
|
-
"One or more flows in *flows* attribute in "
|
|
495
|
-
"*@trigger_on_finish* decorator have an incorrect type. "
|
|
496
|
-
"Supported type is string or Dict[str, str]- \n"
|
|
497
|
-
"@trigger_on_finish(flows=['FooFlow', 'BarFlow']"
|
|
498
|
-
)
|
|
499
|
-
elif callable(self.attributes["flows"]) and not isinstance(
|
|
500
|
-
self.attributes["flows"], DeployTimeField
|
|
501
|
-
):
|
|
502
|
-
trig = DeployTimeField(
|
|
503
|
-
"flows", list, None, self.attributes["flows"], False
|
|
504
|
-
)
|
|
412
|
+
flows = self.attributes["flows"]
|
|
413
|
+
if callable(flows) and not isinstance(flows, DeployTimeField):
|
|
414
|
+
trig = DeployTimeField("flows", list, None, flows, False)
|
|
505
415
|
self.triggers.append(trig)
|
|
416
|
+
elif isinstance(flows, list):
|
|
417
|
+
self.triggers.extend(self._parse_static_triggers(flows))
|
|
506
418
|
else:
|
|
507
419
|
raise MetaflowException(
|
|
508
420
|
"Incorrect type for *flows* attribute in *@trigger_on_finish* "
|
|
@@ -519,26 +431,7 @@ class TriggerOnFinishDecorator(FlowDecorator):
|
|
|
519
431
|
for trigger in self.triggers:
|
|
520
432
|
if isinstance(trigger, DeployTimeField):
|
|
521
433
|
continue
|
|
522
|
-
|
|
523
|
-
# fully qualified name is just the flow name
|
|
524
|
-
trigger["flow"] = trigger["fq_name"]
|
|
525
|
-
elif trigger["fq_name"].count(".") >= 2:
|
|
526
|
-
# fully qualified name is of the format - project.branch.flow_name
|
|
527
|
-
trigger["project"], tail = trigger["fq_name"].split(".", maxsplit=1)
|
|
528
|
-
trigger["branch"], trigger["flow"] = tail.rsplit(".", maxsplit=1)
|
|
529
|
-
else:
|
|
530
|
-
raise MetaflowException(
|
|
531
|
-
"Incorrect format for *flow* in *@trigger_on_finish* "
|
|
532
|
-
"decorator. Specify either just the *flow_name* or a fully "
|
|
533
|
-
"qualified name like *project_name.branch_name.flow_name*."
|
|
534
|
-
)
|
|
535
|
-
# TODO: Also sanity check project and branch names
|
|
536
|
-
if not re.match(r"^[A-Za-z0-9_]+$", trigger["flow"]):
|
|
537
|
-
raise MetaflowException(
|
|
538
|
-
"Invalid flow name *%s* in *@trigger_on_finish* "
|
|
539
|
-
"decorator. Only alphanumeric characters and "
|
|
540
|
-
"underscores(_) are allowed." % trigger["flow"]
|
|
541
|
-
)
|
|
434
|
+
self._parse_fq_name(trigger)
|
|
542
435
|
|
|
543
436
|
self.options = self.attributes["options"]
|
|
544
437
|
|
|
@@ -593,9 +486,67 @@ class TriggerOnFinishDecorator(FlowDecorator):
|
|
|
593
486
|
run_objs.append(run_obj)
|
|
594
487
|
current._update_env({"trigger": Trigger.from_runs(run_objs)})
|
|
595
488
|
|
|
489
|
+
@staticmethod
|
|
490
|
+
def _parse_static_triggers(flows):
|
|
491
|
+
results = []
|
|
492
|
+
for flow in flows:
|
|
493
|
+
if is_stringish(flow):
|
|
494
|
+
results.append(
|
|
495
|
+
{
|
|
496
|
+
"fq_name": flow,
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
elif isinstance(flow, dict):
|
|
500
|
+
if "name" not in flow:
|
|
501
|
+
if len(flows) > 1:
|
|
502
|
+
raise MetaflowException(
|
|
503
|
+
"One or more flows in the *flows* attribute for "
|
|
504
|
+
"*@trigger_on_finish* is missing the "
|
|
505
|
+
"*name* key."
|
|
506
|
+
)
|
|
507
|
+
raise MetaflowException(
|
|
508
|
+
"The *flow* attribute for *@trigger_on_finish* is missing the "
|
|
509
|
+
"*name* key."
|
|
510
|
+
)
|
|
511
|
+
flow_name = flow["name"]
|
|
512
|
+
|
|
513
|
+
if not is_stringish(flow_name) or "." in flow_name:
|
|
514
|
+
raise MetaflowException(
|
|
515
|
+
f"The *name* attribute of the *flow* {flow_name} is not a valid string"
|
|
516
|
+
)
|
|
517
|
+
result = {"fq_name": flow_name}
|
|
518
|
+
if "project" in flow:
|
|
519
|
+
if is_stringish(flow["project"]):
|
|
520
|
+
result["project"] = flow["project"]
|
|
521
|
+
else:
|
|
522
|
+
raise MetaflowException(
|
|
523
|
+
f"The *project* attribute of the *flow* {flow_name} is not a string"
|
|
524
|
+
)
|
|
525
|
+
if "project_branch" in flow:
|
|
526
|
+
if is_stringish(flow["project_branch"]):
|
|
527
|
+
result["branch"] = flow["project_branch"]
|
|
528
|
+
else:
|
|
529
|
+
raise MetaflowException(
|
|
530
|
+
f"The *project_branch* attribute of the *flow* {flow_name} is not a string"
|
|
531
|
+
)
|
|
532
|
+
results.append(result)
|
|
533
|
+
else:
|
|
534
|
+
if len(flows) > 1:
|
|
535
|
+
raise MetaflowException(
|
|
536
|
+
"One or more flows in the *flows* attribute for "
|
|
537
|
+
"*@trigger_on_finish* decorator have an incorrect type. "
|
|
538
|
+
"Supported type is string or Dict[str, str]- \n"
|
|
539
|
+
"@trigger_on_finish(flows=['FooFlow', 'BarFlow']"
|
|
540
|
+
)
|
|
541
|
+
raise MetaflowException(
|
|
542
|
+
"Incorrect type for *flow* attribute in *@trigger_on_finish* "
|
|
543
|
+
" decorator. Supported type is string or Dict[str, str] - \n"
|
|
544
|
+
"@trigger_on_finish(flow='FooFlow') or "
|
|
545
|
+
"@trigger_on_finish(flow={'name':'FooFlow', 'project_branch': 'branch'})"
|
|
546
|
+
)
|
|
547
|
+
return results
|
|
548
|
+
|
|
596
549
|
def _parse_fq_name(self, trigger):
|
|
597
|
-
if isinstance(trigger, DeployTimeField):
|
|
598
|
-
trigger["fq_name"] = deploy_time_eval(trigger["fq_name"])
|
|
599
550
|
if trigger["fq_name"].count(".") == 0:
|
|
600
551
|
# fully qualified name is just the flow name
|
|
601
552
|
trigger["flow"] = trigger["fq_name"]
|
|
@@ -615,32 +566,18 @@ class TriggerOnFinishDecorator(FlowDecorator):
|
|
|
615
566
|
"decorator. Only alphanumeric characters and "
|
|
616
567
|
"underscores(_) are allowed." % trigger["flow"]
|
|
617
568
|
)
|
|
618
|
-
return trigger
|
|
619
569
|
|
|
620
570
|
def format_deploytime_value(self):
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
deploy_value = deploy_time_eval(trigger)
|
|
626
|
-
if isinstance(deploy_value, list):
|
|
627
|
-
self.triggers = deploy_value
|
|
571
|
+
if len(self.triggers) == 1 and isinstance(self.triggers[0], DeployTimeField):
|
|
572
|
+
deploy_value = deploy_time_eval(self.triggers[0])
|
|
573
|
+
if isinstance(deploy_value, list):
|
|
574
|
+
self.triggers = deploy_value
|
|
628
575
|
else:
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
trigger = deploy_time_eval(trigger)
|
|
635
|
-
if isinstance(trigger, dict):
|
|
636
|
-
trigger["fq_name"] = trigger.get("name")
|
|
637
|
-
trigger["project"] = trigger.get("project")
|
|
638
|
-
trigger["branch"] = trigger.get("project_branch")
|
|
639
|
-
# We also added this bc it won't be formatted yet
|
|
640
|
-
if isinstance(trigger, str):
|
|
641
|
-
trigger = {"fq_name": trigger}
|
|
642
|
-
trigger = self._parse_fq_name(trigger)
|
|
643
|
-
self.triggers[self.triggers.index(old_trig)] = trigger
|
|
576
|
+
self.triggers = [deploy_value]
|
|
577
|
+
triggers = self._parse_static_triggers(self.triggers)
|
|
578
|
+
for trigger in triggers:
|
|
579
|
+
self._parse_fq_name(trigger)
|
|
580
|
+
self.triggers = triggers
|
|
644
581
|
|
|
645
582
|
def get_top_level_options(self):
|
|
646
583
|
return list(self._option_values.items())
|
|
@@ -685,15 +685,6 @@ class Kubernetes(object):
|
|
|
685
685
|
for name, value in system_annotations.items():
|
|
686
686
|
job.annotation(name, value)
|
|
687
687
|
|
|
688
|
-
(
|
|
689
|
-
job.annotation("metaflow/run_id", run_id)
|
|
690
|
-
.annotation("metaflow/step_name", step_name)
|
|
691
|
-
.annotation("metaflow/task_id", task_id)
|
|
692
|
-
.annotation("metaflow/attempt", attempt)
|
|
693
|
-
.label("app.kubernetes.io/name", "metaflow-task")
|
|
694
|
-
.label("app.kubernetes.io/part-of", "metaflow")
|
|
695
|
-
)
|
|
696
|
-
|
|
697
688
|
return job
|
|
698
689
|
|
|
699
690
|
def create_k8sjob(self, job):
|
|
@@ -190,7 +190,7 @@ def step(
|
|
|
190
190
|
executable = ctx.obj.environment.executable(step_name, executable)
|
|
191
191
|
|
|
192
192
|
# Set environment
|
|
193
|
-
env = {}
|
|
193
|
+
env = {"METAFLOW_FLOW_FILENAME": os.path.basename(sys.argv[0])}
|
|
194
194
|
env_deco = [deco for deco in node.decorators if deco.name == "environment"]
|
|
195
195
|
if env_deco:
|
|
196
196
|
env = env_deco[0].attributes["vars"]
|
{ob_metaflow-2.13.4.1 → ob_metaflow-2.13.7.1}/metaflow/plugins/kubernetes/kubernetes_decorator.py
RENAMED
|
@@ -562,6 +562,13 @@ class KubernetesDecorator(StepDecorator):
|
|
|
562
562
|
self._save_logs_sidecar = Sidecar("save_logs_periodically")
|
|
563
563
|
self._save_logs_sidecar.start()
|
|
564
564
|
|
|
565
|
+
# Start spot termination monitor sidecar.
|
|
566
|
+
current._update_env(
|
|
567
|
+
{"spot_termination_notice": "/tmp/spot_termination_notice"}
|
|
568
|
+
)
|
|
569
|
+
self._spot_monitor_sidecar = Sidecar("spot_termination_monitor")
|
|
570
|
+
self._spot_monitor_sidecar.start()
|
|
571
|
+
|
|
565
572
|
num_parallel = None
|
|
566
573
|
if hasattr(flow, "_parallel_ubf_iter"):
|
|
567
574
|
num_parallel = flow._parallel_ubf_iter.num_parallel
|
|
@@ -620,6 +627,7 @@ class KubernetesDecorator(StepDecorator):
|
|
|
620
627
|
|
|
621
628
|
try:
|
|
622
629
|
self._save_logs_sidecar.terminate()
|
|
630
|
+
self._spot_monitor_sidecar.terminate()
|
|
623
631
|
except:
|
|
624
632
|
# Best effort kill
|
|
625
633
|
pass
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from metaflow._vendor import click
|
|
2
|
+
from datetime import datetime, timezone
|
|
3
|
+
from metaflow.tagging_util import validate_tags
|
|
4
|
+
from metaflow.metadata_provider import MetaDatum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@click.group()
|
|
8
|
+
def cli():
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@cli.group(help="Commands related to spot metadata.")
|
|
13
|
+
def spot_metadata():
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@spot_metadata.command(help="Record spot termination metadata for a task.")
|
|
18
|
+
@click.option(
|
|
19
|
+
"--run-id",
|
|
20
|
+
required=True,
|
|
21
|
+
help="Run ID for which metadata is to be recorded.",
|
|
22
|
+
)
|
|
23
|
+
@click.option(
|
|
24
|
+
"--step-name",
|
|
25
|
+
required=True,
|
|
26
|
+
help="Step Name for which metadata is to be recorded.",
|
|
27
|
+
)
|
|
28
|
+
@click.option(
|
|
29
|
+
"--task-id",
|
|
30
|
+
required=True,
|
|
31
|
+
help="Task ID for which metadata is to be recorded.",
|
|
32
|
+
)
|
|
33
|
+
@click.option(
|
|
34
|
+
"--termination-notice-time",
|
|
35
|
+
required=True,
|
|
36
|
+
help="Spot termination notice time.",
|
|
37
|
+
)
|
|
38
|
+
@click.option(
|
|
39
|
+
"--tag",
|
|
40
|
+
"tags",
|
|
41
|
+
multiple=True,
|
|
42
|
+
required=False,
|
|
43
|
+
default=None,
|
|
44
|
+
help="List of tags.",
|
|
45
|
+
)
|
|
46
|
+
@click.pass_obj
|
|
47
|
+
def record(obj, run_id, step_name, task_id, termination_notice_time, tags=None):
|
|
48
|
+
validate_tags(tags)
|
|
49
|
+
|
|
50
|
+
tag_list = list(tags) if tags else []
|
|
51
|
+
|
|
52
|
+
entries = [
|
|
53
|
+
MetaDatum(
|
|
54
|
+
field="spot-termination-received-at",
|
|
55
|
+
value=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
56
|
+
type="spot-termination-received-at",
|
|
57
|
+
tags=tag_list,
|
|
58
|
+
),
|
|
59
|
+
MetaDatum(
|
|
60
|
+
field="spot-termination-time",
|
|
61
|
+
value=termination_notice_time,
|
|
62
|
+
type="spot-termination-time",
|
|
63
|
+
tags=tag_list,
|
|
64
|
+
),
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
obj.metadata.register_metadata(
|
|
68
|
+
run_id=run_id, step_name=step_name, task_id=task_id, metadata=entries
|
|
69
|
+
)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import time
|
|
4
|
+
import signal
|
|
5
|
+
import requests
|
|
6
|
+
import subprocess
|
|
7
|
+
from multiprocessing import Process
|
|
8
|
+
from datetime import datetime, timezone
|
|
9
|
+
from metaflow.sidecar import MessageTypes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SpotTerminationMonitorSidecar(object):
|
|
13
|
+
EC2_TYPE_URL = "http://169.254.169.254/latest/meta-data/instance-life-cycle"
|
|
14
|
+
METADATA_URL = "http://169.254.169.254/latest/meta-data/spot/termination-time"
|
|
15
|
+
TOKEN_URL = "http://169.254.169.254/latest/api/token"
|
|
16
|
+
POLL_INTERVAL = 5 # seconds
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
self.is_alive = True
|
|
20
|
+
self._process = None
|
|
21
|
+
self._token = None
|
|
22
|
+
self._token_expiry = 0
|
|
23
|
+
|
|
24
|
+
if self._is_aws_spot_instance():
|
|
25
|
+
self._process = Process(target=self._monitor_loop)
|
|
26
|
+
self._process.start()
|
|
27
|
+
|
|
28
|
+
def process_message(self, msg):
|
|
29
|
+
if msg.msg_type == MessageTypes.SHUTDOWN:
|
|
30
|
+
self.is_alive = False
|
|
31
|
+
if self._process:
|
|
32
|
+
self._process.terminate()
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def get_worker(cls):
|
|
36
|
+
return cls
|
|
37
|
+
|
|
38
|
+
def _get_imds_token(self):
|
|
39
|
+
current_time = time.time()
|
|
40
|
+
if current_time >= self._token_expiry - 60: # Refresh 60s before expiry
|
|
41
|
+
try:
|
|
42
|
+
response = requests.put(
|
|
43
|
+
url=self.TOKEN_URL,
|
|
44
|
+
headers={"X-aws-ec2-metadata-token-ttl-seconds": "300"},
|
|
45
|
+
timeout=1,
|
|
46
|
+
)
|
|
47
|
+
if response.status_code == 200:
|
|
48
|
+
self._token = response.text
|
|
49
|
+
self._token_expiry = current_time + 240 # Slightly less than TTL
|
|
50
|
+
except requests.exceptions.RequestException:
|
|
51
|
+
pass
|
|
52
|
+
return self._token
|
|
53
|
+
|
|
54
|
+
def _make_ec2_request(self, url, timeout):
|
|
55
|
+
token = self._get_imds_token()
|
|
56
|
+
headers = {"X-aws-ec2-metadata-token": token} if token else {}
|
|
57
|
+
response = requests.get(url=url, headers=headers, timeout=timeout)
|
|
58
|
+
return response
|
|
59
|
+
|
|
60
|
+
def _is_aws_spot_instance(self):
|
|
61
|
+
try:
|
|
62
|
+
response = self._make_ec2_request(url=self.EC2_TYPE_URL, timeout=1)
|
|
63
|
+
return response.status_code == 200 and response.text == "spot"
|
|
64
|
+
except (requests.exceptions.RequestException, requests.exceptions.Timeout):
|
|
65
|
+
return False
|
|
66
|
+
|
|
67
|
+
def _monitor_loop(self):
|
|
68
|
+
while self.is_alive:
|
|
69
|
+
try:
|
|
70
|
+
response = self._make_ec2_request(url=self.METADATA_URL, timeout=1)
|
|
71
|
+
if response.status_code == 200:
|
|
72
|
+
termination_time = response.text
|
|
73
|
+
self._emit_termination_metadata(termination_time)
|
|
74
|
+
os.kill(os.getppid(), signal.SIGTERM)
|
|
75
|
+
break
|
|
76
|
+
except (requests.exceptions.RequestException, requests.exceptions.Timeout):
|
|
77
|
+
pass
|
|
78
|
+
time.sleep(self.POLL_INTERVAL)
|
|
79
|
+
|
|
80
|
+
def _emit_termination_metadata(self, termination_time):
|
|
81
|
+
flow_filename = os.getenv("METAFLOW_FLOW_FILENAME")
|
|
82
|
+
pathspec = os.getenv("MF_PATHSPEC")
|
|
83
|
+
_, run_id, step_name, task_id = pathspec.split("/")
|
|
84
|
+
retry_count = os.getenv("MF_ATTEMPT")
|
|
85
|
+
|
|
86
|
+
with open("/tmp/spot_termination_notice", "w") as fp:
|
|
87
|
+
fp.write(termination_time)
|
|
88
|
+
|
|
89
|
+
command = [
|
|
90
|
+
sys.executable,
|
|
91
|
+
f"/metaflow/{flow_filename}",
|
|
92
|
+
"spot-metadata",
|
|
93
|
+
"record",
|
|
94
|
+
"--run-id",
|
|
95
|
+
run_id,
|
|
96
|
+
"--step-name",
|
|
97
|
+
step_name,
|
|
98
|
+
"--task-id",
|
|
99
|
+
task_id,
|
|
100
|
+
"--termination-notice-time",
|
|
101
|
+
termination_time,
|
|
102
|
+
"--tag",
|
|
103
|
+
"attempt_id:{}".format(retry_count),
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
result = subprocess.run(command, capture_output=True, text=True)
|
|
107
|
+
|
|
108
|
+
if result.returncode != 0:
|
|
109
|
+
print(f"Failed to record spot termination metadata: {result.stderr}")
|