metaflow 2.12.10__py2.py3-none-any.whl → 2.12.11__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/client/core.py +6 -6
- metaflow/client/filecache.py +16 -3
- metaflow/cmd/develop/stub_generator.py +62 -47
- metaflow/datastore/content_addressed_store.py +1 -1
- metaflow/datastore/task_datastore.py +1 -1
- metaflow/decorators.py +2 -4
- metaflow/extension_support/__init__.py +3 -3
- metaflow/extension_support/plugins.py +3 -3
- metaflow/metaflow_config.py +35 -18
- metaflow/parameters.py +3 -3
- metaflow/plugins/airflow/airflow.py +6 -6
- metaflow/plugins/airflow/airflow_utils.py +5 -3
- metaflow/plugins/argo/argo_workflows.py +407 -193
- metaflow/plugins/argo/argo_workflows_cli.py +17 -4
- metaflow/plugins/argo/argo_workflows_decorator.py +6 -13
- metaflow/plugins/argo/capture_error.py +70 -0
- metaflow/plugins/aws/step_functions/step_functions.py +3 -3
- metaflow/plugins/cards/card_modules/basic.py +5 -3
- metaflow/plugins/cards/card_modules/convert_to_native_type.py +2 -2
- metaflow/plugins/cards/card_modules/renderer_tools.py +1 -0
- metaflow/plugins/cards/card_modules/test_cards.py +0 -2
- metaflow/plugins/datatools/s3/s3op.py +5 -3
- metaflow/plugins/kubernetes/kubernetes.py +1 -0
- metaflow/plugins/kubernetes/kubernetes_job.py +10 -8
- metaflow/plugins/kubernetes/kubernetes_jobsets.py +15 -14
- metaflow/plugins/logs_cli.py +1 -0
- metaflow/plugins/pypi/conda_environment.py +1 -3
- metaflow/plugins/pypi/pip.py +3 -3
- metaflow/plugins/tag_cli.py +3 -3
- metaflow/procpoll.py +1 -1
- metaflow/runtime.py +1 -0
- metaflow/util.py +6 -6
- metaflow/version.py +1 -1
- {metaflow-2.12.10.dist-info → metaflow-2.12.11.dist-info}/METADATA +2 -2
- {metaflow-2.12.10.dist-info → metaflow-2.12.11.dist-info}/RECORD +39 -38
- {metaflow-2.12.10.dist-info → metaflow-2.12.11.dist-info}/LICENSE +0 -0
- {metaflow-2.12.10.dist-info → metaflow-2.12.11.dist-info}/WHEEL +0 -0
- {metaflow-2.12.10.dist-info → metaflow-2.12.11.dist-info}/entry_points.txt +0 -0
- {metaflow-2.12.10.dist-info → metaflow-2.12.11.dist-info}/top_level.txt +0 -0
metaflow/client/core.py
CHANGED
@@ -391,9 +391,9 @@ class MetaflowObject(object):
|
|
391
391
|
_object=obj,
|
392
392
|
_parent=self,
|
393
393
|
_namespace_check=self._namespace_check,
|
394
|
-
_current_namespace=
|
395
|
-
|
396
|
-
|
394
|
+
_current_namespace=(
|
395
|
+
self._current_namespace if self._namespace_check else None
|
396
|
+
),
|
397
397
|
)
|
398
398
|
for obj in unfiltered_children
|
399
399
|
),
|
@@ -506,9 +506,9 @@ class MetaflowObject(object):
|
|
506
506
|
_object=obj,
|
507
507
|
_parent=self,
|
508
508
|
_namespace_check=self._namespace_check,
|
509
|
-
_current_namespace=
|
510
|
-
|
511
|
-
|
509
|
+
_current_namespace=(
|
510
|
+
self._current_namespace if self._namespace_check else None
|
511
|
+
),
|
512
512
|
)
|
513
513
|
else:
|
514
514
|
raise KeyError(id)
|
metaflow/client/filecache.py
CHANGED
@@ -6,6 +6,8 @@ import time
|
|
6
6
|
from tempfile import NamedTemporaryFile
|
7
7
|
from hashlib import sha1
|
8
8
|
|
9
|
+
from urllib.parse import urlparse
|
10
|
+
|
9
11
|
from metaflow.datastore import FlowDataStore
|
10
12
|
from metaflow.datastore.content_addressed_store import BlobCache
|
11
13
|
from metaflow.exception import MetaflowException
|
@@ -83,7 +85,6 @@ class FileCache(object):
|
|
83
85
|
def get_log_legacy(
|
84
86
|
self, ds_type, location, logtype, attempt, flow_name, run_id, step_name, task_id
|
85
87
|
):
|
86
|
-
|
87
88
|
ds_cls = self._get_datastore_storage_impl(ds_type)
|
88
89
|
ds_root = ds_cls.path_join(*ds_cls.path_split(location)[:-5])
|
89
90
|
cache_id = self._flow_ds_id(ds_type, ds_root, flow_name)
|
@@ -311,12 +312,24 @@ class FileCache(object):
|
|
311
312
|
|
312
313
|
@staticmethod
|
313
314
|
def _flow_ds_id(ds_type, ds_root, flow_name):
|
314
|
-
|
315
|
+
p = urlparse(ds_root)
|
316
|
+
sanitized_root = (p.netloc + p.path).replace("/", "_")
|
317
|
+
return ".".join([ds_type, sanitized_root, flow_name])
|
315
318
|
|
316
319
|
@staticmethod
|
317
320
|
def _task_ds_id(ds_type, ds_root, flow_name, run_id, step_name, task_id, attempt):
|
321
|
+
p = urlparse(ds_root)
|
322
|
+
sanitized_root = (p.netloc + p.path).replace("/", "_")
|
318
323
|
return ".".join(
|
319
|
-
[
|
324
|
+
[
|
325
|
+
ds_type,
|
326
|
+
sanitized_root,
|
327
|
+
flow_name,
|
328
|
+
run_id,
|
329
|
+
step_name,
|
330
|
+
task_id,
|
331
|
+
str(attempt),
|
332
|
+
]
|
320
333
|
)
|
321
334
|
|
322
335
|
def _garbage_collect(self):
|
@@ -292,9 +292,11 @@ class StubGenerator:
|
|
292
292
|
try:
|
293
293
|
potential_element = eval(
|
294
294
|
element,
|
295
|
-
|
296
|
-
|
297
|
-
|
295
|
+
(
|
296
|
+
self._current_parent_module.__dict__
|
297
|
+
if self._current_parent_module
|
298
|
+
else None
|
299
|
+
),
|
298
300
|
)
|
299
301
|
if potential_element:
|
300
302
|
element = potential_element
|
@@ -555,14 +557,14 @@ class StubGenerator:
|
|
555
557
|
inspect.Parameter(
|
556
558
|
name=arg_name,
|
557
559
|
kind=inspect.Parameter.KEYWORD_ONLY,
|
558
|
-
default=
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
annotation=
|
564
|
-
|
565
|
-
|
560
|
+
default=(
|
561
|
+
default
|
562
|
+
if default_set
|
563
|
+
else None if is_optional else inspect.Parameter.empty
|
564
|
+
),
|
565
|
+
annotation=(
|
566
|
+
Optional[type_name] if is_optional else type_name
|
567
|
+
),
|
566
568
|
)
|
567
569
|
)
|
568
570
|
if not default_set:
|
@@ -706,24 +708,31 @@ class StubGenerator:
|
|
706
708
|
result = result + [
|
707
709
|
(
|
708
710
|
inspect.Signature(
|
709
|
-
parameters=
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
711
|
+
parameters=(
|
712
|
+
[
|
713
|
+
inspect.Parameter(
|
714
|
+
name="f",
|
715
|
+
kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
716
|
+
annotation=Optional[typing.Type[FlowSpecDerived]],
|
717
|
+
default=(
|
718
|
+
None
|
719
|
+
if no_arg_version
|
720
|
+
else inspect.Parameter.empty
|
721
|
+
),
|
722
|
+
)
|
723
|
+
]
|
724
|
+
+ parameters
|
725
|
+
if no_arg_version
|
726
|
+
else [] + parameters
|
727
|
+
),
|
728
|
+
return_annotation=(
|
729
|
+
inspect.Signature.empty
|
730
|
+
if no_arg_version
|
731
|
+
else Callable[
|
732
|
+
[typing.Type[FlowSpecDerived]],
|
733
|
+
typing.Type[FlowSpecDerived],
|
734
|
+
]
|
735
|
+
),
|
727
736
|
),
|
728
737
|
"",
|
729
738
|
),
|
@@ -732,24 +741,30 @@ class StubGenerator:
|
|
732
741
|
result = result + [
|
733
742
|
(
|
734
743
|
inspect.Signature(
|
735
|
-
parameters=
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
744
|
+
parameters=(
|
745
|
+
[
|
746
|
+
inspect.Parameter(
|
747
|
+
name="f",
|
748
|
+
kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
749
|
+
annotation=Optional[MetaflowStepFunction],
|
750
|
+
default=(
|
751
|
+
None
|
752
|
+
if no_arg_version
|
753
|
+
else inspect.Parameter.empty
|
754
|
+
),
|
755
|
+
)
|
756
|
+
]
|
757
|
+
+ parameters
|
758
|
+
if no_arg_version
|
759
|
+
else [] + parameters
|
760
|
+
),
|
761
|
+
return_annotation=(
|
762
|
+
inspect.Signature.empty
|
763
|
+
if no_arg_version
|
764
|
+
else typing.Callable[
|
765
|
+
[MetaflowStepFunction], MetaflowStepFunction
|
766
|
+
]
|
767
|
+
),
|
753
768
|
),
|
754
769
|
"",
|
755
770
|
),
|
@@ -133,7 +133,7 @@ class ContentAddressedStore(object):
|
|
133
133
|
load_paths.append((key, path))
|
134
134
|
|
135
135
|
with self._storage_impl.load_bytes([p for _, p in load_paths]) as loaded:
|
136
|
-
for
|
136
|
+
for path_key, file_path, meta in loaded:
|
137
137
|
key = self._storage_impl.path_split(path_key)[-1]
|
138
138
|
# At this point, we either return the object as is (if raw) or
|
139
139
|
# decode it according to the encoding version
|
@@ -381,7 +381,7 @@ class TaskDataStore(object):
|
|
381
381
|
# We assume that if we have one "old" style artifact, all of them are
|
382
382
|
# like that which is an easy assumption to make since artifacts are all
|
383
383
|
# stored by the same implementation of the datastore for a given task.
|
384
|
-
for
|
384
|
+
for key, blob in self._ca_store.load_blobs(to_load.keys()):
|
385
385
|
names = to_load[key]
|
386
386
|
for name in names:
|
387
387
|
# We unpickle everytime to have fully distinct objects (the user
|
metaflow/decorators.py
CHANGED
@@ -575,15 +575,13 @@ StepFlag = NewType("StepFlag", bool)
|
|
575
575
|
@overload
|
576
576
|
def step(
|
577
577
|
f: Callable[[FlowSpecDerived], None]
|
578
|
-
) -> Callable[[FlowSpecDerived, StepFlag], None]:
|
579
|
-
...
|
578
|
+
) -> Callable[[FlowSpecDerived, StepFlag], None]: ...
|
580
579
|
|
581
580
|
|
582
581
|
@overload
|
583
582
|
def step(
|
584
583
|
f: Callable[[FlowSpecDerived, Any], None],
|
585
|
-
) -> Callable[[FlowSpecDerived, Any, StepFlag], None]:
|
586
|
-
...
|
584
|
+
) -> Callable[[FlowSpecDerived, Any, StepFlag], None]: ...
|
587
585
|
|
588
586
|
|
589
587
|
def step(
|
@@ -980,9 +980,9 @@ class _OrigLoader(Loader):
|
|
980
980
|
if self._previously_loaded_module:
|
981
981
|
sys.modules[self._orig_name] = self._previously_loaded_module
|
982
982
|
if self._previously_loaded_parent_module:
|
983
|
-
sys.modules[
|
984
|
-
|
985
|
-
|
983
|
+
sys.modules[".".join(self._orig_name.split(".")[:-1])] = (
|
984
|
+
self._previously_loaded_parent_module
|
985
|
+
)
|
986
986
|
|
987
987
|
|
988
988
|
class _LazyFinder(MetaPathFinder):
|
@@ -186,9 +186,9 @@ _plugin_categories = {
|
|
186
186
|
"logging_sidecar": None,
|
187
187
|
"monitor_sidecar": None,
|
188
188
|
"aws_client_provider": lambda x: x.name,
|
189
|
-
"cli": lambda x:
|
190
|
-
|
191
|
-
|
189
|
+
"cli": lambda x: (
|
190
|
+
list(x.commands)[0] if len(x.commands) == 1 else "too many commands"
|
191
|
+
),
|
192
192
|
}
|
193
193
|
|
194
194
|
|
metaflow/metaflow_config.py
CHANGED
@@ -104,9 +104,11 @@ RETRY_WARNING_THRESHOLD = 3
|
|
104
104
|
DATATOOLS_SUFFIX = from_conf("DATATOOLS_SUFFIX", "data")
|
105
105
|
DATATOOLS_S3ROOT = from_conf(
|
106
106
|
"DATATOOLS_S3ROOT",
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
(
|
108
|
+
os.path.join(DATASTORE_SYSROOT_S3, DATATOOLS_SUFFIX)
|
109
|
+
if DATASTORE_SYSROOT_S3
|
110
|
+
else None
|
111
|
+
),
|
110
112
|
)
|
111
113
|
|
112
114
|
TEMPDIR = from_conf("TEMPDIR", ".")
|
@@ -124,25 +126,31 @@ DATATOOLS_SESSION_VARS = from_conf("DATATOOLS_SESSION_VARS", {})
|
|
124
126
|
# Similar to DATATOOLS_LOCALROOT, this is used ONLY by the IncludeFile's internal implementation.
|
125
127
|
DATATOOLS_AZUREROOT = from_conf(
|
126
128
|
"DATATOOLS_AZUREROOT",
|
127
|
-
|
128
|
-
|
129
|
-
|
129
|
+
(
|
130
|
+
os.path.join(DATASTORE_SYSROOT_AZURE, DATATOOLS_SUFFIX)
|
131
|
+
if DATASTORE_SYSROOT_AZURE
|
132
|
+
else None
|
133
|
+
),
|
130
134
|
)
|
131
135
|
# GS datatools root location
|
132
136
|
# Note: we do not expose an actual datatools library for GS (like we do for S3)
|
133
137
|
# Similar to DATATOOLS_LOCALROOT, this is used ONLY by the IncludeFile's internal implementation.
|
134
138
|
DATATOOLS_GSROOT = from_conf(
|
135
139
|
"DATATOOLS_GSROOT",
|
136
|
-
|
137
|
-
|
138
|
-
|
140
|
+
(
|
141
|
+
os.path.join(DATASTORE_SYSROOT_GS, DATATOOLS_SUFFIX)
|
142
|
+
if DATASTORE_SYSROOT_GS
|
143
|
+
else None
|
144
|
+
),
|
139
145
|
)
|
140
146
|
# Local datatools root location
|
141
147
|
DATATOOLS_LOCALROOT = from_conf(
|
142
148
|
"DATATOOLS_LOCALROOT",
|
143
|
-
|
144
|
-
|
145
|
-
|
149
|
+
(
|
150
|
+
os.path.join(DATASTORE_SYSROOT_LOCAL, DATATOOLS_SUFFIX)
|
151
|
+
if DATASTORE_SYSROOT_LOCAL
|
152
|
+
else None
|
153
|
+
),
|
146
154
|
)
|
147
155
|
|
148
156
|
# Secrets Backend - AWS Secrets Manager configuration
|
@@ -176,9 +184,11 @@ CARD_S3ROOT = from_conf(
|
|
176
184
|
)
|
177
185
|
CARD_AZUREROOT = from_conf(
|
178
186
|
"CARD_AZUREROOT",
|
179
|
-
|
180
|
-
|
181
|
-
|
187
|
+
(
|
188
|
+
os.path.join(DATASTORE_SYSROOT_AZURE, CARD_SUFFIX)
|
189
|
+
if DATASTORE_SYSROOT_AZURE
|
190
|
+
else None
|
191
|
+
),
|
182
192
|
)
|
183
193
|
CARD_GSROOT = from_conf(
|
184
194
|
"CARD_GSROOT",
|
@@ -238,6 +248,11 @@ DEFAULT_RUNTIME_LIMIT = from_conf("DEFAULT_RUNTIME_LIMIT", 5 * 24 * 60 * 60)
|
|
238
248
|
###
|
239
249
|
UI_URL = from_conf("UI_URL")
|
240
250
|
|
251
|
+
###
|
252
|
+
# Capture error logs from argo
|
253
|
+
###
|
254
|
+
ARGO_WORKFLOWS_CAPTURE_ERROR_SCRIPT = from_conf("ARGO_WORKFLOWS_CAPTURE_ERROR_SCRIPT")
|
255
|
+
|
241
256
|
# Contact information displayed when running the `metaflow` command.
|
242
257
|
# Value should be a dictionary where:
|
243
258
|
# - key is a string describing contact method
|
@@ -306,9 +321,11 @@ SFN_EXECUTION_LOG_GROUP_ARN = from_conf("SFN_EXECUTION_LOG_GROUP_ARN")
|
|
306
321
|
# Amazon S3 path for storing the results of AWS Step Functions Distributed Map
|
307
322
|
SFN_S3_DISTRIBUTED_MAP_OUTPUT_PATH = from_conf(
|
308
323
|
"SFN_S3_DISTRIBUTED_MAP_OUTPUT_PATH",
|
309
|
-
|
310
|
-
|
311
|
-
|
324
|
+
(
|
325
|
+
os.path.join(DATASTORE_SYSROOT_S3, "sfn_distributed_map_output")
|
326
|
+
if DATASTORE_SYSROOT_S3
|
327
|
+
else None
|
328
|
+
),
|
312
329
|
)
|
313
330
|
###
|
314
331
|
# Kubernetes configuration
|
metaflow/parameters.py
CHANGED
@@ -115,9 +115,9 @@ class DeployTimeField(object):
|
|
115
115
|
self.parameter_name = parameter_name
|
116
116
|
self.parameter_type = parameter_type
|
117
117
|
self.return_str = return_str
|
118
|
-
self.print_representation = (
|
119
|
-
|
120
|
-
)
|
118
|
+
self.print_representation = self.user_print_representation = (
|
119
|
+
print_representation
|
120
|
+
)
|
121
121
|
if self.print_representation is None:
|
122
122
|
self.print_representation = str(self.fun)
|
123
123
|
|
@@ -399,17 +399,17 @@ class Airflow(object):
|
|
399
399
|
"METAFLOW_CARD_GSROOT": CARD_GSROOT,
|
400
400
|
"METAFLOW_S3_ENDPOINT_URL": S3_ENDPOINT_URL,
|
401
401
|
}
|
402
|
-
env[
|
403
|
-
|
404
|
-
|
402
|
+
env["METAFLOW_AZURE_STORAGE_BLOB_SERVICE_ENDPOINT"] = (
|
403
|
+
AZURE_STORAGE_BLOB_SERVICE_ENDPOINT
|
404
|
+
)
|
405
405
|
env["METAFLOW_DATASTORE_SYSROOT_AZURE"] = DATASTORE_SYSROOT_AZURE
|
406
406
|
env["METAFLOW_CARD_AZUREROOT"] = CARD_AZUREROOT
|
407
407
|
if DEFAULT_SECRETS_BACKEND_TYPE:
|
408
408
|
env["METAFLOW_DEFAULT_SECRETS_BACKEND_TYPE"] = DEFAULT_SECRETS_BACKEND_TYPE
|
409
409
|
if AWS_SECRETS_MANAGER_DEFAULT_REGION:
|
410
|
-
env[
|
411
|
-
|
412
|
-
|
410
|
+
env["METAFLOW_AWS_SECRETS_MANAGER_DEFAULT_REGION"] = (
|
411
|
+
AWS_SECRETS_MANAGER_DEFAULT_REGION
|
412
|
+
)
|
413
413
|
if GCP_SECRET_MANAGER_PREFIX:
|
414
414
|
env["METAFLOW_GCP_SECRET_MANAGER_PREFIX"] = GCP_SECRET_MANAGER_PREFIX
|
415
415
|
|
@@ -567,9 +567,11 @@ class AirflowTask(object):
|
|
567
567
|
return cls(
|
568
568
|
task_dict["name"],
|
569
569
|
is_mapper_node=is_mapper_node,
|
570
|
-
operator_type=
|
571
|
-
|
572
|
-
|
570
|
+
operator_type=(
|
571
|
+
task_dict["operator_type"]
|
572
|
+
if "operator_type" in task_dict
|
573
|
+
else "kubernetes"
|
574
|
+
),
|
573
575
|
flow_name=flow_name,
|
574
576
|
flow_contains_foreach=flow_contains_foreach,
|
575
577
|
).set_operator_args(**op_args)
|