ob-metaflow 2.11.13.1__py2.py3-none-any.whl → 2.19.7.1rc0__py2.py3-none-any.whl
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/R.py +10 -7
- metaflow/__init__.py +40 -25
- metaflow/_vendor/imghdr/__init__.py +186 -0
- metaflow/_vendor/importlib_metadata/__init__.py +1063 -0
- metaflow/_vendor/importlib_metadata/_adapters.py +68 -0
- metaflow/_vendor/importlib_metadata/_collections.py +30 -0
- metaflow/_vendor/importlib_metadata/_compat.py +71 -0
- metaflow/_vendor/importlib_metadata/_functools.py +104 -0
- metaflow/_vendor/importlib_metadata/_itertools.py +73 -0
- metaflow/_vendor/importlib_metadata/_meta.py +48 -0
- metaflow/_vendor/importlib_metadata/_text.py +99 -0
- metaflow/_vendor/importlib_metadata/py.typed +0 -0
- metaflow/_vendor/typeguard/__init__.py +48 -0
- metaflow/_vendor/typeguard/_checkers.py +1070 -0
- metaflow/_vendor/typeguard/_config.py +108 -0
- metaflow/_vendor/typeguard/_decorators.py +233 -0
- metaflow/_vendor/typeguard/_exceptions.py +42 -0
- metaflow/_vendor/typeguard/_functions.py +308 -0
- metaflow/_vendor/typeguard/_importhook.py +213 -0
- metaflow/_vendor/typeguard/_memo.py +48 -0
- metaflow/_vendor/typeguard/_pytest_plugin.py +127 -0
- metaflow/_vendor/typeguard/_suppression.py +86 -0
- metaflow/_vendor/typeguard/_transformer.py +1229 -0
- metaflow/_vendor/typeguard/_union_transformer.py +55 -0
- metaflow/_vendor/typeguard/_utils.py +173 -0
- metaflow/_vendor/typeguard/py.typed +0 -0
- metaflow/_vendor/typing_extensions.py +3641 -0
- metaflow/_vendor/v3_7/importlib_metadata/__init__.py +1063 -0
- metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +68 -0
- metaflow/_vendor/v3_7/importlib_metadata/_collections.py +30 -0
- metaflow/_vendor/v3_7/importlib_metadata/_compat.py +71 -0
- metaflow/_vendor/v3_7/importlib_metadata/_functools.py +104 -0
- metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +73 -0
- metaflow/_vendor/v3_7/importlib_metadata/_meta.py +48 -0
- metaflow/_vendor/v3_7/importlib_metadata/_text.py +99 -0
- metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
- metaflow/_vendor/v3_7/typeguard/__init__.py +48 -0
- metaflow/_vendor/v3_7/typeguard/_checkers.py +906 -0
- metaflow/_vendor/v3_7/typeguard/_config.py +108 -0
- metaflow/_vendor/v3_7/typeguard/_decorators.py +237 -0
- metaflow/_vendor/v3_7/typeguard/_exceptions.py +42 -0
- metaflow/_vendor/v3_7/typeguard/_functions.py +310 -0
- metaflow/_vendor/v3_7/typeguard/_importhook.py +213 -0
- metaflow/_vendor/v3_7/typeguard/_memo.py +48 -0
- metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +100 -0
- metaflow/_vendor/v3_7/typeguard/_suppression.py +88 -0
- metaflow/_vendor/v3_7/typeguard/_transformer.py +1207 -0
- metaflow/_vendor/v3_7/typeguard/_union_transformer.py +54 -0
- metaflow/_vendor/v3_7/typeguard/_utils.py +169 -0
- metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
- metaflow/_vendor/v3_7/typing_extensions.py +3072 -0
- metaflow/_vendor/yaml/__init__.py +427 -0
- metaflow/_vendor/yaml/composer.py +139 -0
- metaflow/_vendor/yaml/constructor.py +748 -0
- metaflow/_vendor/yaml/cyaml.py +101 -0
- metaflow/_vendor/yaml/dumper.py +62 -0
- metaflow/_vendor/yaml/emitter.py +1137 -0
- metaflow/_vendor/yaml/error.py +75 -0
- metaflow/_vendor/yaml/events.py +86 -0
- metaflow/_vendor/yaml/loader.py +63 -0
- metaflow/_vendor/yaml/nodes.py +49 -0
- metaflow/_vendor/yaml/parser.py +589 -0
- metaflow/_vendor/yaml/reader.py +185 -0
- metaflow/_vendor/yaml/representer.py +389 -0
- metaflow/_vendor/yaml/resolver.py +227 -0
- metaflow/_vendor/yaml/scanner.py +1435 -0
- metaflow/_vendor/yaml/serializer.py +111 -0
- metaflow/_vendor/yaml/tokens.py +104 -0
- metaflow/cards.py +5 -0
- metaflow/cli.py +331 -785
- metaflow/cli_args.py +17 -0
- metaflow/cli_components/__init__.py +0 -0
- metaflow/cli_components/dump_cmd.py +96 -0
- metaflow/cli_components/init_cmd.py +52 -0
- metaflow/cli_components/run_cmds.py +546 -0
- metaflow/cli_components/step_cmd.py +334 -0
- metaflow/cli_components/utils.py +140 -0
- metaflow/client/__init__.py +1 -0
- metaflow/client/core.py +467 -73
- metaflow/client/filecache.py +75 -35
- metaflow/clone_util.py +7 -1
- metaflow/cmd/code/__init__.py +231 -0
- metaflow/cmd/develop/stub_generator.py +756 -288
- metaflow/cmd/develop/stubs.py +12 -28
- metaflow/cmd/main_cli.py +6 -4
- metaflow/cmd/make_wrapper.py +78 -0
- metaflow/datastore/__init__.py +1 -0
- metaflow/datastore/content_addressed_store.py +41 -10
- metaflow/datastore/datastore_set.py +11 -2
- metaflow/datastore/flow_datastore.py +156 -10
- metaflow/datastore/spin_datastore.py +91 -0
- metaflow/datastore/task_datastore.py +154 -39
- metaflow/debug.py +5 -0
- metaflow/decorators.py +404 -78
- metaflow/exception.py +8 -2
- metaflow/extension_support/__init__.py +527 -376
- metaflow/extension_support/_empty_file.py +2 -2
- metaflow/extension_support/plugins.py +49 -31
- metaflow/flowspec.py +482 -33
- metaflow/graph.py +210 -42
- metaflow/includefile.py +84 -40
- metaflow/lint.py +141 -22
- metaflow/meta_files.py +13 -0
- metaflow/{metadata → metadata_provider}/heartbeat.py +24 -8
- metaflow/{metadata → metadata_provider}/metadata.py +86 -1
- metaflow/metaflow_config.py +175 -28
- metaflow/metaflow_config_funcs.py +51 -3
- metaflow/metaflow_current.py +4 -10
- metaflow/metaflow_environment.py +139 -53
- metaflow/metaflow_git.py +115 -0
- metaflow/metaflow_profile.py +18 -0
- metaflow/metaflow_version.py +150 -66
- metaflow/mflog/__init__.py +4 -3
- metaflow/mflog/save_logs.py +2 -2
- metaflow/multicore_utils.py +31 -14
- metaflow/package/__init__.py +673 -0
- metaflow/packaging_sys/__init__.py +880 -0
- metaflow/packaging_sys/backend.py +128 -0
- metaflow/packaging_sys/distribution_support.py +153 -0
- metaflow/packaging_sys/tar_backend.py +99 -0
- metaflow/packaging_sys/utils.py +54 -0
- metaflow/packaging_sys/v1.py +527 -0
- metaflow/parameters.py +149 -28
- metaflow/plugins/__init__.py +74 -5
- metaflow/plugins/airflow/airflow.py +40 -25
- metaflow/plugins/airflow/airflow_cli.py +22 -5
- metaflow/plugins/airflow/airflow_decorator.py +1 -1
- metaflow/plugins/airflow/airflow_utils.py +5 -3
- metaflow/plugins/airflow/sensors/base_sensor.py +4 -4
- metaflow/plugins/airflow/sensors/external_task_sensor.py +2 -2
- metaflow/plugins/airflow/sensors/s3_sensor.py +2 -2
- metaflow/plugins/argo/argo_client.py +78 -33
- metaflow/plugins/argo/argo_events.py +6 -6
- metaflow/plugins/argo/argo_workflows.py +2410 -527
- metaflow/plugins/argo/argo_workflows_cli.py +571 -121
- metaflow/plugins/argo/argo_workflows_decorator.py +43 -12
- metaflow/plugins/argo/argo_workflows_deployer.py +106 -0
- metaflow/plugins/argo/argo_workflows_deployer_objects.py +453 -0
- metaflow/plugins/argo/capture_error.py +73 -0
- metaflow/plugins/argo/conditional_input_paths.py +35 -0
- metaflow/plugins/argo/exit_hooks.py +209 -0
- metaflow/plugins/argo/jobset_input_paths.py +15 -0
- metaflow/plugins/argo/param_val.py +19 -0
- metaflow/plugins/aws/aws_client.py +10 -3
- metaflow/plugins/aws/aws_utils.py +55 -2
- metaflow/plugins/aws/batch/batch.py +72 -5
- metaflow/plugins/aws/batch/batch_cli.py +33 -10
- metaflow/plugins/aws/batch/batch_client.py +4 -3
- metaflow/plugins/aws/batch/batch_decorator.py +102 -35
- metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +13 -10
- metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -3
- metaflow/plugins/aws/step_functions/production_token.py +1 -1
- metaflow/plugins/aws/step_functions/step_functions.py +65 -8
- metaflow/plugins/aws/step_functions/step_functions_cli.py +101 -7
- metaflow/plugins/aws/step_functions/step_functions_decorator.py +1 -2
- metaflow/plugins/aws/step_functions/step_functions_deployer.py +97 -0
- metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +264 -0
- metaflow/plugins/azure/azure_exceptions.py +1 -1
- metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +240 -0
- metaflow/plugins/azure/azure_tail.py +1 -1
- metaflow/plugins/azure/includefile_support.py +2 -0
- metaflow/plugins/cards/card_cli.py +66 -30
- metaflow/plugins/cards/card_creator.py +25 -1
- metaflow/plugins/cards/card_datastore.py +21 -49
- metaflow/plugins/cards/card_decorator.py +132 -8
- metaflow/plugins/cards/card_modules/basic.py +112 -17
- metaflow/plugins/cards/card_modules/bundle.css +1 -1
- metaflow/plugins/cards/card_modules/card.py +16 -1
- metaflow/plugins/cards/card_modules/chevron/renderer.py +1 -1
- metaflow/plugins/cards/card_modules/components.py +665 -28
- metaflow/plugins/cards/card_modules/convert_to_native_type.py +36 -7
- metaflow/plugins/cards/card_modules/json_viewer.py +232 -0
- metaflow/plugins/cards/card_modules/main.css +1 -0
- metaflow/plugins/cards/card_modules/main.js +68 -49
- metaflow/plugins/cards/card_modules/renderer_tools.py +1 -0
- metaflow/plugins/cards/card_modules/test_cards.py +26 -12
- metaflow/plugins/cards/card_server.py +39 -14
- metaflow/plugins/cards/component_serializer.py +2 -9
- metaflow/plugins/cards/metadata.py +22 -0
- metaflow/plugins/catch_decorator.py +9 -0
- metaflow/plugins/datastores/azure_storage.py +10 -1
- metaflow/plugins/datastores/gs_storage.py +6 -2
- metaflow/plugins/datastores/local_storage.py +12 -6
- metaflow/plugins/datastores/spin_storage.py +12 -0
- metaflow/plugins/datatools/local.py +2 -0
- metaflow/plugins/datatools/s3/s3.py +126 -75
- metaflow/plugins/datatools/s3/s3op.py +254 -121
- metaflow/plugins/env_escape/__init__.py +3 -3
- metaflow/plugins/env_escape/client_modules.py +102 -72
- metaflow/plugins/env_escape/server.py +7 -0
- metaflow/plugins/env_escape/stub.py +24 -5
- metaflow/plugins/events_decorator.py +343 -185
- metaflow/plugins/exit_hook/__init__.py +0 -0
- metaflow/plugins/exit_hook/exit_hook_decorator.py +46 -0
- metaflow/plugins/exit_hook/exit_hook_script.py +52 -0
- metaflow/plugins/gcp/__init__.py +1 -1
- metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +11 -6
- metaflow/plugins/gcp/gs_tail.py +10 -6
- metaflow/plugins/gcp/includefile_support.py +3 -0
- metaflow/plugins/kubernetes/kube_utils.py +108 -0
- metaflow/plugins/kubernetes/kubernetes.py +411 -130
- metaflow/plugins/kubernetes/kubernetes_cli.py +168 -36
- metaflow/plugins/kubernetes/kubernetes_client.py +104 -2
- metaflow/plugins/kubernetes/kubernetes_decorator.py +246 -88
- metaflow/plugins/kubernetes/kubernetes_job.py +253 -581
- metaflow/plugins/kubernetes/kubernetes_jobsets.py +1071 -0
- metaflow/plugins/kubernetes/spot_metadata_cli.py +69 -0
- metaflow/plugins/kubernetes/spot_monitor_sidecar.py +109 -0
- metaflow/plugins/logs_cli.py +359 -0
- metaflow/plugins/{metadata → metadata_providers}/local.py +144 -84
- metaflow/plugins/{metadata → metadata_providers}/service.py +103 -26
- metaflow/plugins/metadata_providers/spin.py +16 -0
- metaflow/plugins/package_cli.py +36 -24
- metaflow/plugins/parallel_decorator.py +128 -11
- metaflow/plugins/parsers.py +16 -0
- metaflow/plugins/project_decorator.py +51 -5
- metaflow/plugins/pypi/bootstrap.py +357 -105
- metaflow/plugins/pypi/conda_decorator.py +82 -81
- metaflow/plugins/pypi/conda_environment.py +187 -52
- metaflow/plugins/pypi/micromamba.py +157 -47
- metaflow/plugins/pypi/parsers.py +268 -0
- metaflow/plugins/pypi/pip.py +88 -13
- metaflow/plugins/pypi/pypi_decorator.py +37 -1
- metaflow/plugins/pypi/utils.py +48 -2
- metaflow/plugins/resources_decorator.py +2 -2
- metaflow/plugins/secrets/__init__.py +3 -0
- metaflow/plugins/secrets/secrets_decorator.py +26 -181
- metaflow/plugins/secrets/secrets_func.py +49 -0
- metaflow/plugins/secrets/secrets_spec.py +101 -0
- metaflow/plugins/secrets/utils.py +74 -0
- metaflow/plugins/tag_cli.py +4 -7
- metaflow/plugins/test_unbounded_foreach_decorator.py +41 -6
- metaflow/plugins/timeout_decorator.py +3 -3
- metaflow/plugins/uv/__init__.py +0 -0
- metaflow/plugins/uv/bootstrap.py +128 -0
- metaflow/plugins/uv/uv_environment.py +72 -0
- metaflow/procpoll.py +1 -1
- metaflow/pylint_wrapper.py +5 -1
- metaflow/runner/__init__.py +0 -0
- metaflow/runner/click_api.py +717 -0
- metaflow/runner/deployer.py +470 -0
- metaflow/runner/deployer_impl.py +201 -0
- metaflow/runner/metaflow_runner.py +714 -0
- metaflow/runner/nbdeploy.py +132 -0
- metaflow/runner/nbrun.py +225 -0
- metaflow/runner/subprocess_manager.py +650 -0
- metaflow/runner/utils.py +335 -0
- metaflow/runtime.py +1078 -260
- metaflow/sidecar/sidecar_worker.py +1 -1
- metaflow/system/__init__.py +5 -0
- metaflow/system/system_logger.py +85 -0
- metaflow/system/system_monitor.py +108 -0
- metaflow/system/system_utils.py +19 -0
- metaflow/task.py +521 -225
- metaflow/tracing/__init__.py +7 -7
- metaflow/tracing/span_exporter.py +31 -38
- metaflow/tracing/tracing_modules.py +38 -43
- metaflow/tuple_util.py +27 -0
- metaflow/user_configs/__init__.py +0 -0
- metaflow/user_configs/config_options.py +563 -0
- metaflow/user_configs/config_parameters.py +598 -0
- metaflow/user_decorators/__init__.py +0 -0
- metaflow/user_decorators/common.py +144 -0
- metaflow/user_decorators/mutable_flow.py +512 -0
- metaflow/user_decorators/mutable_step.py +424 -0
- metaflow/user_decorators/user_flow_decorator.py +264 -0
- metaflow/user_decorators/user_step_decorator.py +749 -0
- metaflow/util.py +243 -27
- metaflow/vendor.py +23 -7
- metaflow/version.py +1 -1
- ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/Makefile +355 -0
- ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/Tiltfile +726 -0
- ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/pick_services.sh +105 -0
- ob_metaflow-2.19.7.1rc0.dist-info/METADATA +87 -0
- ob_metaflow-2.19.7.1rc0.dist-info/RECORD +445 -0
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/WHEEL +1 -1
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/entry_points.txt +1 -0
- metaflow/_vendor/v3_5/__init__.py +0 -1
- metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -644
- metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -152
- metaflow/package.py +0 -188
- ob_metaflow-2.11.13.1.dist-info/METADATA +0 -85
- ob_metaflow-2.11.13.1.dist-info/RECORD +0 -308
- /metaflow/_vendor/{v3_5/zipp.py → zipp.py} +0 -0
- /metaflow/{metadata → metadata_provider}/__init__.py +0 -0
- /metaflow/{metadata → metadata_provider}/util.py +0 -0
- /metaflow/plugins/{metadata → metadata_providers}/__init__.py +0 -0
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info/licenses}/LICENSE +0 -0
- {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/top_level.txt +0 -0
metaflow/parameters.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from contextlib import contextmanager
|
|
4
|
+
from threading import local
|
|
5
|
+
|
|
6
|
+
from typing import Any, Callable, Dict, NamedTuple, Optional, TYPE_CHECKING, Type, Union
|
|
3
7
|
|
|
4
8
|
from metaflow._vendor import click
|
|
5
9
|
|
|
@@ -10,6 +14,9 @@ from .exception import (
|
|
|
10
14
|
MetaflowException,
|
|
11
15
|
)
|
|
12
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from .user_configs.config_parameters import ConfigValue
|
|
19
|
+
|
|
13
20
|
try:
|
|
14
21
|
# Python2
|
|
15
22
|
strtype = basestring
|
|
@@ -28,13 +35,57 @@ ParameterContext = NamedTuple(
|
|
|
28
35
|
("parameter_name", str),
|
|
29
36
|
("logger", Callable[..., None]),
|
|
30
37
|
("ds_type", str),
|
|
38
|
+
("configs", Optional["ConfigValue"]),
|
|
31
39
|
],
|
|
32
40
|
)
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
|
|
43
|
+
# When we launch a flow, we need to know the parameters so we can
|
|
44
|
+
# attach them with add_custom_parameters to commands. This used to be a global
|
|
45
|
+
# but causes problems when multiple FlowSpec are loaded (as can happen when using
|
|
46
|
+
# the Runner or just if multiple Flows are defined and instantiated). To minimally
|
|
47
|
+
# impact code, we now create the CLI with a thread local value of the FlowSpec
|
|
48
|
+
# that is being used to create the CLI which enables us to extract the parameters
|
|
49
|
+
# directly from the Flow.
|
|
50
|
+
current_flow = local()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@contextmanager
|
|
54
|
+
def flow_context(flow_cls):
|
|
55
|
+
"""
|
|
56
|
+
Context manager to set the current flow for the thread. This is used
|
|
57
|
+
to extract the parameters from the FlowSpec that is being used to create
|
|
58
|
+
the CLI.
|
|
59
|
+
"""
|
|
60
|
+
# Use a stack because with the runner this can get called multiple times in
|
|
61
|
+
# a nested fashion
|
|
62
|
+
current_flow.flow_cls_stack = getattr(current_flow, "flow_cls_stack", [])
|
|
63
|
+
current_flow.flow_cls_stack.insert(0, flow_cls)
|
|
64
|
+
current_flow.flow_cls = current_flow.flow_cls_stack[0]
|
|
65
|
+
try:
|
|
66
|
+
yield
|
|
67
|
+
finally:
|
|
68
|
+
current_flow.flow_cls_stack = current_flow.flow_cls_stack[1:]
|
|
69
|
+
if len(current_flow.flow_cls_stack) == 0:
|
|
70
|
+
del current_flow.flow_cls_stack
|
|
71
|
+
del current_flow.flow_cls
|
|
72
|
+
else:
|
|
73
|
+
current_flow.flow_cls = current_flow.flow_cls_stack[0]
|
|
74
|
+
|
|
75
|
+
|
|
35
76
|
context_proto = None
|
|
36
77
|
|
|
37
78
|
|
|
79
|
+
def replace_flow_context(flow_cls):
|
|
80
|
+
"""
|
|
81
|
+
Replace the current flow context with a new flow class. This is used
|
|
82
|
+
when we change the current flow class after having run user configuration functions
|
|
83
|
+
"""
|
|
84
|
+
current_flow.flow_cls_stack = current_flow.flow_cls_stack[1:]
|
|
85
|
+
current_flow.flow_cls_stack.insert(0, flow_cls)
|
|
86
|
+
current_flow.flow_cls = current_flow.flow_cls_stack[0]
|
|
87
|
+
|
|
88
|
+
|
|
38
89
|
class JSONTypeClass(click.ParamType):
|
|
39
90
|
name = "JSON"
|
|
40
91
|
|
|
@@ -78,9 +129,9 @@ class DeployTimeField(object):
|
|
|
78
129
|
self.parameter_name = parameter_name
|
|
79
130
|
self.parameter_type = parameter_type
|
|
80
131
|
self.return_str = return_str
|
|
81
|
-
self.print_representation = (
|
|
82
|
-
|
|
83
|
-
)
|
|
132
|
+
self.print_representation = self.user_print_representation = (
|
|
133
|
+
print_representation
|
|
134
|
+
)
|
|
84
135
|
if self.print_representation is None:
|
|
85
136
|
self.print_representation = str(self.fun)
|
|
86
137
|
|
|
@@ -114,6 +165,7 @@ class DeployTimeField(object):
|
|
|
114
165
|
return self._check_type(val, deploy_time)
|
|
115
166
|
|
|
116
167
|
def _check_type(self, val, deploy_time):
|
|
168
|
+
|
|
117
169
|
# it is easy to introduce a deploy-time function that accidentally
|
|
118
170
|
# returns a value whose type is not compatible with what is defined
|
|
119
171
|
# in Parameter. Let's catch those mistakes early here, instead of
|
|
@@ -121,7 +173,7 @@ class DeployTimeField(object):
|
|
|
121
173
|
|
|
122
174
|
# note: this doesn't work with long in Python2 or types defined as
|
|
123
175
|
# click types, e.g. click.INT
|
|
124
|
-
TYPES = {bool: "bool", int: "int", float: "float", list: "list"}
|
|
176
|
+
TYPES = {bool: "bool", int: "int", float: "float", list: "list", dict: "dict"}
|
|
125
177
|
|
|
126
178
|
msg = (
|
|
127
179
|
"The value returned by the deploy-time function for "
|
|
@@ -129,7 +181,12 @@ class DeployTimeField(object):
|
|
|
129
181
|
% (self.parameter_name, self.field)
|
|
130
182
|
)
|
|
131
183
|
|
|
132
|
-
if self.parameter_type
|
|
184
|
+
if isinstance(self.parameter_type, list):
|
|
185
|
+
if not any(isinstance(val, x) for x in self.parameter_type):
|
|
186
|
+
msg += "Expected one of the following %s." % TYPES[self.parameter_type]
|
|
187
|
+
raise ParameterFieldTypeMismatch(msg)
|
|
188
|
+
return str(val) if self.return_str else val
|
|
189
|
+
elif self.parameter_type in TYPES:
|
|
133
190
|
if type(val) != self.parameter_type:
|
|
134
191
|
msg += "Expected a %s." % TYPES[self.parameter_type]
|
|
135
192
|
raise ParameterFieldTypeMismatch(msg)
|
|
@@ -167,12 +224,18 @@ class DeployTimeField(object):
|
|
|
167
224
|
def deploy_time_eval(value):
|
|
168
225
|
if isinstance(value, DeployTimeField):
|
|
169
226
|
return value(deploy_time=True)
|
|
227
|
+
elif isinstance(value, DelayedEvaluationParameter):
|
|
228
|
+
return value(return_str=True)
|
|
170
229
|
else:
|
|
171
230
|
return value
|
|
172
231
|
|
|
173
232
|
|
|
174
233
|
# this is called by cli.main
|
|
175
|
-
def set_parameter_context(flow_name, echo, datastore):
|
|
234
|
+
def set_parameter_context(flow_name, echo, datastore, configs):
|
|
235
|
+
from .user_configs.config_parameters import (
|
|
236
|
+
ConfigValue,
|
|
237
|
+
) # Prevent circular dependency
|
|
238
|
+
|
|
176
239
|
global context_proto
|
|
177
240
|
context_proto = ParameterContext(
|
|
178
241
|
flow_name=flow_name,
|
|
@@ -180,6 +243,7 @@ def set_parameter_context(flow_name, echo, datastore):
|
|
|
180
243
|
parameter_name=None,
|
|
181
244
|
logger=echo,
|
|
182
245
|
ds_type=datastore.TYPE,
|
|
246
|
+
configs=ConfigValue(dict(configs)),
|
|
183
247
|
)
|
|
184
248
|
|
|
185
249
|
|
|
@@ -236,7 +300,11 @@ class Parameter(object):
|
|
|
236
300
|
----------
|
|
237
301
|
name : str
|
|
238
302
|
User-visible parameter name.
|
|
239
|
-
default : str
|
|
303
|
+
default : Union[str, float, int, bool, Dict[str, Any],
|
|
304
|
+
Callable[
|
|
305
|
+
[ParameterContext], Union[str, float, int, bool, Dict[str, Any]]
|
|
306
|
+
],
|
|
307
|
+
], optional, default None
|
|
240
308
|
Default value for the parameter. Use a special `JSONType` class to
|
|
241
309
|
indicate that the value must be a valid JSON object. A function
|
|
242
310
|
implies that the parameter corresponds to a *deploy-time parameter*.
|
|
@@ -245,15 +313,19 @@ class Parameter(object):
|
|
|
245
313
|
If `default` is not specified, define the parameter type. Specify
|
|
246
314
|
one of `str`, `float`, `int`, `bool`, or `JSONType`. If None, defaults
|
|
247
315
|
to the type of `default` or `str` if none specified.
|
|
248
|
-
help : str, optional
|
|
316
|
+
help : str, optional, default None
|
|
249
317
|
Help text to show in `run --help`.
|
|
250
|
-
required : bool, default
|
|
251
|
-
Require that the user
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
318
|
+
required : bool, optional, default None
|
|
319
|
+
Require that the user specifies a value for the parameter. Note that if
|
|
320
|
+
a default is provide, the required flag is ignored.
|
|
321
|
+
A value of None is equivalent to False.
|
|
322
|
+
show_default : bool, optional, default None
|
|
323
|
+
If True, show the default value in the help text. A value of None is equivalent
|
|
324
|
+
to True.
|
|
255
325
|
"""
|
|
256
326
|
|
|
327
|
+
IS_CONFIG_PARAMETER = False
|
|
328
|
+
|
|
257
329
|
def __init__(
|
|
258
330
|
self,
|
|
259
331
|
name: str,
|
|
@@ -264,31 +336,62 @@ class Parameter(object):
|
|
|
264
336
|
int,
|
|
265
337
|
bool,
|
|
266
338
|
Dict[str, Any],
|
|
267
|
-
Callable[
|
|
339
|
+
Callable[
|
|
340
|
+
[ParameterContext], Union[str, float, int, bool, Dict[str, Any]]
|
|
341
|
+
],
|
|
268
342
|
]
|
|
269
343
|
] = None,
|
|
270
344
|
type: Optional[
|
|
271
345
|
Union[Type[str], Type[float], Type[int], Type[bool], JSONTypeClass]
|
|
272
346
|
] = None,
|
|
273
347
|
help: Optional[str] = None,
|
|
274
|
-
required: bool =
|
|
275
|
-
show_default: bool =
|
|
348
|
+
required: Optional[bool] = None,
|
|
349
|
+
show_default: Optional[bool] = None,
|
|
276
350
|
**kwargs: Dict[str, Any]
|
|
277
351
|
):
|
|
278
352
|
self.name = name
|
|
279
353
|
self.kwargs = kwargs
|
|
280
|
-
|
|
354
|
+
self._override_kwargs = {
|
|
281
355
|
"default": default,
|
|
282
356
|
"type": type,
|
|
283
357
|
"help": help,
|
|
284
358
|
"required": required,
|
|
285
359
|
"show_default": show_default,
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
def init(self, ignore_errors=False):
|
|
363
|
+
# Prevent circular import
|
|
364
|
+
from .user_configs.config_parameters import (
|
|
365
|
+
resolve_delayed_evaluator,
|
|
366
|
+
unpack_delayed_evaluator,
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
# Resolve any value from configurations
|
|
370
|
+
self.kwargs, _ = unpack_delayed_evaluator(
|
|
371
|
+
self.kwargs, ignore_errors=ignore_errors
|
|
372
|
+
)
|
|
373
|
+
# Do it one item at a time so errors are ignored at that level (as opposed to
|
|
374
|
+
# at the entire kwargs level)
|
|
375
|
+
self.kwargs = {
|
|
376
|
+
k: resolve_delayed_evaluator(v, ignore_errors=ignore_errors, to_dict=True)
|
|
377
|
+
for k, v in self.kwargs.items()
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
# This was the behavior before configs: values specified in args would override
|
|
381
|
+
# stuff in kwargs which is what we implement here as well
|
|
382
|
+
for key, value in self._override_kwargs.items():
|
|
383
|
+
if value is not None:
|
|
384
|
+
self.kwargs[key] = resolve_delayed_evaluator(
|
|
385
|
+
value, ignore_errors=ignore_errors, to_dict=True
|
|
386
|
+
)
|
|
387
|
+
# Set two default values if no-one specified them
|
|
388
|
+
self.kwargs.setdefault("required", False)
|
|
389
|
+
self.kwargs.setdefault("show_default", True)
|
|
390
|
+
|
|
391
|
+
# Continue processing kwargs free of any configuration values :)
|
|
289
392
|
|
|
290
393
|
# TODO: check that the type is one of the supported types
|
|
291
|
-
param_type = self.kwargs["type"] = self._get_type(kwargs)
|
|
394
|
+
param_type = self.kwargs["type"] = self._get_type(self.kwargs)
|
|
292
395
|
|
|
293
396
|
reserved_params = [
|
|
294
397
|
"params",
|
|
@@ -313,23 +416,27 @@ class Parameter(object):
|
|
|
313
416
|
raise MetaflowException(
|
|
314
417
|
"Parameter name '%s' is a reserved "
|
|
315
418
|
"word. Please use a different "
|
|
316
|
-
"name for your parameter." % (name)
|
|
419
|
+
"name for your parameter." % (self.name)
|
|
317
420
|
)
|
|
318
421
|
|
|
319
422
|
# make sure the user is not trying to pass a function in one of the
|
|
320
423
|
# fields that don't support function-values yet
|
|
321
424
|
for field in ("show_default", "separator", "required"):
|
|
322
|
-
if callable(kwargs.get(field)):
|
|
425
|
+
if callable(self.kwargs.get(field)):
|
|
323
426
|
raise MetaflowException(
|
|
324
427
|
"Parameter *%s*: Field '%s' cannot "
|
|
325
|
-
"have a function as its value" % (name, field)
|
|
428
|
+
"have a function as its value" % (self.name, field)
|
|
326
429
|
)
|
|
327
430
|
|
|
328
431
|
# default can be defined as a function
|
|
329
432
|
default_field = self.kwargs.get("default")
|
|
330
433
|
if callable(default_field) and not isinstance(default_field, DeployTimeField):
|
|
331
434
|
self.kwargs["default"] = DeployTimeField(
|
|
332
|
-
|
|
435
|
+
self.name,
|
|
436
|
+
param_type,
|
|
437
|
+
"default",
|
|
438
|
+
self.kwargs["default"],
|
|
439
|
+
return_str=True,
|
|
333
440
|
)
|
|
334
441
|
|
|
335
442
|
# note that separator doesn't work with DeployTimeFields unless you
|
|
@@ -338,7 +445,7 @@ class Parameter(object):
|
|
|
338
445
|
if self.separator and not self.is_string_type:
|
|
339
446
|
raise MetaflowException(
|
|
340
447
|
"Parameter *%s*: Separator is only allowed "
|
|
341
|
-
"for string parameters." % name
|
|
448
|
+
"for string parameters." % self.name
|
|
342
449
|
)
|
|
343
450
|
|
|
344
451
|
def __repr__(self):
|
|
@@ -388,11 +495,25 @@ def add_custom_parameters(deploy_mode=False):
|
|
|
388
495
|
# deploy_mode determines whether deploy-time functions should or should
|
|
389
496
|
# not be evaluated for this command
|
|
390
497
|
def wrapper(cmd):
|
|
498
|
+
# Save the original params once, if they haven't been saved before.
|
|
499
|
+
if not hasattr(cmd, "original_params"):
|
|
500
|
+
cmd.original_params = list(cmd.params)
|
|
501
|
+
|
|
502
|
+
cmd.has_flow_params = True
|
|
391
503
|
# Iterate over parameters in reverse order so cmd.params lists options
|
|
392
504
|
# in the order they are defined in the FlowSpec subclass
|
|
505
|
+
flow_cls = getattr(current_flow, "flow_cls", None)
|
|
506
|
+
if flow_cls is None:
|
|
507
|
+
return cmd
|
|
508
|
+
parameters = [
|
|
509
|
+
p for _, p in flow_cls._get_parameters() if not p.IS_CONFIG_PARAMETER
|
|
510
|
+
]
|
|
393
511
|
for arg in parameters[::-1]:
|
|
394
512
|
kwargs = arg.option_kwargs(deploy_mode)
|
|
395
513
|
cmd.params.insert(0, click.Option(("--" + arg.name,), **kwargs))
|
|
396
514
|
return cmd
|
|
397
515
|
|
|
398
516
|
return wrapper
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
JSONType = JSONTypeClass()
|
metaflow/plugins/__init__.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
1
3
|
from metaflow.extension_support.plugins import (
|
|
2
4
|
merge_lists,
|
|
3
5
|
process_plugins,
|
|
@@ -14,8 +16,15 @@ CLIS_DESC = [
|
|
|
14
16
|
("argo-workflows", ".argo.argo_workflows_cli.cli"),
|
|
15
17
|
("card", ".cards.card_cli.cli"),
|
|
16
18
|
("tag", ".tag_cli.cli"),
|
|
19
|
+
("spot-metadata", ".kubernetes.spot_metadata_cli.cli"),
|
|
20
|
+
("logs", ".logs_cli.cli"),
|
|
17
21
|
]
|
|
18
22
|
|
|
23
|
+
# Add additional commands to the runner here
|
|
24
|
+
# These will be accessed using Runner().<command>()
|
|
25
|
+
RUNNER_CLIS_DESC = []
|
|
26
|
+
|
|
27
|
+
|
|
19
28
|
from .test_unbounded_foreach_decorator import InternalTestUnboundedForeachInput
|
|
20
29
|
|
|
21
30
|
# Add new step decorators here
|
|
@@ -60,35 +69,51 @@ FLOW_DECORATORS_DESC = [
|
|
|
60
69
|
("trigger_on_finish", ".events_decorator.TriggerOnFinishDecorator"),
|
|
61
70
|
("pypi_base", ".pypi.pypi_decorator.PyPIFlowDecorator"),
|
|
62
71
|
("conda_base", ".pypi.conda_decorator.CondaFlowDecorator"),
|
|
72
|
+
("exit_hook", ".exit_hook.exit_hook_decorator.ExitHookDecorator"),
|
|
63
73
|
]
|
|
64
74
|
|
|
65
75
|
# Add environments here
|
|
66
76
|
ENVIRONMENTS_DESC = [
|
|
67
77
|
("conda", ".pypi.conda_environment.CondaEnvironment"),
|
|
68
78
|
("pypi", ".pypi.pypi_environment.PyPIEnvironment"),
|
|
79
|
+
("uv", ".uv.uv_environment.UVEnvironment"),
|
|
69
80
|
]
|
|
70
81
|
|
|
71
82
|
# Add metadata providers here
|
|
72
83
|
METADATA_PROVIDERS_DESC = [
|
|
73
|
-
("service", ".
|
|
74
|
-
("local", ".
|
|
84
|
+
("service", ".metadata_providers.service.ServiceMetadataProvider"),
|
|
85
|
+
("local", ".metadata_providers.local.LocalMetadataProvider"),
|
|
86
|
+
("spin", ".metadata_providers.spin.SpinMetadataProvider"),
|
|
75
87
|
]
|
|
76
88
|
|
|
77
89
|
# Add datastore here
|
|
78
90
|
DATASTORES_DESC = [
|
|
79
91
|
("local", ".datastores.local_storage.LocalStorage"),
|
|
92
|
+
("spin", ".datastores.spin_storage.SpinStorage"),
|
|
80
93
|
("s3", ".datastores.s3_storage.S3Storage"),
|
|
81
94
|
("azure", ".datastores.azure_storage.AzureStorage"),
|
|
82
95
|
("gs", ".datastores.gs_storage.GSStorage"),
|
|
83
96
|
]
|
|
84
97
|
|
|
98
|
+
# Dataclients are used for IncludeFile
|
|
99
|
+
DATACLIENTS_DESC = [
|
|
100
|
+
("local", ".datatools.Local"),
|
|
101
|
+
("s3", ".datatools.S3"),
|
|
102
|
+
("azure", ".azure.includefile_support.Azure"),
|
|
103
|
+
("gs", ".gcp.includefile_support.GS"),
|
|
104
|
+
]
|
|
105
|
+
|
|
85
106
|
# Add non monitoring/logging sidecars here
|
|
86
107
|
SIDECARS_DESC = [
|
|
87
108
|
(
|
|
88
109
|
"save_logs_periodically",
|
|
89
110
|
"..mflog.save_logs_periodically.SaveLogsPeriodicallySidecar",
|
|
90
111
|
),
|
|
91
|
-
(
|
|
112
|
+
(
|
|
113
|
+
"spot_termination_monitor",
|
|
114
|
+
".kubernetes.spot_monitor_sidecar.SpotTerminationMonitorSidecar",
|
|
115
|
+
),
|
|
116
|
+
("heartbeat", "metaflow.metadata_provider.heartbeat.MetadataHeartBeat"),
|
|
92
117
|
]
|
|
93
118
|
|
|
94
119
|
# Add logging sidecars here
|
|
@@ -124,16 +149,34 @@ SECRETS_PROVIDERS_DESC = [
|
|
|
124
149
|
"gcp-secret-manager",
|
|
125
150
|
".gcp.gcp_secret_manager_secrets_provider.GcpSecretManagerSecretsProvider",
|
|
126
151
|
),
|
|
152
|
+
(
|
|
153
|
+
"az-key-vault",
|
|
154
|
+
".azure.azure_secret_manager_secrets_provider.AzureKeyVaultSecretsProvider",
|
|
155
|
+
),
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
GCP_CLIENT_PROVIDERS_DESC = [
|
|
159
|
+
("gcp-default", ".gcp.gs_storage_client_factory.GcpDefaultClientProvider")
|
|
127
160
|
]
|
|
128
161
|
|
|
129
162
|
AZURE_CLIENT_PROVIDERS_DESC = [
|
|
130
163
|
("azure-default", ".azure.azure_credential.AzureDefaultClientProvider")
|
|
131
164
|
]
|
|
132
165
|
|
|
133
|
-
|
|
134
|
-
("
|
|
166
|
+
DEPLOYER_IMPL_PROVIDERS_DESC = [
|
|
167
|
+
("argo-workflows", ".argo.argo_workflows_deployer.ArgoWorkflowsDeployer"),
|
|
168
|
+
(
|
|
169
|
+
"step-functions",
|
|
170
|
+
".aws.step_functions.step_functions_deployer.StepFunctionsDeployer",
|
|
171
|
+
),
|
|
135
172
|
]
|
|
136
173
|
|
|
174
|
+
TL_PLUGINS_DESC = [
|
|
175
|
+
("yaml_parser", ".parsers.yaml_parser"),
|
|
176
|
+
("requirements_txt_parser", ".pypi.parsers.requirements_txt_parser"),
|
|
177
|
+
("pyproject_toml_parser", ".pypi.parsers.pyproject_toml_parser"),
|
|
178
|
+
("conda_environment_yml_parser", ".pypi.parsers.conda_environment_yml_parser"),
|
|
179
|
+
]
|
|
137
180
|
|
|
138
181
|
process_plugins(globals())
|
|
139
182
|
|
|
@@ -142,11 +185,24 @@ def get_plugin_cli():
|
|
|
142
185
|
return resolve_plugins("cli")
|
|
143
186
|
|
|
144
187
|
|
|
188
|
+
def get_plugin_cli_path():
|
|
189
|
+
return resolve_plugins("cli", path_only=True)
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def get_runner_cli():
|
|
193
|
+
return resolve_plugins("runner_cli")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def get_runner_cli_path():
|
|
197
|
+
return resolve_plugins("runner_cli", path_only=True)
|
|
198
|
+
|
|
199
|
+
|
|
145
200
|
STEP_DECORATORS = resolve_plugins("step_decorator")
|
|
146
201
|
FLOW_DECORATORS = resolve_plugins("flow_decorator")
|
|
147
202
|
ENVIRONMENTS = resolve_plugins("environment")
|
|
148
203
|
METADATA_PROVIDERS = resolve_plugins("metadata_provider")
|
|
149
204
|
DATASTORES = resolve_plugins("datastore")
|
|
205
|
+
DATACLIENTS = resolve_plugins("dataclient")
|
|
150
206
|
SIDECARS = resolve_plugins("sidecar")
|
|
151
207
|
LOGGING_SIDECARS = resolve_plugins("logging_sidecar")
|
|
152
208
|
MONITOR_SIDECARS = resolve_plugins("monitor_sidecar")
|
|
@@ -159,6 +215,11 @@ SECRETS_PROVIDERS = resolve_plugins("secrets_provider")
|
|
|
159
215
|
AZURE_CLIENT_PROVIDERS = resolve_plugins("azure_client_provider")
|
|
160
216
|
GCP_CLIENT_PROVIDERS = resolve_plugins("gcp_client_provider")
|
|
161
217
|
|
|
218
|
+
if sys.version_info >= (3, 7):
|
|
219
|
+
DEPLOYER_IMPL_PROVIDERS = resolve_plugins("deployer_impl_provider")
|
|
220
|
+
|
|
221
|
+
TL_PLUGINS = resolve_plugins("tl_plugin")
|
|
222
|
+
|
|
162
223
|
from .cards.card_modules import MF_EXTERNAL_CARDS
|
|
163
224
|
|
|
164
225
|
# Cards; due to the way cards were designed, it is harder to make them fit
|
|
@@ -183,6 +244,7 @@ from .cards.card_modules.test_cards import (
|
|
|
183
244
|
TestTimeoutCard,
|
|
184
245
|
TestRefreshCard,
|
|
185
246
|
TestRefreshComponentCard,
|
|
247
|
+
TestImageCard,
|
|
186
248
|
)
|
|
187
249
|
|
|
188
250
|
CARDS = [
|
|
@@ -201,5 +263,12 @@ CARDS = [
|
|
|
201
263
|
DefaultCardJSON,
|
|
202
264
|
TestRefreshCard,
|
|
203
265
|
TestRefreshComponentCard,
|
|
266
|
+
TestImageCard,
|
|
204
267
|
]
|
|
205
268
|
merge_lists(CARDS, MF_EXTERNAL_CARDS, "type")
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def _import_tl_plugins(globals_dict):
|
|
272
|
+
|
|
273
|
+
for name, p in TL_PLUGINS.items():
|
|
274
|
+
globals_dict[name] = p
|
|
@@ -32,6 +32,7 @@ from metaflow.metaflow_config import (
|
|
|
32
32
|
S3_ENDPOINT_URL,
|
|
33
33
|
SERVICE_HEADERS,
|
|
34
34
|
SERVICE_INTERNAL_URL,
|
|
35
|
+
AZURE_KEY_VAULT_PREFIX,
|
|
35
36
|
)
|
|
36
37
|
|
|
37
38
|
from metaflow.metaflow_config_funcs import config_values
|
|
@@ -45,6 +46,7 @@ from metaflow.parameters import (
|
|
|
45
46
|
# TODO: Move chevron to _vendor
|
|
46
47
|
from metaflow.plugins.cards.card_modules import chevron
|
|
47
48
|
from metaflow.plugins.kubernetes.kubernetes import Kubernetes
|
|
49
|
+
from metaflow.plugins.kubernetes.kube_utils import qos_requests_and_limits
|
|
48
50
|
from metaflow.plugins.timeout_decorator import get_run_time_limit_for_task
|
|
49
51
|
from metaflow.util import compress_list, dict_to_cli_options, get_username
|
|
50
52
|
|
|
@@ -64,6 +66,7 @@ class Airflow(object):
|
|
|
64
66
|
name,
|
|
65
67
|
graph,
|
|
66
68
|
flow,
|
|
69
|
+
code_package_metadata,
|
|
67
70
|
code_package_sha,
|
|
68
71
|
code_package_url,
|
|
69
72
|
metadata,
|
|
@@ -85,6 +88,7 @@ class Airflow(object):
|
|
|
85
88
|
self.name = name
|
|
86
89
|
self.graph = graph
|
|
87
90
|
self.flow = flow
|
|
91
|
+
self.code_package_metadata = code_package_metadata
|
|
88
92
|
self.code_package_sha = code_package_sha
|
|
89
93
|
self.code_package_url = code_package_url
|
|
90
94
|
self.metadata = metadata
|
|
@@ -370,6 +374,7 @@ class Airflow(object):
|
|
|
370
374
|
# Technically the "user" is the stakeholder but should these labels be present.
|
|
371
375
|
}
|
|
372
376
|
additional_mf_variables = {
|
|
377
|
+
"METAFLOW_CODE_METADATA": self.code_package_metadata,
|
|
373
378
|
"METAFLOW_CODE_SHA": self.code_package_sha,
|
|
374
379
|
"METAFLOW_CODE_URL": self.code_package_url,
|
|
375
380
|
"METAFLOW_CODE_DS": self.flow_datastore.TYPE,
|
|
@@ -398,20 +403,23 @@ class Airflow(object):
|
|
|
398
403
|
"METAFLOW_CARD_GSROOT": CARD_GSROOT,
|
|
399
404
|
"METAFLOW_S3_ENDPOINT_URL": S3_ENDPOINT_URL,
|
|
400
405
|
}
|
|
401
|
-
env[
|
|
402
|
-
|
|
403
|
-
|
|
406
|
+
env["METAFLOW_AZURE_STORAGE_BLOB_SERVICE_ENDPOINT"] = (
|
|
407
|
+
AZURE_STORAGE_BLOB_SERVICE_ENDPOINT
|
|
408
|
+
)
|
|
404
409
|
env["METAFLOW_DATASTORE_SYSROOT_AZURE"] = DATASTORE_SYSROOT_AZURE
|
|
405
410
|
env["METAFLOW_CARD_AZUREROOT"] = CARD_AZUREROOT
|
|
406
411
|
if DEFAULT_SECRETS_BACKEND_TYPE:
|
|
407
412
|
env["METAFLOW_DEFAULT_SECRETS_BACKEND_TYPE"] = DEFAULT_SECRETS_BACKEND_TYPE
|
|
408
413
|
if AWS_SECRETS_MANAGER_DEFAULT_REGION:
|
|
409
|
-
env[
|
|
410
|
-
|
|
411
|
-
|
|
414
|
+
env["METAFLOW_AWS_SECRETS_MANAGER_DEFAULT_REGION"] = (
|
|
415
|
+
AWS_SECRETS_MANAGER_DEFAULT_REGION
|
|
416
|
+
)
|
|
412
417
|
if GCP_SECRET_MANAGER_PREFIX:
|
|
413
418
|
env["METAFLOW_GCP_SECRET_MANAGER_PREFIX"] = GCP_SECRET_MANAGER_PREFIX
|
|
414
419
|
|
|
420
|
+
if AZURE_KEY_VAULT_PREFIX:
|
|
421
|
+
env["METAFLOW_AZURE_KEY_VAULT_PREFIX"] = AZURE_KEY_VAULT_PREFIX
|
|
422
|
+
|
|
415
423
|
env.update(additional_mf_variables)
|
|
416
424
|
|
|
417
425
|
service_account = (
|
|
@@ -424,25 +432,25 @@ class Airflow(object):
|
|
|
424
432
|
if k8s_deco.attributes["namespace"] is not None
|
|
425
433
|
else "default"
|
|
426
434
|
)
|
|
427
|
-
|
|
435
|
+
qos_requests, qos_limits = qos_requests_and_limits(
|
|
436
|
+
k8s_deco.attributes["qos"],
|
|
437
|
+
k8s_deco.attributes["cpu"],
|
|
438
|
+
k8s_deco.attributes["memory"],
|
|
439
|
+
k8s_deco.attributes["disk"],
|
|
440
|
+
)
|
|
428
441
|
resources = dict(
|
|
429
|
-
requests=
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
442
|
+
requests=qos_requests,
|
|
443
|
+
limits={
|
|
444
|
+
**qos_limits,
|
|
445
|
+
**{
|
|
446
|
+
"%s.com/gpu".lower()
|
|
447
|
+
% k8s_deco.attributes["gpu_vendor"]: str(k8s_deco.attributes["gpu"])
|
|
448
|
+
for k in [0]
|
|
449
|
+
# Don't set GPU limits if gpu isn't specified.
|
|
450
|
+
if k8s_deco.attributes["gpu"] is not None
|
|
451
|
+
},
|
|
452
|
+
},
|
|
434
453
|
)
|
|
435
|
-
if k8s_deco.attributes["gpu"] is not None:
|
|
436
|
-
resources.update(
|
|
437
|
-
dict(
|
|
438
|
-
limits={
|
|
439
|
-
"%s.com/gpu".lower()
|
|
440
|
-
% k8s_deco.attributes["gpu_vendor"]: str(
|
|
441
|
-
k8s_deco.attributes["gpu"]
|
|
442
|
-
)
|
|
443
|
-
}
|
|
444
|
-
)
|
|
445
|
-
)
|
|
446
454
|
|
|
447
455
|
annotations = {
|
|
448
456
|
"metaflow/production_token": self.production_token,
|
|
@@ -471,6 +479,7 @@ class Airflow(object):
|
|
|
471
479
|
node.name,
|
|
472
480
|
AIRFLOW_MACROS.create_task_id(self.contains_foreach),
|
|
473
481
|
AIRFLOW_MACROS.ATTEMPT,
|
|
482
|
+
code_package_metadata=self.code_package_metadata,
|
|
474
483
|
code_package_url=self.code_package_url,
|
|
475
484
|
step_cmds=self._step_cli(
|
|
476
485
|
node, input_paths, self.code_package_url, user_code_retries
|
|
@@ -529,13 +538,13 @@ class Airflow(object):
|
|
|
529
538
|
"with": [
|
|
530
539
|
decorator.make_decorator_spec()
|
|
531
540
|
for decorator in node.decorators
|
|
532
|
-
if not decorator.statically_defined
|
|
541
|
+
if not decorator.statically_defined and decorator.inserted_by is None
|
|
533
542
|
]
|
|
534
543
|
}
|
|
535
544
|
# FlowDecorators can define their own top-level options. They are
|
|
536
545
|
# responsible for adding their own top-level options and values through
|
|
537
546
|
# the get_top_level_options() hook. See similar logic in runtime.py.
|
|
538
|
-
for deco in flow_decorators():
|
|
547
|
+
for deco in flow_decorators(self.flow):
|
|
539
548
|
top_opts_dict.update(deco.get_top_level_options())
|
|
540
549
|
|
|
541
550
|
top_opts = list(dict_to_cli_options(top_opts_dict))
|
|
@@ -649,6 +658,12 @@ class Airflow(object):
|
|
|
649
658
|
"to Airflow is not supported currently."
|
|
650
659
|
)
|
|
651
660
|
|
|
661
|
+
if self.flow._flow_decorators.get("exit_hook"):
|
|
662
|
+
raise AirflowException(
|
|
663
|
+
"Deploying flows with the @exit_hook decorator "
|
|
664
|
+
"to Airflow is not currently supported."
|
|
665
|
+
)
|
|
666
|
+
|
|
652
667
|
# Visit every node of the flow and recursively build the state machine.
|
|
653
668
|
def _visit(node, workflow, exit_node=None):
|
|
654
669
|
kube_deco = dict(
|