metaflow 2.13.3__tar.gz → 2.13.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {metaflow-2.13.3/metaflow.egg-info → metaflow-2.13.5}/PKG-INFO +2 -2
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli.py +5 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli_components/run_cmds.py +2 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli_components/step_cmd.py +0 -13
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/decorators.py +2 -2
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/parameters.py +3 -1
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/__init__.py +5 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/argo_workflows.py +1 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_decorator.py +53 -20
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/events_decorator.py +41 -7
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/kubernetes_cli.py +1 -1
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/kubernetes_decorator.py +8 -0
- metaflow-2.13.5/metaflow/plugins/kubernetes/spot_metadata_cli.py +69 -0
- metaflow-2.13.5/metaflow/plugins/kubernetes/spot_monitor_sidecar.py +109 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/project_decorator.py +33 -5
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/user_configs/config_parameters.py +23 -9
- metaflow-2.13.5/metaflow/version.py +1 -0
- {metaflow-2.13.3 → metaflow-2.13.5/metaflow.egg-info}/PKG-INFO +2 -2
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow.egg-info/SOURCES.txt +2 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow.egg-info/requires.txt +1 -1
- metaflow-2.13.3/metaflow/version.py +0 -1
- {metaflow-2.13.3 → metaflow-2.13.5}/LICENSE +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/MANIFEST.in +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/R.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/_bashcomplete.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/_compat.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/_termui_impl.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/_textwrap.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/_unicodefun.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/_winconsole.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/core.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/decorators.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/exceptions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/formatting.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/globals.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/parser.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/termui.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/testing.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/types.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/click/utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/_adapters.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/_collections.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/_compat.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/_functools.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/_itertools.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/_meta.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/_text.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/importlib_metadata/py.typed +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/_elffile.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/_manylinux.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/_musllinux.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/_parser.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/_structures.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/_tokenizer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/markers.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/py.typed +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/requirements.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/specifiers.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/tags.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/packaging/version.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_checkers.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_config.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_decorators.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_exceptions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_functions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_importhook.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_memo.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_pytest_plugin.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_suppression.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_transformer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_union_transformer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typeguard/py.typed +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/typing_extensions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_5/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_5/zipp.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/_adapters.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/_collections.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/_compat.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/_functools.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/_itertools.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/_meta.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/_text.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/importlib_metadata/py.typed +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/typing_extensions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/v3_6/zipp.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/_vendor/zipp.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cards.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli_args.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli_components/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli_components/dump_cmd.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli_components/init_cmd.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cli_components/utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/client/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/client/core.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/client/filecache.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/clone_util.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/configure_cmd.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/develop/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/develop/stub_generator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/develop/stubs.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/main_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/tutorials_cmd.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd/util.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/cmd_with_io.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/content_addressed_store.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/datastore_set.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/datastore_storage.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/exceptions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/flow_datastore.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/inputs.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/datastore/task_datastore.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/debug.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/event_logger.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/events.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/exception.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/extension_support/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/extension_support/_empty_file.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/extension_support/cmd.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/extension_support/integrations.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/extension_support/plugins.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/flowspec.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/graph.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/includefile.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/info_file.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/integrations.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/lint.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metadata_provider/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metadata_provider/heartbeat.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metadata_provider/metadata.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metadata_provider/util.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metaflow_config.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metaflow_config_funcs.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metaflow_current.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metaflow_environment.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metaflow_profile.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/metaflow_version.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/mflog/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/mflog/mflog.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/mflog/save_logs.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/mflog/save_logs_periodically.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/mflog/tee.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/monitor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/multicore_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/package.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/airflow.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/airflow_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/airflow_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/airflow_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/dag.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/exception.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/plumbing/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/plumbing/set_parameters.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/sensors/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/sensors/base_sensor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/sensors/external_task_sensor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/airflow/sensors/s3_sensor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/argo_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/argo_events.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/argo_workflows_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/argo_workflows_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/argo_workflows_deployer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/argo_workflows_deployer_objects.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/capture_error.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/generate_input_paths.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/argo/jobset_input_paths.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/aws_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/aws_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/batch/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/batch/batch.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/batch/batch_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/batch/batch_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/batch/batch_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/secrets_manager/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/event_bridge_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/production_token.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/schedule_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/set_batch_environment.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/step_functions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/step_functions_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/step_functions_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/step_functions_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/step_functions_deployer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/azure_credential.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/azure_exceptions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/azure_tail.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/azure_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/blob_service_client_factory.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/azure/includefile_support.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_creator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_datastore.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/base.html +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/basic.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/bundle.css +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/card.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/chevron/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/chevron/main.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/chevron/metadata.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/chevron/renderer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/chevron/tokenizer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/components.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/convert_to_native_type.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/main.js +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/renderer_tools.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_modules/test_cards.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_resolver.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_server.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/card_viewer/viewer.html +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/component_serializer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/cards/exception.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/catch_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datastores/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datastores/azure_storage.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datastores/gs_storage.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datastores/local_storage.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datastores/s3_storage.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datatools/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datatools/local.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datatools/s3/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datatools/s3/s3.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datatools/s3/s3op.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datatools/s3/s3tail.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/datatools/s3/s3util.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/debug_logger.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/debug_monitor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/client_modules.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/communication/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/communication/bytestream.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/communication/channel.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/communication/socket_bytestream.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/communication/utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/configurations/emulate_test_lib/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/configurations/emulate_test_lib/overrides.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/configurations/emulate_test_lib/server_mappings.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/configurations/test_lib_impl/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/configurations/test_lib_impl/test_lib.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/consts.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/data_transferer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/exception_transferer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/override_decorators.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/server.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/stub.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/env_escape/utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/environment_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/frameworks/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/frameworks/pytorch.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/gcp/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/gcp/gs_exceptions.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/gcp/gs_storage_client_factory.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/gcp/gs_tail.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/gcp/gs_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/gcp/includefile_support.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/kube_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/kubernetes.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/kubernetes_client.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/kubernetes_job.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/kubernetes/kubernetes_jobsets.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/logs_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/metadata_providers/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/metadata_providers/local.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/metadata_providers/service.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/package_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/parallel_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/bootstrap.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/conda_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/conda_environment.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/micromamba.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/pip.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/pypi_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/pypi_environment.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/pypi/utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/resources_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/retry_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/secrets/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/secrets/inline_secrets_provider.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/secrets/secrets_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/storage_executor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/tag_cli.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/test_unbounded_foreach_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/plugins/timeout_decorator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/procpoll.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/py.typed +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/pylint_wrapper.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/click_api.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/deployer.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/deployer_impl.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/metaflow_runner.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/nbdeploy.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/nbrun.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/subprocess_manager.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runner/utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/runtime.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/sidecar/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/sidecar/sidecar.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/sidecar/sidecar_messages.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/sidecar/sidecar_subprocess.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/sidecar/sidecar_worker.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/system/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/system/system_logger.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/system/system_monitor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/system/system_utils.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tagging_util.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/task.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tracing/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tracing/propagator.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tracing/span_exporter.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tracing/tracing_modules.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tuple_util.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/00-helloworld/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/00-helloworld/helloworld.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/01-playlist/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/01-playlist/movies.csv +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/01-playlist/playlist.ipynb +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/01-playlist/playlist.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/02-statistics/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/02-statistics/movies.csv +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/02-statistics/stats.ipynb +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/02-statistics/stats.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/03-playlist-redux/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/03-playlist-redux/playlist.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/04-playlist-plus/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/04-playlist-plus/playlist.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/05-hello-cloud/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/05-hello-cloud/hello-cloud.ipynb +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/05-hello-cloud/hello-cloud.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/06-statistics-redux/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/06-statistics-redux/stats.ipynb +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/07-worldview/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/07-worldview/worldview.ipynb +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/08-autopilot/README.md +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/tutorials/08-autopilot/autopilot.ipynb +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/unbounded_foreach.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/user_configs/__init__.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/user_configs/config_decorators.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/user_configs/config_options.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/util.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow/vendor.py +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow.egg-info/dependency_links.txt +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow.egg-info/entry_points.txt +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/metaflow.egg-info/top_level.txt +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/setup.cfg +0 -0
- {metaflow-2.13.3 → metaflow-2.13.5}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: metaflow
|
3
|
-
Version: 2.13.
|
3
|
+
Version: 2.13.5
|
4
4
|
Summary: Metaflow: More Data Science, Less Engineering
|
5
5
|
Author: Metaflow Developers
|
6
6
|
Author-email: help@metaflow.org
|
@@ -26,7 +26,7 @@ License-File: LICENSE
|
|
26
26
|
Requires-Dist: requests
|
27
27
|
Requires-Dist: boto3
|
28
28
|
Provides-Extra: stubs
|
29
|
-
Requires-Dist: metaflow-stubs==2.13.
|
29
|
+
Requires-Dist: metaflow-stubs==2.13.5; extra == "stubs"
|
30
30
|
Dynamic: author
|
31
31
|
Dynamic: author-email
|
32
32
|
Dynamic: classifier
|
@@ -504,6 +504,11 @@ def start(
|
|
504
504
|
# *after* the run decospecs so that they don't take precedence. In other
|
505
505
|
# words, for the same decorator, we want `myflow.py run --with foo` to
|
506
506
|
# take precedence over any other `foo` decospec
|
507
|
+
|
508
|
+
# Note that top-level decospecs are used primarily with non run/resume
|
509
|
+
# options as well as with the airflow/argo/sfn integrations which pass
|
510
|
+
# all the decospecs (the ones from top-level but also the ones from the
|
511
|
+
# run/resume level) through the tl decospecs.
|
507
512
|
ctx.obj.tl_decospecs = list(decospecs or [])
|
508
513
|
|
509
514
|
# initialize current and parameter context for deploy-time parameters
|
@@ -39,6 +39,8 @@ def before_run(obj, tags, decospecs):
|
|
39
39
|
+ list(obj.environment.decospecs() or [])
|
40
40
|
)
|
41
41
|
if all_decospecs:
|
42
|
+
# These decospecs are the ones from run/resume PLUS the ones from the
|
43
|
+
# environment (for example the @conda)
|
42
44
|
decorators._attach_decorators(obj.flow, all_decospecs)
|
43
45
|
decorators._init(obj.flow)
|
44
46
|
# Regenerate graph if we attached more decorators
|
@@ -77,14 +77,6 @@ from ..util import decompress_list
|
|
77
77
|
default=None,
|
78
78
|
help="Run id of the origin flow, if this task is part of a flow being resumed.",
|
79
79
|
)
|
80
|
-
@click.option(
|
81
|
-
"--with",
|
82
|
-
"decospecs",
|
83
|
-
multiple=True,
|
84
|
-
help="Add a decorator to this task. You can specify this "
|
85
|
-
"option multiple times to attach multiple decorators "
|
86
|
-
"to this task.",
|
87
|
-
)
|
88
80
|
@click.option(
|
89
81
|
"--ubf-context",
|
90
82
|
default="none",
|
@@ -112,7 +104,6 @@ def step(
|
|
112
104
|
max_user_code_retries=None,
|
113
105
|
clone_only=None,
|
114
106
|
clone_run_id=None,
|
115
|
-
decospecs=None,
|
116
107
|
ubf_context="none",
|
117
108
|
num_parallel=None,
|
118
109
|
):
|
@@ -136,10 +127,6 @@ def step(
|
|
136
127
|
raise CommandException("Function *%s* is not a step." % step_name)
|
137
128
|
echo("Executing a step, *%s*" % step_name, fg="magenta", bold=False)
|
138
129
|
|
139
|
-
if decospecs:
|
140
|
-
decorators._attach_decorators_to_step(func, decospecs)
|
141
|
-
decorators._init(ctx.obj.flow)
|
142
|
-
|
143
130
|
step_kwargs = ctx.params
|
144
131
|
# Remove argument `step_name` from `step_kwargs`.
|
145
132
|
step_kwargs.pop("step_name", None)
|
@@ -150,8 +150,8 @@ class Decorator(object):
|
|
150
150
|
return
|
151
151
|
|
152
152
|
# Note that by design, later values override previous ones.
|
153
|
-
self.attributes = unpack_delayed_evaluator(self.attributes)
|
154
|
-
self._user_defined_attributes.update(
|
153
|
+
self.attributes, new_user_attributes = unpack_delayed_evaluator(self.attributes)
|
154
|
+
self._user_defined_attributes.update(new_user_attributes)
|
155
155
|
self.attributes = resolve_delayed_evaluator(self.attributes)
|
156
156
|
|
157
157
|
self._ran_init = True
|
@@ -367,7 +367,9 @@ class Parameter(object):
|
|
367
367
|
)
|
368
368
|
|
369
369
|
# Resolve any value from configurations
|
370
|
-
self.kwargs = unpack_delayed_evaluator(
|
370
|
+
self.kwargs, _ = unpack_delayed_evaluator(
|
371
|
+
self.kwargs, ignore_errors=ignore_errors
|
372
|
+
)
|
371
373
|
# Do it one item at a time so errors are ignored at that level (as opposed to
|
372
374
|
# at the entire kwargs level)
|
373
375
|
self.kwargs = {
|
@@ -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
|
|
@@ -1705,6 +1705,7 @@ class ArgoWorkflows(object):
|
|
1705
1705
|
},
|
1706
1706
|
**{
|
1707
1707
|
# Some optional values for bookkeeping
|
1708
|
+
"METAFLOW_FLOW_FILENAME": os.path.basename(sys.argv[0]),
|
1708
1709
|
"METAFLOW_FLOW_NAME": self.flow.name,
|
1709
1710
|
"METAFLOW_STEP_NAME": node.name,
|
1710
1711
|
"METAFLOW_RUN_ID": run_id,
|
@@ -76,6 +76,12 @@ class CardDecorator(StepDecorator):
|
|
76
76
|
|
77
77
|
card_creator = None
|
78
78
|
|
79
|
+
_config_values = None
|
80
|
+
|
81
|
+
_config_file_name = None
|
82
|
+
|
83
|
+
task_finished_decos = 0
|
84
|
+
|
79
85
|
def __init__(self, *args, **kwargs):
|
80
86
|
super(CardDecorator, self).__init__(*args, **kwargs)
|
81
87
|
self._task_datastore = None
|
@@ -106,6 +112,25 @@ class CardDecorator(StepDecorator):
|
|
106
112
|
def _increment_step_counter(cls):
|
107
113
|
cls.step_counter += 1
|
108
114
|
|
115
|
+
@classmethod
|
116
|
+
def _increment_completed_counter(cls):
|
117
|
+
cls.task_finished_decos += 1
|
118
|
+
|
119
|
+
@classmethod
|
120
|
+
def _set_config_values(cls, config_values):
|
121
|
+
cls._config_values = config_values
|
122
|
+
|
123
|
+
@classmethod
|
124
|
+
def _set_config_file_name(cls, flow):
|
125
|
+
# Only create a config file from the very first card decorator.
|
126
|
+
if cls._config_values and not cls._config_file_name:
|
127
|
+
with tempfile.NamedTemporaryFile(
|
128
|
+
mode="w", encoding="utf-8", delete=False
|
129
|
+
) as config_file:
|
130
|
+
config_value = dump_config_values(flow)
|
131
|
+
json.dump(config_value, config_file)
|
132
|
+
cls._config_file_name = config_file.name
|
133
|
+
|
109
134
|
def step_init(
|
110
135
|
self, flow, graph, step_name, decorators, environment, flow_datastore, logger
|
111
136
|
):
|
@@ -116,11 +141,13 @@ class CardDecorator(StepDecorator):
|
|
116
141
|
|
117
142
|
# We check for configuration options. We do this here before they are
|
118
143
|
# converted to properties.
|
119
|
-
self.
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
144
|
+
self._set_config_values(
|
145
|
+
[
|
146
|
+
(config.name, ConfigInput.make_key_name(config.name))
|
147
|
+
for _, config in flow._get_parameters()
|
148
|
+
if config.IS_CONFIG_PARAMETER
|
149
|
+
]
|
150
|
+
)
|
124
151
|
|
125
152
|
self.card_options = self.attributes["options"]
|
126
153
|
|
@@ -159,15 +186,11 @@ class CardDecorator(StepDecorator):
|
|
159
186
|
|
160
187
|
# If we have configs, we need to dump them to a file so we can re-use them
|
161
188
|
# when calling the card creation subprocess.
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
json.dump(config_value, config_file)
|
168
|
-
self._config_file_name = config_file.name
|
169
|
-
else:
|
170
|
-
self._config_file_name = None
|
189
|
+
# Since a step can contain multiple card decorators, and all the card creation processes
|
190
|
+
# will reference the same config file (because of how the CardCreator is created (only single class instance)),
|
191
|
+
# we need to ensure that a single config file is being referenced for all card create commands.
|
192
|
+
# This config file will be removed when the last card decorator has finished creating its card.
|
193
|
+
self._set_config_file_name(flow)
|
171
194
|
|
172
195
|
card_type = self.attributes["type"]
|
173
196
|
card_class = get_card_class(card_type)
|
@@ -246,12 +269,7 @@ class CardDecorator(StepDecorator):
|
|
246
269
|
self.card_creator.create(mode="render", final=True, **create_options)
|
247
270
|
self.card_creator.create(mode="refresh", final=True, **create_options)
|
248
271
|
|
249
|
-
|
250
|
-
if self._config_file_name:
|
251
|
-
try:
|
252
|
-
os.unlink(self._config_file_name)
|
253
|
-
except Exception as e:
|
254
|
-
pass
|
272
|
+
self._cleanup(step_name)
|
255
273
|
|
256
274
|
@staticmethod
|
257
275
|
def _options(mapping):
|
@@ -286,3 +304,18 @@ class CardDecorator(StepDecorator):
|
|
286
304
|
top_level_options["local-config-file"] = self._config_file_name
|
287
305
|
|
288
306
|
return list(self._options(top_level_options))
|
307
|
+
|
308
|
+
def task_exception(
|
309
|
+
self, exception, step_name, flow, graph, retry_count, max_user_code_retries
|
310
|
+
):
|
311
|
+
self._cleanup(step_name)
|
312
|
+
|
313
|
+
def _cleanup(self, step_name):
|
314
|
+
self._increment_completed_counter()
|
315
|
+
if self.task_finished_decos == self.total_decos_on_step[step_name]:
|
316
|
+
# Unlink the config file if it exists
|
317
|
+
if self._config_file_name:
|
318
|
+
try:
|
319
|
+
os.unlink(self._config_file_name)
|
320
|
+
except Exception as e:
|
321
|
+
pass
|
@@ -362,11 +362,7 @@ class TriggerOnFinishDecorator(FlowDecorator):
|
|
362
362
|
"""
|
363
363
|
|
364
364
|
name = "trigger_on_finish"
|
365
|
-
|
366
|
-
"flow": None, # flow_name or project_flow_name
|
367
|
-
"flows": [], # flow_names or project_flow_names
|
368
|
-
"options": {},
|
369
|
-
}
|
365
|
+
|
370
366
|
options = {
|
371
367
|
"trigger": dict(
|
372
368
|
multiple=True,
|
@@ -374,6 +370,14 @@ class TriggerOnFinishDecorator(FlowDecorator):
|
|
374
370
|
help="Specify run pathspec for testing @trigger_on_finish locally.",
|
375
371
|
),
|
376
372
|
}
|
373
|
+
defaults = {
|
374
|
+
"flow": None, # flow_name or project_flow_name
|
375
|
+
"flows": [], # flow_names or project_flow_names
|
376
|
+
"options": {},
|
377
|
+
# Re-enable if you want to support TL options directly in the decorator like
|
378
|
+
# for @project decorator
|
379
|
+
# **{k: v["default"] for k, v in options.items()},
|
380
|
+
}
|
377
381
|
|
378
382
|
def flow_init(
|
379
383
|
self,
|
@@ -539,13 +543,43 @@ class TriggerOnFinishDecorator(FlowDecorator):
|
|
539
543
|
self.options = self.attributes["options"]
|
540
544
|
|
541
545
|
# Handle scenario for local testing using --trigger.
|
546
|
+
|
547
|
+
# Re-enable this code if you want to support passing trigger directly in the
|
548
|
+
# decorator in a way similar to how production and branch are passed in the
|
549
|
+
# project decorator.
|
550
|
+
|
551
|
+
# # This is overkill since default is None for all options but adding this code
|
552
|
+
# # to make it safe if other non None-default options are added in the future.
|
553
|
+
# for op in options:
|
554
|
+
# if (
|
555
|
+
# op in self._user_defined_attributes
|
556
|
+
# and options[op] != self.defaults[op]
|
557
|
+
# and self.attributes[op] != options[op]
|
558
|
+
# ):
|
559
|
+
# # Exception if:
|
560
|
+
# # - the user provides a value in the attributes field
|
561
|
+
# # - AND the user provided a value in the command line (non default)
|
562
|
+
# # - AND the values are different
|
563
|
+
# # Note that this won't raise an error if the user provided the default
|
564
|
+
# # value in the command line and provided one in attribute but although
|
565
|
+
# # slightly inconsistent, it is not incorrect.
|
566
|
+
# raise MetaflowException(
|
567
|
+
# "You cannot pass %s as both a command-line argument and an attribute "
|
568
|
+
# "of the @trigger_on_finish decorator." % op
|
569
|
+
# )
|
570
|
+
|
571
|
+
# if "trigger" in self._user_defined_attributes:
|
572
|
+
# trigger_option = self.attributes["trigger"]
|
573
|
+
# else:
|
574
|
+
trigger_option = options["trigger"]
|
575
|
+
|
542
576
|
self._option_values = options
|
543
|
-
if
|
577
|
+
if trigger_option:
|
544
578
|
from metaflow import Run
|
545
579
|
from metaflow.events import Trigger
|
546
580
|
|
547
581
|
run_objs = []
|
548
|
-
for run_pathspec in
|
582
|
+
for run_pathspec in trigger_option:
|
549
583
|
if len(run_pathspec.split("/")) != 2:
|
550
584
|
raise MetaflowException(
|
551
585
|
"Incorrect format for run pathspec for *--trigger*. "
|
@@ -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"]
|
@@ -547,6 +547,13 @@ class KubernetesDecorator(StepDecorator):
|
|
547
547
|
self._save_logs_sidecar = Sidecar("save_logs_periodically")
|
548
548
|
self._save_logs_sidecar.start()
|
549
549
|
|
550
|
+
# Start spot termination monitor sidecar.
|
551
|
+
current._update_env(
|
552
|
+
{"spot_termination_notice": "/tmp/spot_termination_notice"}
|
553
|
+
)
|
554
|
+
self._spot_monitor_sidecar = Sidecar("spot_termination_monitor")
|
555
|
+
self._spot_monitor_sidecar.start()
|
556
|
+
|
550
557
|
num_parallel = None
|
551
558
|
if hasattr(flow, "_parallel_ubf_iter"):
|
552
559
|
num_parallel = flow._parallel_ubf_iter.num_parallel
|
@@ -605,6 +612,7 @@ class KubernetesDecorator(StepDecorator):
|
|
605
612
|
|
606
613
|
try:
|
607
614
|
self._save_logs_sidecar.terminate()
|
615
|
+
self._spot_monitor_sidecar.terminate()
|
608
616
|
except:
|
609
617
|
# Best effort kill
|
610
618
|
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}")
|
@@ -72,7 +72,6 @@ class ProjectDecorator(FlowDecorator):
|
|
72
72
|
"""
|
73
73
|
|
74
74
|
name = "project"
|
75
|
-
defaults = {"name": None}
|
76
75
|
|
77
76
|
options = {
|
78
77
|
"production": dict(
|
@@ -91,19 +90,48 @@ class ProjectDecorator(FlowDecorator):
|
|
91
90
|
),
|
92
91
|
}
|
93
92
|
|
93
|
+
defaults = {"name": None, **{k: v["default"] for k, v in options.items()}}
|
94
|
+
|
94
95
|
def flow_init(
|
95
96
|
self, flow, graph, environment, flow_datastore, metadata, logger, echo, options
|
96
97
|
):
|
97
98
|
self._option_values = options
|
98
99
|
project_name = self.attributes.get("name")
|
100
|
+
for op in options:
|
101
|
+
if (
|
102
|
+
op in self._user_defined_attributes
|
103
|
+
and options[op] != self.defaults[op]
|
104
|
+
and self.attributes[op] != options[op]
|
105
|
+
):
|
106
|
+
# Exception if:
|
107
|
+
# - the user provides a value in the attributes field
|
108
|
+
# - AND the user provided a value in the command line (non default)
|
109
|
+
# - AND the values are different
|
110
|
+
# Note that this won't raise an error if the user provided the default
|
111
|
+
# value in the command line and provided one in attribute but although
|
112
|
+
# slightly inconsistent, it is not incorrect.
|
113
|
+
raise MetaflowException(
|
114
|
+
"You cannot pass %s as both a command-line argument and an attribute "
|
115
|
+
"of the @project decorator." % op
|
116
|
+
)
|
117
|
+
if "branch" in self._user_defined_attributes:
|
118
|
+
project_branch = self.attributes["branch"]
|
119
|
+
else:
|
120
|
+
project_branch = options["branch"]
|
121
|
+
|
122
|
+
if "production" in self._user_defined_attributes:
|
123
|
+
project_production = self.attributes["production"]
|
124
|
+
else:
|
125
|
+
project_production = options["production"]
|
126
|
+
|
99
127
|
project_flow_name, branch_name = format_name(
|
100
128
|
flow.name,
|
101
129
|
project_name,
|
102
|
-
|
103
|
-
|
130
|
+
project_production,
|
131
|
+
project_branch,
|
104
132
|
get_username(),
|
105
133
|
)
|
106
|
-
is_user_branch =
|
134
|
+
is_user_branch = project_branch is None and not project_production
|
107
135
|
echo(
|
108
136
|
"Project: *%s*, Branch: *%s*" % (project_name, branch_name),
|
109
137
|
fg="magenta",
|
@@ -114,7 +142,7 @@ class ProjectDecorator(FlowDecorator):
|
|
114
142
|
"project_name": project_name,
|
115
143
|
"branch_name": branch_name,
|
116
144
|
"is_user_branch": is_user_branch,
|
117
|
-
"is_production":
|
145
|
+
"is_production": project_production,
|
118
146
|
"project_flow_name": project_flow_name,
|
119
147
|
}
|
120
148
|
)
|
@@ -3,7 +3,7 @@ import json
|
|
3
3
|
import os
|
4
4
|
import re
|
5
5
|
|
6
|
-
from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Union
|
6
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, TYPE_CHECKING, Union
|
7
7
|
|
8
8
|
|
9
9
|
from ..exception import MetaflowException
|
@@ -171,7 +171,7 @@ class DelayEvaluator(collections.abc.Mapping):
|
|
171
171
|
yield "%s%d" % (UNPACK_KEY, id(self))
|
172
172
|
|
173
173
|
def __getitem__(self, key):
|
174
|
-
if key == "%s%d" % (UNPACK_KEY, id(self)):
|
174
|
+
if isinstance(key, str) and key == "%s%d" % (UNPACK_KEY, id(self)):
|
175
175
|
return self
|
176
176
|
if self._access is None:
|
177
177
|
raise KeyError(key)
|
@@ -196,12 +196,23 @@ class DelayEvaluator(collections.abc.Mapping):
|
|
196
196
|
if flow_cls is None:
|
197
197
|
# We are not executing inside a flow (ie: not the CLI)
|
198
198
|
raise MetaflowException(
|
199
|
-
"Config object can only be used directly in the FlowSpec defining them
|
200
|
-
"
|
199
|
+
"Config object can only be used directly in the FlowSpec defining them "
|
200
|
+
"(or their flow decorators)."
|
201
201
|
)
|
202
202
|
if self._access is not None:
|
203
203
|
# Build the final expression by adding all the fields in access as . fields
|
204
|
-
|
204
|
+
access_list = [self._config_expr]
|
205
|
+
for a in self._access:
|
206
|
+
if isinstance(a, str):
|
207
|
+
access_list.append(a)
|
208
|
+
elif isinstance(a, DelayEvaluator):
|
209
|
+
# Supports things like config[other_config.selector].var
|
210
|
+
access_list.append(a())
|
211
|
+
else:
|
212
|
+
raise MetaflowException(
|
213
|
+
"Field '%s' of type '%s' is not supported" % (str(a), type(a))
|
214
|
+
)
|
215
|
+
self._config_expr = ".".join(access_list)
|
205
216
|
# Evaluate the expression setting the config values as local variables
|
206
217
|
try:
|
207
218
|
return eval(
|
@@ -369,7 +380,7 @@ class Config(Parameter, collections.abc.Mapping):
|
|
369
380
|
|
370
381
|
def __getitem__(self, key):
|
371
382
|
self._init_delayed_evaluator()
|
372
|
-
if key.startswith(UNPACK_KEY):
|
383
|
+
if isinstance(key, str) and key.startswith(UNPACK_KEY):
|
373
384
|
return self._delayed_evaluator[key]
|
374
385
|
return DelayEvaluator(self.name.lower())[key]
|
375
386
|
|
@@ -406,17 +417,20 @@ def resolve_delayed_evaluator(v: Any, ignore_errors: bool = False) -> Any:
|
|
406
417
|
|
407
418
|
def unpack_delayed_evaluator(
|
408
419
|
to_unpack: Dict[str, Any], ignore_errors: bool = False
|
409
|
-
) -> Dict[str, Any]:
|
420
|
+
) -> Tuple[Dict[str, Any], List[str]]:
|
410
421
|
result = {}
|
422
|
+
new_keys = []
|
411
423
|
for k, v in to_unpack.items():
|
412
424
|
if not isinstance(k, str) or not k.startswith(UNPACK_KEY):
|
413
425
|
result[k] = v
|
414
426
|
else:
|
415
427
|
# k.startswith(UNPACK_KEY)
|
416
428
|
try:
|
417
|
-
|
429
|
+
new_vals = resolve_delayed_evaluator(v)
|
430
|
+
new_keys.extend(new_vals.keys())
|
431
|
+
result.update(new_vals)
|
418
432
|
except Exception as e:
|
419
433
|
if ignore_errors:
|
420
434
|
continue
|
421
435
|
raise e
|
422
|
-
return result
|
436
|
+
return result, new_keys
|
@@ -0,0 +1 @@
|
|
1
|
+
metaflow_version = "2.13.5"
|