ob-metaflow 2.15.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/__init__.py +10 -3
- metaflow/_vendor/imghdr/__init__.py +186 -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 +4 -0
- metaflow/cli.py +125 -21
- metaflow/cli_components/init_cmd.py +1 -0
- metaflow/cli_components/run_cmds.py +204 -40
- metaflow/cli_components/step_cmd.py +160 -4
- metaflow/client/__init__.py +1 -0
- metaflow/client/core.py +198 -130
- metaflow/client/filecache.py +59 -32
- metaflow/cmd/code/__init__.py +2 -1
- metaflow/cmd/develop/stub_generator.py +49 -18
- metaflow/cmd/develop/stubs.py +9 -27
- metaflow/cmd/make_wrapper.py +30 -0
- metaflow/datastore/__init__.py +1 -0
- metaflow/datastore/content_addressed_store.py +40 -9
- metaflow/datastore/datastore_set.py +10 -1
- metaflow/datastore/flow_datastore.py +124 -4
- metaflow/datastore/spin_datastore.py +91 -0
- metaflow/datastore/task_datastore.py +92 -6
- metaflow/debug.py +5 -0
- metaflow/decorators.py +331 -82
- metaflow/extension_support/__init__.py +414 -356
- metaflow/extension_support/_empty_file.py +2 -2
- metaflow/flowspec.py +322 -82
- metaflow/graph.py +178 -15
- metaflow/includefile.py +25 -3
- metaflow/lint.py +94 -3
- metaflow/meta_files.py +13 -0
- metaflow/metadata_provider/metadata.py +13 -2
- metaflow/metaflow_config.py +66 -4
- metaflow/metaflow_environment.py +91 -25
- metaflow/metaflow_profile.py +18 -0
- metaflow/metaflow_version.py +16 -1
- 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 +6 -2
- metaflow/plugins/__init__.py +6 -0
- metaflow/plugins/airflow/airflow.py +11 -1
- metaflow/plugins/airflow/airflow_cli.py +16 -5
- metaflow/plugins/argo/argo_client.py +42 -20
- metaflow/plugins/argo/argo_events.py +6 -6
- metaflow/plugins/argo/argo_workflows.py +1023 -344
- metaflow/plugins/argo/argo_workflows_cli.py +396 -94
- metaflow/plugins/argo/argo_workflows_decorator.py +9 -0
- metaflow/plugins/argo/argo_workflows_deployer_objects.py +75 -49
- metaflow/plugins/argo/capture_error.py +5 -2
- metaflow/plugins/argo/conditional_input_paths.py +35 -0
- metaflow/plugins/argo/exit_hooks.py +209 -0
- metaflow/plugins/argo/param_val.py +19 -0
- metaflow/plugins/aws/aws_client.py +6 -0
- metaflow/plugins/aws/aws_utils.py +33 -1
- metaflow/plugins/aws/batch/batch.py +72 -5
- metaflow/plugins/aws/batch/batch_cli.py +24 -3
- metaflow/plugins/aws/batch/batch_decorator.py +57 -6
- metaflow/plugins/aws/step_functions/step_functions.py +28 -3
- metaflow/plugins/aws/step_functions/step_functions_cli.py +49 -4
- metaflow/plugins/aws/step_functions/step_functions_deployer.py +3 -0
- metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +30 -0
- metaflow/plugins/cards/card_cli.py +20 -1
- metaflow/plugins/cards/card_creator.py +24 -1
- metaflow/plugins/cards/card_datastore.py +21 -49
- metaflow/plugins/cards/card_decorator.py +58 -6
- metaflow/plugins/cards/card_modules/basic.py +38 -9
- metaflow/plugins/cards/card_modules/bundle.css +1 -1
- metaflow/plugins/cards/card_modules/chevron/renderer.py +1 -1
- metaflow/plugins/cards/card_modules/components.py +592 -3
- metaflow/plugins/cards/card_modules/convert_to_native_type.py +34 -5
- 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 +56 -41
- metaflow/plugins/cards/card_modules/test_cards.py +22 -6
- metaflow/plugins/cards/component_serializer.py +1 -8
- metaflow/plugins/cards/metadata.py +22 -0
- metaflow/plugins/catch_decorator.py +9 -0
- metaflow/plugins/datastores/local_storage.py +12 -6
- metaflow/plugins/datastores/spin_storage.py +12 -0
- metaflow/plugins/datatools/s3/s3.py +49 -17
- metaflow/plugins/datatools/s3/s3op.py +113 -66
- metaflow/plugins/env_escape/client_modules.py +102 -72
- metaflow/plugins/events_decorator.py +127 -121
- 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/kubernetes/kubernetes.py +12 -1
- metaflow/plugins/kubernetes/kubernetes_cli.py +11 -0
- metaflow/plugins/kubernetes/kubernetes_decorator.py +25 -6
- metaflow/plugins/kubernetes/kubernetes_job.py +12 -4
- metaflow/plugins/kubernetes/kubernetes_jobsets.py +31 -30
- metaflow/plugins/metadata_providers/local.py +76 -82
- metaflow/plugins/metadata_providers/service.py +13 -9
- metaflow/plugins/metadata_providers/spin.py +16 -0
- metaflow/plugins/package_cli.py +36 -24
- metaflow/plugins/parallel_decorator.py +11 -2
- metaflow/plugins/parsers.py +16 -0
- metaflow/plugins/pypi/bootstrap.py +7 -1
- metaflow/plugins/pypi/conda_decorator.py +41 -82
- metaflow/plugins/pypi/conda_environment.py +14 -6
- metaflow/plugins/pypi/micromamba.py +9 -1
- metaflow/plugins/pypi/pip.py +41 -5
- metaflow/plugins/pypi/pypi_decorator.py +4 -4
- metaflow/plugins/pypi/utils.py +22 -0
- metaflow/plugins/secrets/__init__.py +3 -0
- metaflow/plugins/secrets/secrets_decorator.py +14 -178
- 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/test_unbounded_foreach_decorator.py +2 -2
- metaflow/plugins/timeout_decorator.py +0 -1
- metaflow/plugins/uv/bootstrap.py +29 -1
- metaflow/plugins/uv/uv_environment.py +5 -3
- metaflow/pylint_wrapper.py +5 -1
- metaflow/runner/click_api.py +79 -26
- metaflow/runner/deployer.py +208 -6
- metaflow/runner/deployer_impl.py +32 -12
- metaflow/runner/metaflow_runner.py +266 -33
- metaflow/runner/subprocess_manager.py +21 -1
- metaflow/runner/utils.py +27 -16
- metaflow/runtime.py +660 -66
- metaflow/task.py +255 -26
- metaflow/user_configs/config_options.py +33 -21
- metaflow/user_configs/config_parameters.py +220 -58
- 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 +197 -7
- metaflow/vendor.py +23 -7
- metaflow/version.py +1 -1
- {ob_metaflow-2.15.13.1.data → ob_metaflow-2.19.7.1rc0.data}/data/share/metaflow/devtools/Makefile +13 -2
- {ob_metaflow-2.15.13.1.data → ob_metaflow-2.19.7.1rc0.data}/data/share/metaflow/devtools/Tiltfile +107 -7
- {ob_metaflow-2.15.13.1.data → ob_metaflow-2.19.7.1rc0.data}/data/share/metaflow/devtools/pick_services.sh +1 -0
- {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/METADATA +2 -3
- {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/RECORD +162 -121
- {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/WHEEL +1 -1
- 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/_vendor/v3_5/zipp.py +0 -329
- metaflow/info_file.py +0 -25
- metaflow/package.py +0 -203
- metaflow/user_configs/config_decorators.py +0 -568
- {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/entry_points.txt +0 -0
- {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/licenses/LICENSE +0 -0
- {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/top_level.txt +0 -0
|
@@ -6,6 +6,7 @@ import time
|
|
|
6
6
|
|
|
7
7
|
from functools import wraps
|
|
8
8
|
from io import BufferedIOBase, FileIO, RawIOBase
|
|
9
|
+
from typing import List, Optional
|
|
9
10
|
from types import MethodType, FunctionType
|
|
10
11
|
|
|
11
12
|
from .. import metaflow_config
|
|
@@ -98,8 +99,8 @@ class TaskDataStore(object):
|
|
|
98
99
|
data_metadata=None,
|
|
99
100
|
mode="r",
|
|
100
101
|
allow_not_done=False,
|
|
102
|
+
persist=True,
|
|
101
103
|
):
|
|
102
|
-
|
|
103
104
|
self._storage_impl = flow_datastore._storage_impl
|
|
104
105
|
self.TYPE = self._storage_impl.TYPE
|
|
105
106
|
self._ca_store = flow_datastore.ca_store
|
|
@@ -114,11 +115,12 @@ class TaskDataStore(object):
|
|
|
114
115
|
self._attempt = attempt
|
|
115
116
|
self._metadata = flow_datastore.metadata
|
|
116
117
|
self._parent = flow_datastore
|
|
118
|
+
self._persist = persist
|
|
117
119
|
|
|
118
120
|
# The GZIP encodings are for backward compatibility
|
|
119
121
|
self._encodings = {"pickle-v2", "gzip+pickle-v2"}
|
|
120
122
|
ver = sys.version_info[0] * 10 + sys.version_info[1]
|
|
121
|
-
if ver >=
|
|
123
|
+
if ver >= 36:
|
|
122
124
|
self._encodings.add("pickle-v4")
|
|
123
125
|
self._encodings.add("gzip+pickle-v4")
|
|
124
126
|
|
|
@@ -149,6 +151,8 @@ class TaskDataStore(object):
|
|
|
149
151
|
)
|
|
150
152
|
if self.has_metadata(check_meta, add_attempt=False):
|
|
151
153
|
max_attempt = i
|
|
154
|
+
elif max_attempt is not None:
|
|
155
|
+
break
|
|
152
156
|
if self._attempt is None:
|
|
153
157
|
self._attempt = max_attempt
|
|
154
158
|
elif max_attempt is None or self._attempt > max_attempt:
|
|
@@ -223,6 +227,9 @@ class TaskDataStore(object):
|
|
|
223
227
|
@property
|
|
224
228
|
def pathspec_index(self):
|
|
225
229
|
idxstr = ",".join(map(str, (f.index for f in self["_foreach_stack"])))
|
|
230
|
+
if "_iteration_stack" in self:
|
|
231
|
+
itrstr = ",".join(map(str, (f for f in self["_iteration_stack"])))
|
|
232
|
+
return "%s/%s[%s][%s]" % (self._run_id, self._step_name, idxstr, itrstr)
|
|
226
233
|
return "%s/%s[%s]" % (self._run_id, self._step_name, idxstr)
|
|
227
234
|
|
|
228
235
|
@property
|
|
@@ -251,6 +258,72 @@ class TaskDataStore(object):
|
|
|
251
258
|
"""
|
|
252
259
|
self.save_metadata({self.METADATA_ATTEMPT_SUFFIX: {"time": time.time()}})
|
|
253
260
|
|
|
261
|
+
@only_if_not_done
|
|
262
|
+
@require_mode("w")
|
|
263
|
+
def transfer_artifacts(
|
|
264
|
+
self, other_datastore: "TaskDataStore", names: Optional[List[str]] = None
|
|
265
|
+
):
|
|
266
|
+
"""
|
|
267
|
+
Copies the blobs from other_datastore to this datastore if the datastore roots
|
|
268
|
+
are different.
|
|
269
|
+
|
|
270
|
+
This is used specifically for spin so we can bring in artifacts from the original
|
|
271
|
+
datastore.
|
|
272
|
+
|
|
273
|
+
Parameters
|
|
274
|
+
----------
|
|
275
|
+
other_datastore : TaskDataStore
|
|
276
|
+
Other datastore from which to copy artifacts from
|
|
277
|
+
names : List[str], optional, default None
|
|
278
|
+
If provided, only transfer the artifacts with these names. If None,
|
|
279
|
+
transfer all artifacts from the other datastore.
|
|
280
|
+
"""
|
|
281
|
+
if (
|
|
282
|
+
other_datastore.TYPE == self.TYPE
|
|
283
|
+
and other_datastore._storage_impl.datastore_root
|
|
284
|
+
== self._storage_impl.datastore_root
|
|
285
|
+
):
|
|
286
|
+
# Nothing to transfer -- artifacts are already saved properly
|
|
287
|
+
return
|
|
288
|
+
|
|
289
|
+
# Determine which artifacts need to be transferred
|
|
290
|
+
if names is None:
|
|
291
|
+
# Transfer all artifacts from other datastore
|
|
292
|
+
artifacts_to_transfer = list(other_datastore._objects.keys())
|
|
293
|
+
else:
|
|
294
|
+
# Transfer only specified artifacts
|
|
295
|
+
artifacts_to_transfer = [
|
|
296
|
+
name for name in names if name in other_datastore._objects
|
|
297
|
+
]
|
|
298
|
+
|
|
299
|
+
if not artifacts_to_transfer:
|
|
300
|
+
return
|
|
301
|
+
|
|
302
|
+
# Get SHA keys for artifacts to transfer
|
|
303
|
+
shas_to_transfer = [
|
|
304
|
+
other_datastore._objects[name] for name in artifacts_to_transfer
|
|
305
|
+
]
|
|
306
|
+
|
|
307
|
+
# Check which blobs are missing locally
|
|
308
|
+
missing_shas = []
|
|
309
|
+
for sha in shas_to_transfer:
|
|
310
|
+
local_path = self._ca_store._storage_impl.path_join(
|
|
311
|
+
self._ca_store._prefix, sha[:2], sha
|
|
312
|
+
)
|
|
313
|
+
if not self._ca_store._storage_impl.is_file([local_path])[0]:
|
|
314
|
+
missing_shas.append(sha)
|
|
315
|
+
|
|
316
|
+
if not missing_shas:
|
|
317
|
+
return # All blobs already exist locally
|
|
318
|
+
|
|
319
|
+
# Load blobs from other datastore in transfer mode
|
|
320
|
+
transfer_blobs = other_datastore._ca_store.load_blobs(
|
|
321
|
+
missing_shas, is_transfer=True
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
# Save blobs to local datastore in transfer mode
|
|
325
|
+
self._ca_store.save_blobs(transfer_blobs, is_transfer=True)
|
|
326
|
+
|
|
254
327
|
@only_if_not_done
|
|
255
328
|
@require_mode("w")
|
|
256
329
|
def save_artifacts(self, artifacts_iter, len_hint=0):
|
|
@@ -289,7 +362,7 @@ class TaskDataStore(object):
|
|
|
289
362
|
except (SystemError, OverflowError) as e:
|
|
290
363
|
raise DataException(
|
|
291
364
|
"Artifact *%s* is very large (over 2GB). "
|
|
292
|
-
"You need to use Python 3.
|
|
365
|
+
"You need to use Python 3.6 or newer if you want to "
|
|
293
366
|
"serialize large objects." % name
|
|
294
367
|
) from e
|
|
295
368
|
except TypeError as e:
|
|
@@ -352,7 +425,7 @@ class TaskDataStore(object):
|
|
|
352
425
|
encode_type = "gzip+pickle-v2"
|
|
353
426
|
if encode_type not in self._encodings:
|
|
354
427
|
raise DataException(
|
|
355
|
-
"Python 3.
|
|
428
|
+
"Python 3.6 or later is required to load artifact '%s'" % name
|
|
356
429
|
)
|
|
357
430
|
else:
|
|
358
431
|
to_load[self._objects[name]].append(name)
|
|
@@ -681,14 +754,16 @@ class TaskDataStore(object):
|
|
|
681
754
|
flow : FlowSpec
|
|
682
755
|
Flow to persist
|
|
683
756
|
"""
|
|
757
|
+
if not self._persist:
|
|
758
|
+
return
|
|
684
759
|
|
|
685
760
|
if flow._datastore:
|
|
686
761
|
self._objects.update(flow._datastore._objects)
|
|
687
762
|
self._info.update(flow._datastore._info)
|
|
688
763
|
|
|
689
|
-
#
|
|
690
|
-
# artifacts_iter, so we can provide a len_hint below
|
|
764
|
+
# Scan flow object FIRST
|
|
691
765
|
valid_artifacts = []
|
|
766
|
+
current_artifact_names = set()
|
|
692
767
|
for var in dir(flow):
|
|
693
768
|
if var.startswith("__") or var in flow._EPHEMERAL:
|
|
694
769
|
continue
|
|
@@ -705,6 +780,16 @@ class TaskDataStore(object):
|
|
|
705
780
|
or isinstance(val, Parameter)
|
|
706
781
|
):
|
|
707
782
|
valid_artifacts.append((var, val))
|
|
783
|
+
current_artifact_names.add(var)
|
|
784
|
+
|
|
785
|
+
# Transfer ONLY artifacts that aren't being overridden
|
|
786
|
+
if hasattr(flow._datastore, "orig_datastore"):
|
|
787
|
+
parent_artifacts = set(flow._datastore._objects.keys())
|
|
788
|
+
unchanged_artifacts = parent_artifacts - current_artifact_names
|
|
789
|
+
if unchanged_artifacts:
|
|
790
|
+
self.transfer_artifacts(
|
|
791
|
+
flow._datastore.orig_datastore, names=list(unchanged_artifacts)
|
|
792
|
+
)
|
|
708
793
|
|
|
709
794
|
def artifacts_iter():
|
|
710
795
|
# we consume the valid_artifacts list destructively to
|
|
@@ -720,6 +805,7 @@ class TaskDataStore(object):
|
|
|
720
805
|
delattr(flow, var)
|
|
721
806
|
yield var, val
|
|
722
807
|
|
|
808
|
+
# Save current artifacts
|
|
723
809
|
self.save_artifacts(artifacts_iter(), len_hint=len(valid_artifacts))
|
|
724
810
|
|
|
725
811
|
@only_if_not_done
|
metaflow/debug.py
CHANGED
|
@@ -42,6 +42,11 @@ class Debug(object):
|
|
|
42
42
|
filename = inspect.stack()[1][1]
|
|
43
43
|
print("debug[%s %s:%s]: %s" % (typ, filename, lineno, s), file=sys.stderr)
|
|
44
44
|
|
|
45
|
+
def __getattr__(self, name):
|
|
46
|
+
# Small piece of code to get pyright and other linters to recognize that there
|
|
47
|
+
# are dynamic attributes.
|
|
48
|
+
return getattr(self, name)
|
|
49
|
+
|
|
45
50
|
def noop(self, args):
|
|
46
51
|
pass
|
|
47
52
|
|