metaflow 2.15.16__py2.py3-none-any.whl → 2.15.18__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 CHANGED
@@ -1,5 +1,6 @@
1
1
  import functools
2
2
  import inspect
3
+ import os
3
4
  import sys
4
5
  import traceback
5
6
  from datetime import datetime
@@ -242,6 +243,14 @@ def version(obj):
242
243
  type=click.Choice(["local"] + [m.TYPE for m in ENVIRONMENTS]),
243
244
  help="Execution environment type",
244
245
  )
246
+ @click.option(
247
+ "--force-rebuild-environments/--no-force-rebuild-environments",
248
+ is_flag=True,
249
+ default=False,
250
+ hidden=True,
251
+ type=bool,
252
+ help="Explicitly rebuild the execution environments",
253
+ )
245
254
  # See comment for --quiet
246
255
  @click.option(
247
256
  "--datastore",
@@ -300,6 +309,7 @@ def start(
300
309
  quiet=False,
301
310
  metadata=None,
302
311
  environment=None,
312
+ force_rebuild_environments=False,
303
313
  datastore=None,
304
314
  datastore_root=None,
305
315
  decospecs=None,
@@ -435,6 +445,8 @@ def start(
435
445
  ctx.obj.environment = [
436
446
  e for e in ENVIRONMENTS + [MetaflowEnvironment] if e.TYPE == environment
437
447
  ][0](ctx.obj.flow)
448
+ # set force rebuild flag for environments that support it.
449
+ ctx.obj.environment._force_rebuild = force_rebuild_environments
438
450
  ctx.obj.environment.validate_environment(ctx.obj.logger, datastore)
439
451
 
440
452
  ctx.obj.event_logger = LOGGING_SIDECARS[event_logger](
@@ -496,7 +508,7 @@ def start(
496
508
  ctx.obj.echo,
497
509
  ctx.obj.flow_datastore,
498
510
  {
499
- k: ConfigValue(v)
511
+ k: ConfigValue(v) if v is not None else None
500
512
  for k, v in ctx.obj.flow.__class__._flow_state.get(
501
513
  _FlowState.CONFIGS, {}
502
514
  ).items()
@@ -524,7 +536,7 @@ def start(
524
536
  decorators._attach_decorators(ctx.obj.flow, all_decospecs)
525
537
  decorators._init(ctx.obj.flow)
526
538
  # Regenerate graph if we attached more decorators
527
- ctx.obj.flow.__class__._init_attrs()
539
+ ctx.obj.flow.__class__._init_graph()
528
540
  ctx.obj.graph = ctx.obj.flow._graph
529
541
 
530
542
  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__._init_attrs()
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)
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
- cls._init_attrs()
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._init_attrs()
340
+ cls._init_graph()
329
341
  return cls
330
342
 
331
343
  def _set_constants(self, graph, kwargs, config_options):
@@ -214,8 +214,6 @@ CARD_GSROOT = from_conf(
214
214
  )
215
215
  CARD_NO_WARNING = from_conf("CARD_NO_WARNING", False)
216
216
 
217
- SKIP_CARD_DUALWRITE = from_conf("SKIP_CARD_DUALWRITE", False)
218
-
219
217
  RUNTIME_CARD_RENDER_INTERVAL = from_conf("RUNTIME_CARD_RENDER_INTERVAL", 60)
220
218
 
221
219
  # Azure storage account URL
@@ -370,6 +368,8 @@ KUBERNETES_CONTAINER_IMAGE = from_conf(
370
368
  )
371
369
  # Image pull policy for container images
372
370
  KUBERNETES_IMAGE_PULL_POLICY = from_conf("KUBERNETES_IMAGE_PULL_POLICY", None)
371
+ # Image pull secrets for container images
372
+ KUBERNETES_IMAGE_PULL_SECRETS = from_conf("KUBERNETES_IMAGE_PULL_SECRETS", "")
373
373
  # Default container registry for K8S
374
374
  KUBERNETES_CONTAINER_REGISTRY = from_conf(
375
375
  "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
 
@@ -16,7 +16,6 @@ from metaflow.metaflow_config import (
16
16
  CARD_SUFFIX,
17
17
  CARD_AZUREROOT,
18
18
  CARD_GSROOT,
19
- SKIP_CARD_DUALWRITE,
20
19
  )
21
20
  import metaflow.metaflow_config as metaflow_config
22
21
 
@@ -231,23 +230,6 @@ class CardDatastore(object):
231
230
 
232
231
  def save_card(self, uuid, card_type, card_html, card_id=None, overwrite=True):
233
232
  card_file_name = card_type
234
- # TEMPORARY_WORKAROUND: FIXME (LATER) : Fix the duplication of below block in a few months.
235
- # Check file blame to understand the age of this temporary workaround.
236
-
237
- # This function will end up saving cards at two locations.
238
- # Thereby doubling the number of cards. (Which is a temporary fix)
239
- # Why do this ? :
240
- # When cards were introduced there was an assumption made about task-ids being unique.
241
- # This assumption was incorrect.
242
- # Only the pathspec needs to be unique but there is no such guarantees about task-ids.
243
- # When task-ids are non-unique, card read would result in finding incorrect cards.
244
- # This happens because cards were stored based on task-ids.
245
- # If we immediately switch from storing based on task-ids to a step-name abstraction folder,
246
- # then card reading will crash for many users.
247
- # It would especially happen for users who are accessing cards created by a newer
248
- # MF client from an older version of MF client.
249
- # It will also easily end up breaking the metaflow-ui (which maybe using a client from an older version).
250
- # Hence, we are writing cards to both paths so that we can introduce breaking changes later in the future.
251
233
  card_path_with_steps = self.get_card_location(
252
234
  self._get_card_write_path(),
253
235
  card_file_name,
@@ -255,24 +237,10 @@ class CardDatastore(object):
255
237
  card_id=card_id,
256
238
  suffix=CardNameSuffix.CARD,
257
239
  )
258
- if SKIP_CARD_DUALWRITE:
259
- self._backend.save_bytes(
260
- [(card_path_with_steps, BytesIO(bytes(card_html, "utf-8")))],
261
- overwrite=overwrite,
262
- )
263
- else:
264
- card_path_without_steps = self.get_card_location(
265
- self._get_card_read_path(with_steps=False),
266
- card_file_name,
267
- uuid,
268
- card_id=card_id,
269
- suffix=CardNameSuffix.CARD,
270
- )
271
- for cp in [card_path_with_steps, card_path_without_steps]:
272
- self._backend.save_bytes(
273
- [(cp, BytesIO(bytes(card_html, "utf-8")))], overwrite=overwrite
274
- )
275
-
240
+ self._backend.save_bytes(
241
+ [(card_path_with_steps, BytesIO(bytes(card_html, "utf-8")))],
242
+ overwrite=overwrite,
243
+ )
276
244
  return self.info_from_path(card_path_with_steps, suffix=CardNameSuffix.CARD)
277
245
 
278
246
  def _list_card_paths(self, card_type=None, card_hash=None, card_id=None):
@@ -283,6 +251,10 @@ class CardDatastore(object):
283
251
  )
284
252
 
285
253
  if len(card_paths_with_steps) == 0:
254
+ # The listing logic is reading the cards with steps and without steps
255
+ # because earlier versions of clients (ones that wrote cards before June 2022),
256
+ # would have written cards without steps. So as a fallback we will try to check for the
257
+ # cards without steps.
286
258
  card_paths_without_steps = self._backend.list_content(
287
259
  [self._get_card_read_path(with_steps=False)]
288
260
  )
@@ -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
- # TODO (savin): Support image_pull_secrets
218
- # image_pull_secrets=?,
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
- # TODO (savin): Support image_pull_secrets
722
- # image_pull_secrets=?,
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
  #
@@ -32,6 +32,7 @@ class CondaEnvironmentException(MetaflowException):
32
32
  class CondaEnvironment(MetaflowEnvironment):
33
33
  TYPE = "conda"
34
34
  _filecache = None
35
+ _force_rebuild = False
35
36
 
36
37
  def __init__(self, flow):
37
38
  self.flow = flow
@@ -71,7 +72,7 @@ class CondaEnvironment(MetaflowEnvironment):
71
72
  self.logger = make_thread_safe(logger)
72
73
 
73
74
  # TODO: Wire up logging
74
- micromamba = Micromamba(self.logger)
75
+ micromamba = Micromamba(self.logger, self._force_rebuild)
75
76
  self.solvers = {"conda": micromamba, "pypi": Pip(micromamba, self.logger)}
76
77
 
77
78
  def init_environment(self, echo, only_steps=None):
@@ -107,7 +108,10 @@ class CondaEnvironment(MetaflowEnvironment):
107
108
  return (
108
109
  id_,
109
110
  (
110
- self.read_from_environment_manifest([id_, platform, type_])
111
+ (
112
+ not self._force_rebuild
113
+ and self.read_from_environment_manifest([id_, platform, type_])
114
+ )
111
115
  or self.write_to_environment_manifest(
112
116
  [id_, platform, type_],
113
117
  self.solvers[type_].solve(id_, **environment),
@@ -153,7 +157,7 @@ class CondaEnvironment(MetaflowEnvironment):
153
157
  _meta = copy.deepcopy(local_packages)
154
158
  for id_, packages, _, _ in results:
155
159
  for package in packages:
156
- if package.get("path"):
160
+ if package.get("path") and not self._force_rebuild:
157
161
  # Cache only those packages that manifest is unaware of
158
162
  local_packages.pop(package["url"], None)
159
163
  else:
@@ -186,7 +190,7 @@ class CondaEnvironment(MetaflowEnvironment):
186
190
  storage.save_bytes(
187
191
  list_of_path_and_filehandle,
188
192
  len_hint=len(list_of_path_and_filehandle),
189
- # overwrite=True,
193
+ overwrite=self._force_rebuild,
190
194
  )
191
195
  for id_, packages, _, platform in results:
192
196
  if id_ in dirty:
@@ -2,6 +2,7 @@ import functools
2
2
  import json
3
3
  import os
4
4
  import re
5
+ import shutil
5
6
  import subprocess
6
7
  import tempfile
7
8
  import time
@@ -30,7 +31,7 @@ _double_equal_match = re.compile("==(?=[<=>!~])")
30
31
 
31
32
 
32
33
  class Micromamba(object):
33
- def __init__(self, logger=None):
34
+ def __init__(self, logger=None, force_rebuild=False):
34
35
  # micromamba is a tiny version of the mamba package manager and comes with
35
36
  # metaflow specific performance enhancements.
36
37
 
@@ -60,6 +61,8 @@ class Micromamba(object):
60
61
  # which causes a race condition in case micromamba needs to be installed first.
61
62
  self.install_mutex = Lock()
62
63
 
64
+ self.force_rebuild = force_rebuild
65
+
63
66
  @property
64
67
  def bin(self) -> str:
65
68
  "Defer installing Micromamba until when the binary path is actually requested"
@@ -152,6 +155,11 @@ class Micromamba(object):
152
155
  keyword="metaflow", # indicates metaflow generated environment
153
156
  id=id_,
154
157
  )
158
+ # If we are forcing a rebuild of the environment, we make sure to remove existing files beforehand.
159
+ # This is to ensure that no irrelevant packages get bundled relative to the resolved environment.
160
+ # NOTE: download always happens before create, so we want to do the cleanup here instead.
161
+ if self.force_rebuild:
162
+ shutil.rmtree(self.path_to_environment(id_, platform), ignore_errors=True)
155
163
 
156
164
  # cheap check
157
165
  if os.path.exists(f"{prefix}/fake.done"):
@@ -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] = ConfigValue(read_value)
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] = ConfigValue(read_value)
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.16"
1
+ metaflow_version = "2.15.18"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaflow
3
- Version: 2.15.16
3
+ Version: 2.15.18
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.16; extra == "stubs"
29
+ Requires-Dist: metaflow-stubs==2.15.18; 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=XqGP8mNObMO0lOJmWtQvFFWUEKWMN_3-cGkvci2n6e4,21296
4
+ metaflow/cli.py,sha256=ype7221pgVp3sFXTT4YpLmEx0yLahYD9UuHizLCbIT0,21714
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=GgbTeUBtG3AmZwIF-prRFMsZqFYGVysd5xBS9IPIPBs,35953
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=Z85cjfTXah5oyQue3JcHcwqxKwxkcrC_FZJfJ8JRx7o,23924
19
+ metaflow/metaflow_config.py,sha256=wVREyuJvQ8EyWDhkQ8c_A11dh1CcIA5HFjohp7CEsHE,23982
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=YpO6EM1pbJPb-iNbMpxXLeHlRbuglsV3WHXkWdqr2gA,29
40
+ metaflow/version.py,sha256=aFD_zYUJd11BSUf4DN7nX_rYimfrx-sNGZXun2I_e-g,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=F12_xYqVdkL2doP2ADI3cA41Izce5_zr1khJCLl77YA,11304
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
@@ -206,7 +206,7 @@ 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=oX-e4o_CxTQP5DJ7zMQwckcobXZJz6hPxLs3fsHSnm8,186544
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
@@ -248,7 +248,7 @@ metaflow/plugins/cards/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
248
248
  metaflow/plugins/cards/card_cli.py,sha256=XyiU5f6i_xjFHPyowWGs9mKQm9fm3dK6id-IKsoe9cY,35177
249
249
  metaflow/plugins/cards/card_client.py,sha256=30dFBoC3axc261GeV7QCIs_V1OHhRtS31S0wEWsjw90,9501
250
250
  metaflow/plugins/cards/card_creator.py,sha256=vRz1EUFa4xQ1fUIWzqyACViC6D7KGFaq5XlLIEssXTI,7741
251
- metaflow/plugins/cards/card_datastore.py,sha256=3K19wE0CZVvOpuYUytftIYYnHHn3pMZJE87FMD6OYlM,14244
251
+ metaflow/plugins/cards/card_datastore.py,sha256=bPLjBFWNlAgIjONAb0IjYXMmp9vMYlh3EYhRjAlDA0U,12714
252
252
  metaflow/plugins/cards/card_decorator.py,sha256=nU-uZ4_ubU7bCsSb6uT61YnN8ruo43_FzqZ24MsZpKg,12070
253
253
  metaflow/plugins/cards/card_resolver.py,sha256=bjyujYpGUFbLJNwXNGHlHhL4f-gVdVKebl7XW1vWDtE,717
254
254
  metaflow/plugins/cards/card_server.py,sha256=DHv0RcepaPULWbkDahiEMrU5A281Cfb0DvHLUYd8JsU,11772
@@ -313,12 +313,12 @@ 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=EUO2RepV4eudwoPv2Jha7w9f_h7sRT0gmwuVAqOWV2c,29832
317
- metaflow/plugins/kubernetes/kubernetes_cli.py,sha256=fMpUUwfIaZ2vs_cH2q1r0iged2J4skTAYT0YrhLy3hY,14103
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=aA7nNxgXep9jFR7xBVWTL3cFej0kofA2dcZSBnSNPx0,31403
320
- metaflow/plugins/kubernetes/kubernetes_job.py,sha256=Eew4a7T7xbJvLeIFnLQzWU9fkRg92RHrFCaE8sCcfa4,32175
321
- metaflow/plugins/kubernetes/kubernetes_jobsets.py,sha256=Q1PBtj_p8ofx46DRjO-7HN8Lt-ZZHwC6CD1JDF3Labo,42903
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
@@ -327,8 +327,8 @@ metaflow/plugins/metadata_providers/service.py,sha256=5UlK0R5M9_nq2J6MgJgCZwqAC3
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
330
- metaflow/plugins/pypi/conda_environment.py,sha256=C7WolJm1dgBQofd6vOk8KCr3U754TyAr4bOpkhosxfM,24582
331
- metaflow/plugins/pypi/micromamba.py,sha256=XAuZulI7O2Q_Zgtx28yjAqHco6tHiPQxoy_vsf1kWm8,16843
330
+ metaflow/plugins/pypi/conda_environment.py,sha256=6QgHphwgXBob_C_ObpKL-4i2R7dN3XPn0ddlPCzu5tc,24771
331
+ metaflow/plugins/pypi/micromamba.py,sha256=UltfY8NmLphfZ-AbpaMFIdxIeOXLdTYDrMrabvPrYVU,17352
332
332
  metaflow/plugins/pypi/parsers.py,sha256=gpOOG2Ph95wI73MWCAi7XjpK0gYhv5k5YIGBs73QPuE,8556
333
333
  metaflow/plugins/pypi/pip.py,sha256=WhPyA18RoVT40sqbZRJdCEij4euL9PZwLfm1SrAKqmU,14333
334
334
  metaflow/plugins/pypi/pypi_decorator.py,sha256=ybNgo-T5Z_0W2KNuED0pdjyI0qygZ4a1MXAzKqdHt_E,7250
@@ -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=qCKVAvd0NKgaCxQ2OThes5-DYHXq6A1HqURubYNeFdw,20481
390
- metaflow/user_configs/config_options.py,sha256=aB53M-2WkDPo_TRLAcC8v89Wy8-oxflfW4l-xlb5pDI,21089
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.16.data/data/share/metaflow/devtools/Makefile,sha256=5n89OGIC_kE4wxtEI66VCucN-b-1w5bqvGeZYmeRGz8,13737
393
- metaflow-2.15.16.data/data/share/metaflow/devtools/Tiltfile,sha256=P5_rn_F3xYLN1_cEAQ9mNeS22HG2rb8beKIz2RIK6fU,20634
394
- metaflow-2.15.16.data/data/share/metaflow/devtools/pick_services.sh,sha256=DCnrMXwtApfx3B4S-YiZESMyAFHbXa3VuNL0MxPLyiE,2196
395
- metaflow-2.15.16.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
396
- metaflow-2.15.16.dist-info/METADATA,sha256=tJxdSSfjh56YThcF7BrwHK50l86Ku5Pb-KFZt0nSiyU,6742
397
- metaflow-2.15.16.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
398
- metaflow-2.15.16.dist-info/entry_points.txt,sha256=RvEq8VFlgGe_FfqGOZi0D7ze1hLD0pAtXeNyGfzc_Yc,103
399
- metaflow-2.15.16.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
400
- metaflow-2.15.16.dist-info/RECORD,,
392
+ metaflow-2.15.18.data/data/share/metaflow/devtools/Makefile,sha256=5n89OGIC_kE4wxtEI66VCucN-b-1w5bqvGeZYmeRGz8,13737
393
+ metaflow-2.15.18.data/data/share/metaflow/devtools/Tiltfile,sha256=P5_rn_F3xYLN1_cEAQ9mNeS22HG2rb8beKIz2RIK6fU,20634
394
+ metaflow-2.15.18.data/data/share/metaflow/devtools/pick_services.sh,sha256=DCnrMXwtApfx3B4S-YiZESMyAFHbXa3VuNL0MxPLyiE,2196
395
+ metaflow-2.15.18.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
396
+ metaflow-2.15.18.dist-info/METADATA,sha256=SNMazx7rUE5-fmaqxAv1-7KxPXKDAojZyRqLBCzLZEo,6742
397
+ metaflow-2.15.18.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
398
+ metaflow-2.15.18.dist-info/entry_points.txt,sha256=RvEq8VFlgGe_FfqGOZi0D7ze1hLD0pAtXeNyGfzc_Yc,103
399
+ metaflow-2.15.18.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
400
+ metaflow-2.15.18.dist-info/RECORD,,