metaflow 2.15.15__py2.py3-none-any.whl → 2.15.17__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/cli.py +2 -2
- metaflow/cli_components/run_cmds.py +1 -1
- metaflow/cmd/develop/stub_generator.py +30 -16
- metaflow/flowspec.py +16 -4
- metaflow/metaflow_config.py +2 -0
- metaflow/plugins/argo/argo_workflows.py +7 -0
- metaflow/plugins/argo/argo_workflows_deployer_objects.py +6 -49
- metaflow/plugins/aws/aws_client.py +6 -0
- metaflow/plugins/datatools/s3/s3op.py +1 -1
- metaflow/plugins/kubernetes/kubernetes.py +4 -0
- metaflow/plugins/kubernetes/kubernetes_cli.py +8 -0
- metaflow/plugins/kubernetes/kubernetes_decorator.py +11 -0
- metaflow/plugins/kubernetes/kubernetes_job.py +4 -2
- metaflow/plugins/kubernetes/kubernetes_jobsets.py +5 -2
- metaflow/plugins/metadata_providers/service.py +12 -8
- metaflow/runner/deployer.py +49 -0
- metaflow/user_configs/config_decorators.py +1 -1
- metaflow/user_configs/config_options.py +6 -2
- metaflow/version.py +1 -1
- {metaflow-2.15.15.dist-info → metaflow-2.15.17.dist-info}/METADATA +2 -2
- {metaflow-2.15.15.dist-info → metaflow-2.15.17.dist-info}/RECORD +28 -28
- {metaflow-2.15.15.data → metaflow-2.15.17.data}/data/share/metaflow/devtools/Makefile +0 -0
- {metaflow-2.15.15.data → metaflow-2.15.17.data}/data/share/metaflow/devtools/Tiltfile +0 -0
- {metaflow-2.15.15.data → metaflow-2.15.17.data}/data/share/metaflow/devtools/pick_services.sh +0 -0
- {metaflow-2.15.15.dist-info → metaflow-2.15.17.dist-info}/WHEEL +0 -0
- {metaflow-2.15.15.dist-info → metaflow-2.15.17.dist-info}/entry_points.txt +0 -0
- {metaflow-2.15.15.dist-info → metaflow-2.15.17.dist-info}/licenses/LICENSE +0 -0
- {metaflow-2.15.15.dist-info → metaflow-2.15.17.dist-info}/top_level.txt +0 -0
metaflow/cli.py
CHANGED
@@ -496,7 +496,7 @@ def start(
|
|
496
496
|
ctx.obj.echo,
|
497
497
|
ctx.obj.flow_datastore,
|
498
498
|
{
|
499
|
-
k: ConfigValue(v)
|
499
|
+
k: ConfigValue(v) if v is not None else None
|
500
500
|
for k, v in ctx.obj.flow.__class__._flow_state.get(
|
501
501
|
_FlowState.CONFIGS, {}
|
502
502
|
).items()
|
@@ -524,7 +524,7 @@ def start(
|
|
524
524
|
decorators._attach_decorators(ctx.obj.flow, all_decospecs)
|
525
525
|
decorators._init(ctx.obj.flow)
|
526
526
|
# Regenerate graph if we attached more decorators
|
527
|
-
ctx.obj.flow.__class__.
|
527
|
+
ctx.obj.flow.__class__._init_graph()
|
528
528
|
ctx.obj.graph = ctx.obj.flow._graph
|
529
529
|
|
530
530
|
decorators._init_step_decorators(
|
@@ -45,7 +45,7 @@ def before_run(obj, tags, decospecs):
|
|
45
45
|
decorators._attach_decorators(obj.flow, all_decospecs)
|
46
46
|
decorators._init(obj.flow)
|
47
47
|
# Regenerate graph if we attached more decorators
|
48
|
-
obj.flow.__class__.
|
48
|
+
obj.flow.__class__._init_graph()
|
49
49
|
obj.graph = obj.flow._graph
|
50
50
|
|
51
51
|
obj.check(obj.graph, obj.flow, obj.environment, pylint=obj.pylint)
|
@@ -488,9 +488,6 @@ class StubGenerator:
|
|
488
488
|
self._imports.add(name)
|
489
489
|
|
490
490
|
def _add_to_typing_check(name, is_module=False):
|
491
|
-
# if name != self._current_module_name:
|
492
|
-
# self._typing_imports.add(name)
|
493
|
-
#
|
494
491
|
if name == "None":
|
495
492
|
return
|
496
493
|
if is_module:
|
@@ -504,6 +501,24 @@ class StubGenerator:
|
|
504
501
|
# the current file
|
505
502
|
self._typing_imports.add(splits[0])
|
506
503
|
|
504
|
+
def _format_qualified_class_name(cls: type) -> str:
|
505
|
+
"""Helper to format a class with its qualified module name"""
|
506
|
+
# Special case for NoneType - return None
|
507
|
+
if cls.__name__ == "NoneType":
|
508
|
+
return "None"
|
509
|
+
|
510
|
+
module = inspect.getmodule(cls)
|
511
|
+
if (
|
512
|
+
module
|
513
|
+
and module.__name__ != "builtins"
|
514
|
+
and module.__name__ != "__main__"
|
515
|
+
):
|
516
|
+
module_name = self._get_module_name_alias(module.__name__)
|
517
|
+
_add_to_typing_check(module_name, is_module=True)
|
518
|
+
return f"{module_name}.{cls.__name__}"
|
519
|
+
else:
|
520
|
+
return cls.__name__
|
521
|
+
|
507
522
|
if isinstance(element, str):
|
508
523
|
# Special case for self referential things (particularly in a class)
|
509
524
|
if element == self._current_name:
|
@@ -557,19 +572,15 @@ class StubGenerator:
|
|
557
572
|
return element.__name__
|
558
573
|
elif isinstance(element, type(Ellipsis)):
|
559
574
|
return "..."
|
560
|
-
# elif (
|
561
|
-
# isinstance(element, typing._GenericAlias)
|
562
|
-
# and hasattr(element, "_name")
|
563
|
-
# and element._name in ("List", "Tuple", "Dict", "Set")
|
564
|
-
# ):
|
565
|
-
# # 3.7 has these as _GenericAlias but they don't behave like the ones in 3.10
|
566
|
-
# _add_to_import("typing")
|
567
|
-
# return str(element)
|
568
575
|
elif isinstance(element, typing._GenericAlias):
|
569
576
|
# We need to check things recursively in __args__ if it exists
|
570
577
|
args_str = []
|
571
578
|
for arg in getattr(element, "__args__", []):
|
572
|
-
|
579
|
+
# Special handling for class objects in type arguments
|
580
|
+
if isinstance(arg, type):
|
581
|
+
args_str.append(_format_qualified_class_name(arg))
|
582
|
+
else:
|
583
|
+
args_str.append(self._get_element_name_with_module(arg))
|
573
584
|
|
574
585
|
_add_to_import("typing")
|
575
586
|
if element._name:
|
@@ -584,12 +595,15 @@ class StubGenerator:
|
|
584
595
|
args_str = [call_args, args_str[-1]]
|
585
596
|
return "typing.%s[%s]" % (element._name, ", ".join(args_str))
|
586
597
|
else:
|
587
|
-
|
598
|
+
# Handle the case where we have a generic type without a _name
|
599
|
+
origin = element.__origin__
|
600
|
+
if isinstance(origin, type):
|
601
|
+
origin_str = _format_qualified_class_name(origin)
|
602
|
+
else:
|
603
|
+
origin_str = str(origin)
|
604
|
+
return "%s[%s]" % (origin_str, ", ".join(args_str))
|
588
605
|
elif isinstance(element, ForwardRef):
|
589
606
|
f_arg = self._get_module_name_alias(element.__forward_arg__)
|
590
|
-
# if f_arg in ("Run", "Task"): # HACK -- forward references in current.py
|
591
|
-
# _add_to_import("metaflow")
|
592
|
-
# f_arg = "metaflow.%s" % f_arg
|
593
607
|
_add_to_typing_check(f_arg)
|
594
608
|
return '"%s"' % f_arg
|
595
609
|
elif inspect.getmodule(element) == inspect.getmodule(typing):
|
metaflow/flowspec.py
CHANGED
@@ -87,6 +87,9 @@ class FlowSpecMeta(type):
|
|
87
87
|
if name == "FlowSpec":
|
88
88
|
return
|
89
89
|
|
90
|
+
cls._init_attrs()
|
91
|
+
|
92
|
+
def _init_attrs(cls):
|
90
93
|
from .decorators import (
|
91
94
|
DuplicateFlowDecoratorException,
|
92
95
|
) # Prevent circular import
|
@@ -103,6 +106,12 @@ class FlowSpecMeta(type):
|
|
103
106
|
# Keys are _FlowState enum values
|
104
107
|
cls._flow_state = {}
|
105
108
|
|
109
|
+
# Keep track if configs have been processed -- this is particularly applicable
|
110
|
+
# for the Runner/Deployer where calling multiple APIs on the same flow could
|
111
|
+
# cause the configs to be processed multiple times. For a given flow, once
|
112
|
+
# the configs have been processed, we do not process them again.
|
113
|
+
cls._configs_processed = False
|
114
|
+
|
106
115
|
# We inherit stuff from our parent classes as well -- we need to be careful
|
107
116
|
# in terms of the order; we will follow the MRO with the following rules:
|
108
117
|
# - decorators (cls._flow_decorators) will cause an error if they do not
|
@@ -127,10 +136,9 @@ class FlowSpecMeta(type):
|
|
127
136
|
cls._flow_state.setdefault(_FlowState.CONFIG_DECORATORS, []).extend(
|
128
137
|
base_configs
|
129
138
|
)
|
139
|
+
cls._init_graph()
|
130
140
|
|
131
|
-
|
132
|
-
|
133
|
-
def _init_attrs(cls):
|
141
|
+
def _init_graph(cls):
|
134
142
|
# Graph and steps are specific to the class -- store here so we can access
|
135
143
|
# in class method _process_config_decorators
|
136
144
|
cls._graph = FlowGraph(cls)
|
@@ -225,6 +233,10 @@ class FlowSpec(metaclass=FlowSpecMeta):
|
|
225
233
|
@classmethod
|
226
234
|
def _process_config_decorators(cls, config_options, process_configs=True):
|
227
235
|
|
236
|
+
if cls._configs_processed:
|
237
|
+
return None
|
238
|
+
cls._configs_processed = True
|
239
|
+
|
228
240
|
# Fast path for no user configurations
|
229
241
|
if not process_configs or (
|
230
242
|
not cls._flow_state.get(_FlowState.CONFIG_DECORATORS)
|
@@ -325,7 +337,7 @@ class FlowSpec(metaclass=FlowSpecMeta):
|
|
325
337
|
parameters.replace_flow_context(cls)
|
326
338
|
|
327
339
|
# Re-calculate class level attributes after modifying the class
|
328
|
-
cls.
|
340
|
+
cls._init_graph()
|
329
341
|
return cls
|
330
342
|
|
331
343
|
def _set_constants(self, graph, kwargs, config_options):
|
metaflow/metaflow_config.py
CHANGED
@@ -370,6 +370,8 @@ KUBERNETES_CONTAINER_IMAGE = from_conf(
|
|
370
370
|
)
|
371
371
|
# Image pull policy for container images
|
372
372
|
KUBERNETES_IMAGE_PULL_POLICY = from_conf("KUBERNETES_IMAGE_PULL_POLICY", None)
|
373
|
+
# Image pull secrets for container images
|
374
|
+
KUBERNETES_IMAGE_PULL_SECRETS = from_conf("KUBERNETES_IMAGE_PULL_SECRETS", "")
|
373
375
|
# Default container registry for K8S
|
374
376
|
KUBERNETES_CONTAINER_REGISTRY = from_conf(
|
375
377
|
"KUBERNETES_CONTAINER_REGISTRY", DEFAULT_CONTAINER_REGISTRY
|
@@ -2007,6 +2007,7 @@ class ArgoWorkflows(object):
|
|
2007
2007
|
namespace=resources["namespace"],
|
2008
2008
|
image=resources["image"],
|
2009
2009
|
image_pull_policy=resources["image_pull_policy"],
|
2010
|
+
image_pull_secrets=resources["image_pull_secrets"],
|
2010
2011
|
service_account=resources["service_account"],
|
2011
2012
|
secrets=(
|
2012
2013
|
[
|
@@ -2193,6 +2194,8 @@ class ArgoWorkflows(object):
|
|
2193
2194
|
.node_selectors(resources.get("node_selector"))
|
2194
2195
|
# Set tolerations
|
2195
2196
|
.tolerations(resources.get("tolerations"))
|
2197
|
+
# Set image pull secrets
|
2198
|
+
.image_pull_secrets(resources.get("image_pull_secrets"))
|
2196
2199
|
# Set container
|
2197
2200
|
.container(
|
2198
2201
|
# TODO: Unify the logic with kubernetes.py
|
@@ -3744,6 +3747,10 @@ class Template(object):
|
|
3744
3747
|
self.payload["tolerations"] = tolerations
|
3745
3748
|
return self
|
3746
3749
|
|
3750
|
+
def image_pull_secrets(self, image_pull_secrets):
|
3751
|
+
self.payload["image_pull_secrets"] = image_pull_secrets
|
3752
|
+
return self
|
3753
|
+
|
3747
3754
|
def to_json(self):
|
3748
3755
|
return self.payload
|
3749
3756
|
|
@@ -9,59 +9,16 @@ from metaflow.exception import MetaflowException
|
|
9
9
|
from metaflow.plugins.argo.argo_client import ArgoClient
|
10
10
|
from metaflow.metaflow_config import KUBERNETES_NAMESPACE
|
11
11
|
from metaflow.plugins.argo.argo_workflows import ArgoWorkflows
|
12
|
-
from metaflow.runner.deployer import
|
12
|
+
from metaflow.runner.deployer import (
|
13
|
+
Deployer,
|
14
|
+
DeployedFlow,
|
15
|
+
TriggeredRun,
|
16
|
+
generate_fake_flow_file_contents,
|
17
|
+
)
|
13
18
|
|
14
19
|
from metaflow.runner.utils import get_lower_level_group, handle_timeout, temporary_fifo
|
15
20
|
|
16
21
|
|
17
|
-
def generate_fake_flow_file_contents(
|
18
|
-
flow_name: str, param_info: dict, project_name: Optional[str] = None
|
19
|
-
):
|
20
|
-
params_code = ""
|
21
|
-
for _, param_details in param_info.items():
|
22
|
-
param_python_var_name = param_details["python_var_name"]
|
23
|
-
param_name = param_details["name"]
|
24
|
-
param_type = param_details["type"]
|
25
|
-
param_help = param_details["description"]
|
26
|
-
param_required = param_details["is_required"]
|
27
|
-
|
28
|
-
if param_type == "JSON":
|
29
|
-
params_code += (
|
30
|
-
f" {param_python_var_name} = Parameter('{param_name}', "
|
31
|
-
f"type=JSONType, help='''{param_help}''', required={param_required})\n"
|
32
|
-
)
|
33
|
-
elif param_type == "FilePath":
|
34
|
-
is_text = param_details.get("is_text", True)
|
35
|
-
encoding = param_details.get("encoding", "utf-8")
|
36
|
-
params_code += (
|
37
|
-
f" {param_python_var_name} = IncludeFile('{param_name}', "
|
38
|
-
f"is_text={is_text}, encoding='{encoding}', help='''{param_help}''', "
|
39
|
-
f"required={param_required})\n"
|
40
|
-
)
|
41
|
-
else:
|
42
|
-
params_code += (
|
43
|
-
f" {param_python_var_name} = Parameter('{param_name}', "
|
44
|
-
f"type={param_type}, help='''{param_help}''', required={param_required})\n"
|
45
|
-
)
|
46
|
-
|
47
|
-
project_decorator = f"@project(name='{project_name}')\n" if project_name else ""
|
48
|
-
|
49
|
-
contents = f"""\
|
50
|
-
from metaflow import FlowSpec, Parameter, IncludeFile, JSONType, step, project
|
51
|
-
{project_decorator}class {flow_name}(FlowSpec):
|
52
|
-
{params_code}
|
53
|
-
@step
|
54
|
-
def start(self):
|
55
|
-
self.next(self.end)
|
56
|
-
@step
|
57
|
-
def end(self):
|
58
|
-
pass
|
59
|
-
if __name__ == '__main__':
|
60
|
-
{flow_name}()
|
61
|
-
"""
|
62
|
-
return contents
|
63
|
-
|
64
|
-
|
65
22
|
class ArgoWorkflowsTriggeredRun(TriggeredRun):
|
66
23
|
"""
|
67
24
|
A class representing a triggered Argo Workflow execution.
|
@@ -35,6 +35,12 @@ class Boto3ClientProvider(object):
|
|
35
35
|
"Could not import module 'boto3'. Install boto3 first."
|
36
36
|
)
|
37
37
|
|
38
|
+
# Convert dictionary config to Config object if needed
|
39
|
+
if "config" in client_params and not isinstance(
|
40
|
+
client_params["config"], Config
|
41
|
+
):
|
42
|
+
client_params["config"] = Config(**client_params["config"])
|
43
|
+
|
38
44
|
if module == "s3" and (
|
39
45
|
"config" not in client_params or client_params["config"].retries is None
|
40
46
|
):
|
@@ -131,7 +131,7 @@ def normalize_client_error(err):
|
|
131
131
|
except ValueError:
|
132
132
|
if error_code in ("AccessDenied", "AllAccessDisabled", "InvalidAccessKeyId"):
|
133
133
|
return 403
|
134
|
-
if error_code
|
134
|
+
if error_code in ("NoSuchKey", "NoSuchBucket"):
|
135
135
|
return 404
|
136
136
|
if error_code == "InvalidRange":
|
137
137
|
return 416
|
@@ -170,6 +170,7 @@ class Kubernetes(object):
|
|
170
170
|
code_package_ds,
|
171
171
|
docker_image,
|
172
172
|
docker_image_pull_policy,
|
173
|
+
image_pull_secrets=None,
|
173
174
|
step_cli=None,
|
174
175
|
service_account=None,
|
175
176
|
secrets=None,
|
@@ -206,6 +207,7 @@ class Kubernetes(object):
|
|
206
207
|
node_selector=node_selector,
|
207
208
|
image=docker_image,
|
208
209
|
image_pull_policy=docker_image_pull_policy,
|
210
|
+
image_pull_secrets=image_pull_secrets,
|
209
211
|
cpu=cpu,
|
210
212
|
memory=memory,
|
211
213
|
disk=disk,
|
@@ -467,6 +469,7 @@ class Kubernetes(object):
|
|
467
469
|
step_cli,
|
468
470
|
docker_image,
|
469
471
|
docker_image_pull_policy,
|
472
|
+
image_pull_secrets=None,
|
470
473
|
service_account=None,
|
471
474
|
secrets=None,
|
472
475
|
node_selector=None,
|
@@ -513,6 +516,7 @@ class Kubernetes(object):
|
|
513
516
|
),
|
514
517
|
image=docker_image,
|
515
518
|
image_pull_policy=docker_image_pull_policy,
|
519
|
+
image_pull_secrets=image_pull_secrets,
|
516
520
|
cpu=cpu,
|
517
521
|
memory=memory,
|
518
522
|
disk=disk,
|
@@ -53,6 +53,12 @@ def kubernetes():
|
|
53
53
|
default=None,
|
54
54
|
help="Optional Docker Image Pull Policy for Kubernetes pod.",
|
55
55
|
)
|
56
|
+
@click.option(
|
57
|
+
"--image-pull-secrets",
|
58
|
+
default=None,
|
59
|
+
type=JSONTypeClass(),
|
60
|
+
multiple=False,
|
61
|
+
)
|
56
62
|
@click.option(
|
57
63
|
"--service-account",
|
58
64
|
help="IRSA requirement for Kubernetes pod.",
|
@@ -160,6 +166,7 @@ def step(
|
|
160
166
|
executable=None,
|
161
167
|
image=None,
|
162
168
|
image_pull_policy=None,
|
169
|
+
image_pull_secrets=None,
|
163
170
|
service_account=None,
|
164
171
|
secrets=None,
|
165
172
|
node_selector=None,
|
@@ -303,6 +310,7 @@ def step(
|
|
303
310
|
step_cli=step_cli,
|
304
311
|
docker_image=image,
|
305
312
|
docker_image_pull_policy=image_pull_policy,
|
313
|
+
image_pull_secrets=image_pull_secrets,
|
306
314
|
service_account=service_account,
|
307
315
|
secrets=secrets,
|
308
316
|
node_selector=node_selector,
|
@@ -18,6 +18,7 @@ from metaflow.metaflow_config import (
|
|
18
18
|
KUBERNETES_FETCH_EC2_METADATA,
|
19
19
|
KUBERNETES_GPU_VENDOR,
|
20
20
|
KUBERNETES_IMAGE_PULL_POLICY,
|
21
|
+
KUBERNETES_IMAGE_PULL_SECRETS,
|
21
22
|
KUBERNETES_MEMORY,
|
22
23
|
KUBERNETES_LABELS,
|
23
24
|
KUBERNETES_ANNOTATIONS,
|
@@ -72,6 +73,10 @@ class KubernetesDecorator(StepDecorator):
|
|
72
73
|
not, a default Docker image mapping to the current version of Python is used.
|
73
74
|
image_pull_policy: str, default KUBERNETES_IMAGE_PULL_POLICY
|
74
75
|
If given, the imagePullPolicy to be applied to the Docker image of the step.
|
76
|
+
image_pull_secrets: List[str], default []
|
77
|
+
The default is extracted from METAFLOW_KUBERNETES_IMAGE_PULL_SECRETS.
|
78
|
+
Kubernetes image pull secrets to use when pulling container images
|
79
|
+
in Kubernetes.
|
75
80
|
service_account : str, default METAFLOW_KUBERNETES_SERVICE_ACCOUNT
|
76
81
|
Kubernetes service account to use when launching pod in Kubernetes.
|
77
82
|
secrets : List[str], optional, default None
|
@@ -139,6 +144,7 @@ class KubernetesDecorator(StepDecorator):
|
|
139
144
|
"disk": "10240",
|
140
145
|
"image": None,
|
141
146
|
"image_pull_policy": None,
|
147
|
+
"image_pull_secrets": None, # e.g., ["regcred"]
|
142
148
|
"service_account": None,
|
143
149
|
"secrets": None, # e.g., mysecret
|
144
150
|
"node_selector": None, # e.g., kubernetes.io/os=linux
|
@@ -192,6 +198,10 @@ class KubernetesDecorator(StepDecorator):
|
|
192
198
|
)
|
193
199
|
if not self.attributes["image_pull_policy"] and KUBERNETES_IMAGE_PULL_POLICY:
|
194
200
|
self.attributes["image_pull_policy"] = KUBERNETES_IMAGE_PULL_POLICY
|
201
|
+
if not self.attributes["image_pull_secrets"] and KUBERNETES_IMAGE_PULL_SECRETS:
|
202
|
+
self.attributes["image_pull_secrets"] = json.loads(
|
203
|
+
KUBERNETES_IMAGE_PULL_SECRETS
|
204
|
+
)
|
195
205
|
|
196
206
|
if isinstance(self.attributes["node_selector"], str):
|
197
207
|
self.attributes["node_selector"] = parse_kube_keyvalue_list(
|
@@ -479,6 +489,7 @@ class KubernetesDecorator(StepDecorator):
|
|
479
489
|
for key, val in v.items()
|
480
490
|
]
|
481
491
|
elif k in [
|
492
|
+
"image_pull_secrets",
|
482
493
|
"tolerations",
|
483
494
|
"persistent_volume_claims",
|
484
495
|
"labels",
|
@@ -214,8 +214,10 @@ class KubernetesJob(object):
|
|
214
214
|
)
|
215
215
|
],
|
216
216
|
node_selector=self._kwargs.get("node_selector"),
|
217
|
-
|
218
|
-
|
217
|
+
image_pull_secrets=[
|
218
|
+
client.V1LocalObjectReference(secret)
|
219
|
+
for secret in self._kwargs.get("image_pull_secrets") or []
|
220
|
+
],
|
219
221
|
# TODO (savin): Support preemption policies
|
220
222
|
# preemption_policy=?,
|
221
223
|
#
|
@@ -718,8 +718,11 @@ class JobSetSpec(object):
|
|
718
718
|
)
|
719
719
|
],
|
720
720
|
node_selector=self._kwargs.get("node_selector"),
|
721
|
-
|
722
|
-
|
721
|
+
image_pull_secrets=[
|
722
|
+
client.V1LocalObjectReference(secret)
|
723
|
+
for secret in self._kwargs.get("image_pull_secrets")
|
724
|
+
or []
|
725
|
+
],
|
723
726
|
# TODO (savin): Support preemption policies
|
724
727
|
# preemption_policy=?,
|
725
728
|
#
|
@@ -72,14 +72,18 @@ class ServiceMetadataProvider(MetadataProvider):
|
|
72
72
|
@classmethod
|
73
73
|
def compute_info(cls, val):
|
74
74
|
v = val.rstrip("/")
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
75
|
+
for i in range(SERVICE_RETRY_COUNT):
|
76
|
+
try:
|
77
|
+
resp = cls._session.get(
|
78
|
+
os.path.join(v, "ping"), headers=SERVICE_HEADERS.copy()
|
79
|
+
)
|
80
|
+
resp.raise_for_status()
|
81
|
+
except: # noqa E722
|
82
|
+
time.sleep(2 ** (i - 1))
|
83
|
+
else:
|
84
|
+
return v
|
85
|
+
|
86
|
+
raise ValueError("Metaflow service [%s] unreachable." % v)
|
83
87
|
|
84
88
|
@classmethod
|
85
89
|
def default_info(cls):
|
metaflow/runner/deployer.py
CHANGED
@@ -7,6 +7,55 @@ from typing import ClassVar, Dict, Optional, TYPE_CHECKING
|
|
7
7
|
from metaflow.exception import MetaflowNotFound
|
8
8
|
from metaflow.metaflow_config import DEFAULT_FROM_DEPLOYMENT_IMPL
|
9
9
|
|
10
|
+
|
11
|
+
def generate_fake_flow_file_contents(
|
12
|
+
flow_name: str, param_info: dict, project_name: Optional[str] = None
|
13
|
+
):
|
14
|
+
params_code = ""
|
15
|
+
for _, param_details in param_info.items():
|
16
|
+
param_python_var_name = param_details["python_var_name"]
|
17
|
+
param_name = param_details["name"]
|
18
|
+
param_type = param_details["type"]
|
19
|
+
param_help = param_details["description"]
|
20
|
+
param_required = param_details["is_required"]
|
21
|
+
|
22
|
+
if param_type == "JSON":
|
23
|
+
params_code += (
|
24
|
+
f" {param_python_var_name} = Parameter('{param_name}', "
|
25
|
+
f"type=JSONType, help='''{param_help}''', required={param_required})\n"
|
26
|
+
)
|
27
|
+
elif param_type == "FilePath":
|
28
|
+
is_text = param_details.get("is_text", True)
|
29
|
+
encoding = param_details.get("encoding", "utf-8")
|
30
|
+
params_code += (
|
31
|
+
f" {param_python_var_name} = IncludeFile('{param_name}', "
|
32
|
+
f"is_text={is_text}, encoding='{encoding}', help='''{param_help}''', "
|
33
|
+
f"required={param_required})\n"
|
34
|
+
)
|
35
|
+
else:
|
36
|
+
params_code += (
|
37
|
+
f" {param_python_var_name} = Parameter('{param_name}', "
|
38
|
+
f"type={param_type}, help='''{param_help}''', required={param_required})\n"
|
39
|
+
)
|
40
|
+
|
41
|
+
project_decorator = f"@project(name='{project_name}')\n" if project_name else ""
|
42
|
+
|
43
|
+
contents = f"""\
|
44
|
+
from metaflow import FlowSpec, Parameter, IncludeFile, JSONType, step, project
|
45
|
+
{project_decorator}class {flow_name}(FlowSpec):
|
46
|
+
{params_code}
|
47
|
+
@step
|
48
|
+
def start(self):
|
49
|
+
self.next(self.end)
|
50
|
+
@step
|
51
|
+
def end(self):
|
52
|
+
pass
|
53
|
+
if __name__ == '__main__':
|
54
|
+
{flow_name}()
|
55
|
+
"""
|
56
|
+
return contents
|
57
|
+
|
58
|
+
|
10
59
|
if TYPE_CHECKING:
|
11
60
|
import metaflow
|
12
61
|
import metaflow.runner.deployer_impl
|
@@ -200,7 +200,7 @@ class MutableFlow:
|
|
200
200
|
for name, value in self._flow_cls._flow_state.get(
|
201
201
|
_FlowState.CONFIGS, {}
|
202
202
|
).items():
|
203
|
-
yield name, ConfigValue(value)
|
203
|
+
yield name, ConfigValue(value) if value is not None else None
|
204
204
|
|
205
205
|
@property
|
206
206
|
def parameters(self) -> Generator[Tuple[str, Any], None, None]:
|
@@ -352,7 +352,9 @@ class ConfigInput:
|
|
352
352
|
return None
|
353
353
|
raise exc from e
|
354
354
|
flow_cls._flow_state[_FlowState.CONFIGS][name] = read_value
|
355
|
-
to_return[name] =
|
355
|
+
to_return[name] = (
|
356
|
+
ConfigValue(read_value) if read_value is not None else None
|
357
|
+
)
|
356
358
|
else:
|
357
359
|
if self._parsers[name]:
|
358
360
|
read_value = self._call_parser(self._parsers[name], val)
|
@@ -367,7 +369,9 @@ class ConfigInput:
|
|
367
369
|
continue
|
368
370
|
# TODO: Support YAML
|
369
371
|
flow_cls._flow_state[_FlowState.CONFIGS][name] = read_value
|
370
|
-
to_return[name] =
|
372
|
+
to_return[name] = (
|
373
|
+
ConfigValue(read_value) if read_value is not None else None
|
374
|
+
)
|
371
375
|
|
372
376
|
reqs = missing_configs.intersection(self._req_configs)
|
373
377
|
for missing in reqs:
|
metaflow/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
metaflow_version = "2.15.
|
1
|
+
metaflow_version = "2.15.17"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: metaflow
|
3
|
-
Version: 2.15.
|
3
|
+
Version: 2.15.17
|
4
4
|
Summary: Metaflow: More AI and ML, Less Engineering
|
5
5
|
Author: Metaflow Developers
|
6
6
|
Author-email: help@metaflow.org
|
@@ -26,7 +26,7 @@ License-File: LICENSE
|
|
26
26
|
Requires-Dist: requests
|
27
27
|
Requires-Dist: boto3
|
28
28
|
Provides-Extra: stubs
|
29
|
-
Requires-Dist: metaflow-stubs==2.15.
|
29
|
+
Requires-Dist: metaflow-stubs==2.15.17; extra == "stubs"
|
30
30
|
Dynamic: author
|
31
31
|
Dynamic: author-email
|
32
32
|
Dynamic: classifier
|
@@ -1,7 +1,7 @@
|
|
1
1
|
metaflow/R.py,sha256=CqVfIatvmjciuICNnoyyNGrwE7Va9iXfLdFbQa52hwA,3958
|
2
2
|
metaflow/__init__.py,sha256=aCCgR992PUA5Urd-pb06c1afjKbfaNPDWnH8kKQRnNk,5937
|
3
3
|
metaflow/cards.py,sha256=IbRmredvmFEU0V6JL7DR8wCESwVmmZJubr6x24bo7U4,442
|
4
|
-
metaflow/cli.py,sha256=
|
4
|
+
metaflow/cli.py,sha256=5nqEJf0R9MDdJUpIUpOxbc2dovyw_3HlbJqXmHYVCjc,21323
|
5
5
|
metaflow/cli_args.py,sha256=hDsdWdRmfXYifVGq6b6FDfgoWxtIG2nr_lU6EBV0Pnk,3584
|
6
6
|
metaflow/clone_util.py,sha256=LSuVbFpPUh92UW32DBcnZbL0FFw-4w3CLa0tpEbCkzk,2066
|
7
7
|
metaflow/cmd_with_io.py,sha256=kl53HkAIyv0ecpItv08wZYczv7u3msD1VCcciqigqf0,588
|
@@ -10,13 +10,13 @@ metaflow/decorators.py,sha256=qiAV-NOXt09I53y01Vm7EPZtJ4tROlt2Jsij7nVWOY4,24147
|
|
10
10
|
metaflow/event_logger.py,sha256=joTVRqZPL87nvah4ZOwtqWX8NeraM_CXKXXGVpKGD8o,780
|
11
11
|
metaflow/events.py,sha256=ahjzkSbSnRCK9RZ-9vTfUviz_6gMvSO9DGkJ86X80-k,5300
|
12
12
|
metaflow/exception.py,sha256=_m9ZBJM0cooHRslDqfxCPQmkChqaTh6fGxp7HvISnYI,5161
|
13
|
-
metaflow/flowspec.py,sha256=
|
13
|
+
metaflow/flowspec.py,sha256=FEC3sstpV3uHgqhUWQhNytjuqKls0BZ_NJTc3igZR4M,36471
|
14
14
|
metaflow/graph.py,sha256=cdpnWr85aEj_rRn-7EjbndWjr_i8Dt3P7-oPUW0NNpI,12393
|
15
15
|
metaflow/includefile.py,sha256=RtISGl1V48qjkJBakUZ9yPpHV102h7pOIFiKP8PLHpc,20927
|
16
16
|
metaflow/info_file.py,sha256=wtf2_F0M6dgiUu74AFImM8lfy5RrUw5Yj7Rgs2swKRY,686
|
17
17
|
metaflow/integrations.py,sha256=LlsaoePRg03DjENnmLxZDYto3NwWc9z_PtU6nJxLldg,1480
|
18
18
|
metaflow/lint.py,sha256=x4p6tnRzYqNNniCGXyrUW0WuYfTUgnaOMRivxvnxask,11661
|
19
|
-
metaflow/metaflow_config.py,sha256=
|
19
|
+
metaflow/metaflow_config.py,sha256=wrWSdPV6pAWFHo0Ao6uMnK2_zCaTD3S8-CYvxC5onPo,24045
|
20
20
|
metaflow/metaflow_config_funcs.py,sha256=5GlvoafV6SxykwfL8D12WXSfwjBN_NsyuKE_Q3gjGVE,6738
|
21
21
|
metaflow/metaflow_current.py,sha256=pfkXmkyHeMJhxIs6HBJNBEaBDpcl5kz9Wx5mW6F_3qo,7164
|
22
22
|
metaflow/metaflow_environment.py,sha256=CWG90qpfz9iJ6hHhFlAmMVNALn2v_5eTVk3mFbQR4Pw,8379
|
@@ -37,7 +37,7 @@ metaflow/tuple_util.py,sha256=_G5YIEhuugwJ_f6rrZoelMFak3DqAR2tt_5CapS1XTY,830
|
|
37
37
|
metaflow/unbounded_foreach.py,sha256=p184WMbrMJ3xKYHwewj27ZhRUsSj_kw1jlye5gA9xJk,387
|
38
38
|
metaflow/util.py,sha256=MCXCjcGwpuR7y9euBf1GTNRHPtlh6fCpdPMEtbULefw,14554
|
39
39
|
metaflow/vendor.py,sha256=EDZokNMrx1PU07jNMiWFMFtC7TL03pMXZ1kKn13k-2g,5139
|
40
|
-
metaflow/version.py,sha256=
|
40
|
+
metaflow/version.py,sha256=NkuKBUnu2oRi4r7ARbML2YLGujb0iUN9knslDNptHkM,29
|
41
41
|
metaflow/_vendor/__init__.py,sha256=y_CiwUD3l4eAKvTVDZeqgVujMy31cAM1qjAB-HfI-9s,353
|
42
42
|
metaflow/_vendor/typing_extensions.py,sha256=q9zxWa6p6CzF1zZvSkygSlklduHf_b3K7MCxGz7MJRc,134519
|
43
43
|
metaflow/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425
|
@@ -136,7 +136,7 @@ metaflow/_vendor/v3_7/typeguard/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
136
136
|
metaflow/cli_components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
137
|
metaflow/cli_components/dump_cmd.py,sha256=SZEX51BWNd1o3H2uHDkYA8KRvou5X8g5rTwpdu5vnNQ,2704
|
138
138
|
metaflow/cli_components/init_cmd.py,sha256=Er-BO59UEUV1HIsg81bRtZWT2D2IZNMp93l-AoZLCls,1519
|
139
|
-
metaflow/cli_components/run_cmds.py,sha256=
|
139
|
+
metaflow/cli_components/run_cmds.py,sha256=A0knVmimskHxcSBAxherL3TLcYao7UHHyXoyUl-n3CY,11304
|
140
140
|
metaflow/cli_components/step_cmd.py,sha256=zGJgTv7wxrv34nWDi__CHaC2eS6kItR95EdVGJX803w,4766
|
141
141
|
metaflow/cli_components/utils.py,sha256=gpoDociadjnJD7MuiJup_MDR02ZJjjleejr0jPBu29c,6057
|
142
142
|
metaflow/client/__init__.py,sha256=1GtQB4Y_CBkzaxg32L1syNQSlfj762wmLrfrDxGi1b8,226
|
@@ -150,7 +150,7 @@ metaflow/cmd/tutorials_cmd.py,sha256=8FdlKkicTOhCIDKcBR5b0Oz6giDvS-EMY3o9skIrRqw
|
|
150
150
|
metaflow/cmd/util.py,sha256=jS_0rUjOnGGzPT65fzRLdGjrYAOOLA4jU2S0HJLV0oc,406
|
151
151
|
metaflow/cmd/code/__init__.py,sha256=VO4dNM9M9LHYy5nTgEiJvCV1RBl8lpDlYGJm6GIcaBA,7413
|
152
152
|
metaflow/cmd/develop/__init__.py,sha256=p1Sy8yU1MEKSrH5ttOWOZvNcI1qYu6J6jghdTHwPgOw,689
|
153
|
-
metaflow/cmd/develop/stub_generator.py,sha256=
|
153
|
+
metaflow/cmd/develop/stub_generator.py,sha256=8Ap5rCC2lKOq4KQJ_LTuhQGj2xXYJ_Nnc1h842PsGBs,65929
|
154
154
|
metaflow/cmd/develop/stubs.py,sha256=J8DtpaN3okiPeeAqhxuUe9wQDlW4YYmZgKsVZLlVt0k,11181
|
155
155
|
metaflow/datastore/__init__.py,sha256=VxP6ddJt3rwiCkpiSfAhyVkUCOe1pgZZsytVEJzFmSQ,155
|
156
156
|
metaflow/datastore/content_addressed_store.py,sha256=6T7tNqL29kpmecyMLHF35RhoSBOb-OZcExnsB65AvnI,7641
|
@@ -206,16 +206,16 @@ metaflow/plugins/airflow/sensors/s3_sensor.py,sha256=iDReG-7FKnumrtQg-HY6cCUAAqN
|
|
206
206
|
metaflow/plugins/argo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
207
207
|
metaflow/plugins/argo/argo_client.py,sha256=A1kI9rjVjCadDsBscZ2Wk8xRBI6GNgWV6SU7TyrdfrI,16530
|
208
208
|
metaflow/plugins/argo/argo_events.py,sha256=_C1KWztVqgi3zuH57pInaE9OzABc2NnncC-zdwOMZ-w,5909
|
209
|
-
metaflow/plugins/argo/argo_workflows.py,sha256=
|
209
|
+
metaflow/plugins/argo/argo_workflows.py,sha256=lFFw5E-B2FoVGRxZ9xgnn2za2FhqMiOoLYPgQs6FLlI,186877
|
210
210
|
metaflow/plugins/argo/argo_workflows_cli.py,sha256=1bdG8BQgwyfHooBidyY1Aw52uwjCxq2Edt0bO7qezWM,38375
|
211
211
|
metaflow/plugins/argo/argo_workflows_decorator.py,sha256=ogCSBmwsC2C3eusydrgjuAJd4qK18f1sI4jJwA4Fd-o,7800
|
212
212
|
metaflow/plugins/argo/argo_workflows_deployer.py,sha256=6kHxEnYXJwzNCM9swI8-0AckxtPWqwhZLerYkX8fxUM,4444
|
213
|
-
metaflow/plugins/argo/argo_workflows_deployer_objects.py,sha256=
|
213
|
+
metaflow/plugins/argo/argo_workflows_deployer_objects.py,sha256=7OiapcIM_r-aBkuIobhofgLC5NRJHC-p9bvBmxvhqoM,12500
|
214
214
|
metaflow/plugins/argo/capture_error.py,sha256=Ys9dscGrTpW-ZCirLBU0gD9qBM0BjxyxGlUMKcwewQc,1852
|
215
215
|
metaflow/plugins/argo/generate_input_paths.py,sha256=loYsI6RFX9LlFsHb7Fe-mzlTTtRdySoOu7sYDy-uXK0,881
|
216
216
|
metaflow/plugins/argo/jobset_input_paths.py,sha256=-h0E_e0w6FMiBUod9Rf_XOSCtZv_C0exacw4q1SfIfg,501
|
217
217
|
metaflow/plugins/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
218
|
-
metaflow/plugins/aws/aws_client.py,sha256=
|
218
|
+
metaflow/plugins/aws/aws_client.py,sha256=BTiLMXa1agjja-N73oWinaOZHs-lGPbfKJG8CqdRgaU,4287
|
219
219
|
metaflow/plugins/aws/aws_utils.py,sha256=kNd61C54Y3WxrL7KSjoKydRjBQ1p3exc9QXux-jZyDE,7510
|
220
220
|
metaflow/plugins/aws/batch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
221
221
|
metaflow/plugins/aws/batch/batch.py,sha256=e9ssahWM18GnipPK2sqYB-ztx9w7Eoo7YtWyEtufYxs,17787
|
@@ -279,7 +279,7 @@ metaflow/plugins/datatools/__init__.py,sha256=ge4L16OBQLy2J_MMvoHg3lMfdm-MluQgRW
|
|
279
279
|
metaflow/plugins/datatools/local.py,sha256=FJvMOBcjdyhSPHmdLocBSiIT0rmKkKBmsaclxH75x08,4233
|
280
280
|
metaflow/plugins/datatools/s3/__init__.py,sha256=14tr9fPjN3ULW5IOfKHeG7Uhjmgm7LMtQHfz1SFv-h8,248
|
281
281
|
metaflow/plugins/datatools/s3/s3.py,sha256=3xrWD6pXoVRpuAQHyLGVya79UIE0S8AqAqe2prg4yMw,67182
|
282
|
-
metaflow/plugins/datatools/s3/s3op.py,sha256=
|
282
|
+
metaflow/plugins/datatools/s3/s3op.py,sha256=nDFgc5m0ud-uK4D2_vyweGpGoMjESxu3TlX86zA1MdQ,47561
|
283
283
|
metaflow/plugins/datatools/s3/s3tail.py,sha256=boQjQGQMI-bvTqcMP2y7uSlSYLcvWOy7J3ZUaF78NAA,2597
|
284
284
|
metaflow/plugins/datatools/s3/s3util.py,sha256=FgRgaVmEq7-i2dV7q8XK5w5PfFt-xJjZa8WrK8IJfdI,3769
|
285
285
|
metaflow/plugins/env_escape/__init__.py,sha256=tGNUZnmPvk52eNs__VK443b3CZ7ogEFTT-s9_n_HF8Q,8837
|
@@ -313,17 +313,17 @@ metaflow/plugins/gcp/gs_utils.py,sha256=ZmIGFse1qYyvAVrwga23PQUzF6dXEDLLsZ2F-YRm
|
|
313
313
|
metaflow/plugins/gcp/includefile_support.py,sha256=OQO0IVWv4ObboL0VqEZwcDOyj9ORLdur66JToxQ84vU,3887
|
314
314
|
metaflow/plugins/kubernetes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
315
315
|
metaflow/plugins/kubernetes/kube_utils.py,sha256=jdFMGbEmIow-oli26v31W9CmbZXigx06b3D_xIobpk0,4140
|
316
|
-
metaflow/plugins/kubernetes/kubernetes.py,sha256=
|
317
|
-
metaflow/plugins/kubernetes/kubernetes_cli.py,sha256=
|
316
|
+
metaflow/plugins/kubernetes/kubernetes.py,sha256=uAFK6mbRBuDitr7Xu_rMeMDVLaTnwk2jlLwKJzNrXGE,30008
|
317
|
+
metaflow/plugins/kubernetes/kubernetes_cli.py,sha256=SsZi5-Ky5_ocuRK3PeBxuLqUqXL1qDZIw1zI3mvQt9Q,14296
|
318
318
|
metaflow/plugins/kubernetes/kubernetes_client.py,sha256=tuvXP-QKpdeSmzVolB2R_TaacOr5DIb0j642eKcjsiM,6491
|
319
|
-
metaflow/plugins/kubernetes/kubernetes_decorator.py,sha256=
|
320
|
-
metaflow/plugins/kubernetes/kubernetes_job.py,sha256=
|
321
|
-
metaflow/plugins/kubernetes/kubernetes_jobsets.py,sha256=
|
319
|
+
metaflow/plugins/kubernetes/kubernetes_decorator.py,sha256=Fr2t0JvePeb1t6MLVb-6DDUJX2z85eRzF8pmxswGe0o,31971
|
320
|
+
metaflow/plugins/kubernetes/kubernetes_job.py,sha256=0QyEyi6XusHq5M7RqPY4ypQXrsQac-eG2O14b7inPOo,32277
|
321
|
+
metaflow/plugins/kubernetes/kubernetes_jobsets.py,sha256=ZZU5vsBe67NmGuxgXw6clf7kKRST7867AW6_t3fCD5g,43065
|
322
322
|
metaflow/plugins/kubernetes/spot_metadata_cli.py,sha256=an0nWCxgflmqIPBCBrlb4m3DereDFFJBLt-KKhqcHc8,1670
|
323
323
|
metaflow/plugins/kubernetes/spot_monitor_sidecar.py,sha256=zrWU-smQwPnL6MBHmzTxWyEA00R6iKKQbhhy50xFwQ8,3832
|
324
324
|
metaflow/plugins/metadata_providers/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
325
325
|
metaflow/plugins/metadata_providers/local.py,sha256=Z0CXaGZJbAkj4II3WspJi-uCCtShH64yaXZQ5i9Ym7g,24390
|
326
|
-
metaflow/plugins/metadata_providers/service.py,sha256=
|
326
|
+
metaflow/plugins/metadata_providers/service.py,sha256=5UlK0R5M9_nq2J6MgJgCZwqAC3bEsofFbglq1K4p4QI,22942
|
327
327
|
metaflow/plugins/pypi/__init__.py,sha256=0YFZpXvX7HCkyBFglatual7XGifdA1RwC3U4kcizyak,1037
|
328
328
|
metaflow/plugins/pypi/bootstrap.py,sha256=NaQboUVNJc90gmUa69-cK_T3G7piHNNsUSaN96IJoic,14745
|
329
329
|
metaflow/plugins/pypi/conda_decorator.py,sha256=N0HGiaS1mRsa6qT4eYzu2C3DHtas22QIXowW4vEl44M,15961
|
@@ -342,7 +342,7 @@ metaflow/plugins/uv/bootstrap.py,sha256=nKucPuEk6IEuu9R3aJtaTaOsD1eZjmQ4iz0t4vYF
|
|
342
342
|
metaflow/plugins/uv/uv_environment.py,sha256=6hUaWrTgqHyzS6igGQUXpS6jb_GHv3Wq9ZrWhZgEals,2587
|
343
343
|
metaflow/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
344
344
|
metaflow/runner/click_api.py,sha256=u9Y1bu9vN13ektBs-L8lg2oxb5oYvGe1dPJjV2shMAw,23727
|
345
|
-
metaflow/runner/deployer.py,sha256=
|
345
|
+
metaflow/runner/deployer.py,sha256=U-hwf4gVzwUlXgnkfTW3y1daGXvo5eP4HTQZwb-vS0g,11058
|
346
346
|
metaflow/runner/deployer_impl.py,sha256=zTING0_fwP44JcGo69DuNrVut5KqdBVzYOM7MYTZgIY,7049
|
347
347
|
metaflow/runner/metaflow_runner.py,sha256=BaDAp-3tCPwJRy_R8hLTAu6L0qjjuQmjeo-L1inhr_c,17498
|
348
348
|
metaflow/runner/nbdeploy.py,sha256=Sp5w-6nCZwjHaRBHWxi8udya-RYnJOB76KNLjB4L7Gs,4166
|
@@ -386,15 +386,15 @@ metaflow/tutorials/07-worldview/worldview.ipynb,sha256=ztPZPI9BXxvW1QdS2Tfe7LBuV
|
|
386
386
|
metaflow/tutorials/08-autopilot/README.md,sha256=GnePFp_q76jPs991lMUqfIIh5zSorIeWznyiUxzeUVE,1039
|
387
387
|
metaflow/tutorials/08-autopilot/autopilot.ipynb,sha256=DQoJlILV7Mq9vfPBGW-QV_kNhWPjS5n6SJLqePjFYLY,3191
|
388
388
|
metaflow/user_configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
389
|
-
metaflow/user_configs/config_decorators.py,sha256=
|
390
|
-
metaflow/user_configs/config_options.py,sha256=
|
389
|
+
metaflow/user_configs/config_decorators.py,sha256=n4OTbfuaXejPVLHnXXgVlNJNcrSvWrVOdXCMcqvQlik,20512
|
390
|
+
metaflow/user_configs/config_options.py,sha256=yyaiKLB4QWlR5AaTg9I7GoBv-OlffOFdGPe1BL85Llc,21241
|
391
391
|
metaflow/user_configs/config_parameters.py,sha256=Eyiqcz4YV_z4algDHAh2gaejGFgIdHk8Vix9AUdPSh0,20989
|
392
|
-
metaflow-2.15.
|
393
|
-
metaflow-2.15.
|
394
|
-
metaflow-2.15.
|
395
|
-
metaflow-2.15.
|
396
|
-
metaflow-2.15.
|
397
|
-
metaflow-2.15.
|
398
|
-
metaflow-2.15.
|
399
|
-
metaflow-2.15.
|
400
|
-
metaflow-2.15.
|
392
|
+
metaflow-2.15.17.data/data/share/metaflow/devtools/Makefile,sha256=5n89OGIC_kE4wxtEI66VCucN-b-1w5bqvGeZYmeRGz8,13737
|
393
|
+
metaflow-2.15.17.data/data/share/metaflow/devtools/Tiltfile,sha256=P5_rn_F3xYLN1_cEAQ9mNeS22HG2rb8beKIz2RIK6fU,20634
|
394
|
+
metaflow-2.15.17.data/data/share/metaflow/devtools/pick_services.sh,sha256=DCnrMXwtApfx3B4S-YiZESMyAFHbXa3VuNL0MxPLyiE,2196
|
395
|
+
metaflow-2.15.17.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
|
396
|
+
metaflow-2.15.17.dist-info/METADATA,sha256=7DfiQK2zg33YgaYjF6Oc5hEHfRgf7js9w-22xvqojFE,6742
|
397
|
+
metaflow-2.15.17.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
|
398
|
+
metaflow-2.15.17.dist-info/entry_points.txt,sha256=RvEq8VFlgGe_FfqGOZi0D7ze1hLD0pAtXeNyGfzc_Yc,103
|
399
|
+
metaflow-2.15.17.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
|
400
|
+
metaflow-2.15.17.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{metaflow-2.15.15.data → metaflow-2.15.17.data}/data/share/metaflow/devtools/pick_services.sh
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|