metaflow 2.18.11__py2.py3-none-any.whl → 2.18.13__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/graph.py CHANGED
@@ -94,7 +94,7 @@ class DAGNode(object):
94
94
  case_key = None
95
95
 
96
96
  # handle string literals
97
- if isinstance(key, ast.Str):
97
+ if hasattr(ast, "Str") and isinstance(key, ast.Str):
98
98
  case_key = key.s
99
99
  elif isinstance(key, ast.Constant):
100
100
  case_key = key.value
@@ -171,7 +171,7 @@ class DAGNode(object):
171
171
  # Get condition parameter
172
172
  for keyword in tail.value.keywords:
173
173
  if keyword.arg == "condition":
174
- if isinstance(keyword.value, ast.Str):
174
+ if hasattr(ast, "Str") and isinstance(keyword.value, ast.Str):
175
175
  condition_name = keyword.value.s
176
176
  elif isinstance(keyword.value, ast.Constant) and isinstance(
177
177
  keyword.value.value, str
@@ -121,6 +121,8 @@ class ArgoWorkflows(object):
121
121
  incident_io_metadata: List[str] = None,
122
122
  enable_heartbeat_daemon=True,
123
123
  enable_error_msg_capture=False,
124
+ workflow_title=None,
125
+ workflow_description=None,
124
126
  ):
125
127
  # Some high-level notes -
126
128
  #
@@ -177,6 +179,8 @@ class ArgoWorkflows(object):
177
179
  )
178
180
  self.enable_heartbeat_daemon = enable_heartbeat_daemon
179
181
  self.enable_error_msg_capture = enable_error_msg_capture
182
+ self.workflow_title = workflow_title
183
+ self.workflow_description = workflow_description
180
184
  self.parameters = self._process_parameters()
181
185
  self.config_parameters = self._process_config_parameters()
182
186
  self.triggers, self.trigger_options = self._process_triggers()
@@ -430,6 +434,25 @@ class ArgoWorkflows(object):
430
434
  "metaflow/project_flow_name": current.project_flow_name,
431
435
  }
432
436
  )
437
+
438
+ # Add Argo Workflows title and description annotations
439
+ # https://argo-workflows.readthedocs.io/en/latest/title-and-description/
440
+ # Use CLI-provided values or auto-populate from metadata
441
+ title = (
442
+ (self.workflow_title.strip() if self.workflow_title else None)
443
+ or current.get("project_flow_name")
444
+ or self.flow.name
445
+ )
446
+
447
+ description = (
448
+ self.workflow_description.strip() if self.workflow_description else None
449
+ ) or (self.flow.__doc__.strip() if self.flow.__doc__ else None)
450
+
451
+ if title:
452
+ annotations["workflows.argoproj.io/title"] = title
453
+ if description:
454
+ annotations["workflows.argoproj.io/description"] = description
455
+
433
456
  return annotations
434
457
 
435
458
  def _get_schedule(self):
@@ -586,7 +609,16 @@ class ArgoWorkflows(object):
586
609
  # the JSON equivalent of None to please argo-workflows. Unfortunately it
587
610
  # has the side effect of casting the parameter value to string null during
588
611
  # execution - which needs to be fixed imminently.
589
- if not is_required or default_value is not None:
612
+ if default_value is None:
613
+ default_value = json.dumps(None)
614
+ elif param_type == "JSON":
615
+ if not isinstance(default_value, str):
616
+ # once to serialize the default value if needed.
617
+ default_value = json.dumps(default_value)
618
+ # adds outer quotes to param
619
+ default_value = json.dumps(default_value)
620
+ else:
621
+ # Make argo sensors happy
590
622
  default_value = json.dumps(default_value)
591
623
 
592
624
  parameters[param.name] = dict(
@@ -894,7 +926,16 @@ class ArgoWorkflows(object):
894
926
  .annotations(
895
927
  {
896
928
  **annotations,
897
- **self._base_annotations,
929
+ **{
930
+ k: v
931
+ for k, v in self._base_annotations.items()
932
+ if k
933
+ # Skip custom title/description for workflows as this makes it harder to find specific runs.
934
+ not in [
935
+ "workflows.argoproj.io/title",
936
+ "workflows.argoproj.io/description",
937
+ ]
938
+ },
898
939
  **{"metaflow/run_id": "argo-{{workflow.name}}"},
899
940
  }
900
941
  )
@@ -909,11 +950,7 @@ class ArgoWorkflows(object):
909
950
  Arguments().parameters(
910
951
  [
911
952
  Parameter(parameter["name"])
912
- .value(
913
- "'%s'" % parameter["value"]
914
- if parameter["type"] == "JSON"
915
- else parameter["value"]
916
- )
953
+ .value(parameter["value"])
917
954
  .description(parameter.get("description"))
918
955
  # TODO: Better handle IncludeFile in Argo Workflows UI.
919
956
  for parameter in self.parameters.values()
@@ -2022,7 +2059,7 @@ class ArgoWorkflows(object):
2022
2059
  # {{foo.bar['param_name']}}.
2023
2060
  # https://argoproj.github.io/argo-events/tutorials/02-parameterization/
2024
2061
  # http://masterminds.github.io/sprig/strings.html
2025
- "--%s={{workflow.parameters.%s}}"
2062
+ "--%s=\\\"$(python -m metaflow.plugins.argo.param_val {{=toBase64(workflow.parameters['%s'])}})\\\""
2026
2063
  % (parameter["name"], parameter["name"])
2027
2064
  for parameter in self.parameters.values()
2028
2065
  ]
@@ -3810,37 +3847,27 @@ class ArgoWorkflows(object):
3810
3847
  # NOTE: We need the conditional logic in order to successfully fall back to the default value
3811
3848
  # when the event payload does not contain a key for a parameter.
3812
3849
  # NOTE: Keys might contain dashes, so use the safer 'get' for fetching the value
3813
- data_template='{{ if (hasKey $.Input.body.payload "%s") }}{{- (get $.Input.body.payload "%s" %s) -}}{{- else -}}{{ (fail "use-default-instead") }}{{- end -}}'
3850
+ data_template='{{ if (hasKey $.Input.body.payload "%s") }}%s{{- else -}}{{ (fail "use-default-instead") }}{{- end -}}'
3814
3851
  % (
3815
- v,
3816
3852
  v,
3817
3853
  (
3818
- "| toRawJson | squote"
3854
+ '{{- $pv:=(get $.Input.body.payload "%s") -}}{{ if kindIs "string" $pv }}{{- $pv | toRawJson -}}{{- else -}}{{ $pv | toRawJson | toRawJson }}{{- end -}}'
3855
+ % v
3819
3856
  if self.parameters[
3820
3857
  parameter_name
3821
3858
  ]["type"]
3822
3859
  == "JSON"
3823
- else "| toRawJson"
3860
+ else '{{- (get $.Input.body.payload "%s" | toRawJson) -}}'
3861
+ % v
3824
3862
  ),
3825
3863
  ),
3826
3864
  # Unfortunately the sensor needs to
3827
3865
  # record the default values for
3828
3866
  # the parameters - there doesn't seem
3829
3867
  # to be any way for us to skip
3830
- value=(
3831
- json.dumps(
3832
- self.parameters[parameter_name][
3833
- "value"
3834
- ]
3835
- )
3836
- if self.parameters[parameter_name][
3837
- "type"
3838
- ]
3839
- == "JSON"
3840
- else self.parameters[
3841
- parameter_name
3842
- ]["value"]
3843
- ),
3868
+ value=self.parameters[parameter_name][
3869
+ "value"
3870
+ ],
3844
3871
  )
3845
3872
  .dest(
3846
3873
  # this undocumented (mis?)feature in
@@ -227,6 +227,18 @@ def argo_workflows(obj, name=None):
227
227
  show_default=True,
228
228
  help="Capture stack trace of first failed task in exit hook.",
229
229
  )
230
+ @click.option(
231
+ "--workflow-title",
232
+ default=None,
233
+ type=str,
234
+ help="Custom title for the workflow displayed in Argo Workflows UI. Defaults to `project_flow_name`. Supports markdown formatting.",
235
+ )
236
+ @click.option(
237
+ "--workflow-description",
238
+ default=None,
239
+ type=str,
240
+ help="Custom description for the workflow displayed in Argo Workflows UI. Defaults to the flow's docstring if available. Supports markdown formatting and multi-line text.",
241
+ )
230
242
  @click.pass_obj
231
243
  def create(
232
244
  obj,
@@ -248,6 +260,8 @@ def create(
248
260
  incident_io_alert_source_config_id=None,
249
261
  incident_io_metadata=None,
250
262
  enable_heartbeat_daemon=True,
263
+ workflow_title=None,
264
+ workflow_description=None,
251
265
  deployer_attribute_file=None,
252
266
  enable_error_msg_capture=False,
253
267
  ):
@@ -312,6 +326,8 @@ def create(
312
326
  incident_io_metadata,
313
327
  enable_heartbeat_daemon,
314
328
  enable_error_msg_capture,
329
+ workflow_title,
330
+ workflow_description,
315
331
  )
316
332
 
317
333
  if only_json:
@@ -658,6 +674,8 @@ def make_flow(
658
674
  incident_io_metadata,
659
675
  enable_heartbeat_daemon,
660
676
  enable_error_msg_capture,
677
+ workflow_title,
678
+ workflow_description,
661
679
  ):
662
680
  # TODO: Make this check less specific to Amazon S3 as we introduce
663
681
  # support for more cloud object stores.
@@ -750,6 +768,8 @@ def make_flow(
750
768
  incident_io_metadata=incident_io_metadata,
751
769
  enable_heartbeat_daemon=enable_heartbeat_daemon,
752
770
  enable_error_msg_capture=enable_error_msg_capture,
771
+ workflow_title=workflow_title,
772
+ workflow_description=workflow_description,
753
773
  )
754
774
 
755
775
 
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  import os
3
- from datetime import datetime
3
+ from datetime import datetime, timezone
4
4
 
5
5
  ###
6
6
  # Algorithm to determine 1st error:
@@ -26,6 +26,9 @@ def parse_workflow_failures():
26
26
  def group_failures_by_template(failures):
27
27
  groups = {}
28
28
  for failure in failures:
29
+ if failure.get("finishedAt", None) is None:
30
+ timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
31
+ failure["finishedAt"] = timestamp
29
32
  groups.setdefault(failure["templateName"], []).append(failure)
30
33
  return groups
31
34
 
@@ -53,7 +56,7 @@ def determine_first_error():
53
56
  grouped_failures = group_failures_by_template(failures)
54
57
  for group in grouped_failures.values():
55
58
  group.sort(
56
- key=lambda x: datetime.strptime(x["finishedAt"], "%Y-%m-%dT%H:%M:%SZ")
59
+ key=lambda g: datetime.strptime(g["finishedAt"], "%Y-%m-%dT%H:%M:%SZ")
57
60
  )
58
61
 
59
62
  earliest_group = grouped_failures[
@@ -0,0 +1,19 @@
1
+ import sys
2
+ import base64
3
+ import json
4
+
5
+
6
+ def parse_parameter_value(base64_value):
7
+ val = base64.b64decode(base64_value).decode("utf-8")
8
+
9
+ try:
10
+ return json.loads(val)
11
+ except json.decoder.JSONDecodeError:
12
+ # fallback to using the original value.
13
+ return val
14
+
15
+
16
+ if __name__ == "__main__":
17
+ base64_val = sys.argv[1]
18
+
19
+ print(parse_parameter_value(base64_val))
@@ -1,7 +1,3 @@
1
- """
2
-
3
- """
4
-
5
1
  from collections import namedtuple
6
2
  from io import BytesIO
7
3
  import os
@@ -67,20 +63,18 @@ class CardDatastore(object):
67
63
  result = CARD_LOCALROOT
68
64
  if result is None:
69
65
  current_path = os.getcwd()
70
- check_dir = os.path.join(current_path, DATASTORE_LOCAL_DIR, CARD_SUFFIX)
66
+ check_dir = os.path.join(current_path, DATASTORE_LOCAL_DIR)
71
67
  check_dir = os.path.realpath(check_dir)
72
68
  orig_path = check_dir
73
69
  while not os.path.isdir(check_dir):
74
70
  new_path = os.path.dirname(current_path)
75
71
  if new_path == current_path:
76
- break # We are no longer making upward progress
72
+ # No longer making upward progress so we
73
+ # return the top level path
74
+ return os.path.join(orig_path, CARD_SUFFIX)
77
75
  current_path = new_path
78
- check_dir = os.path.join(
79
- current_path, DATASTORE_LOCAL_DIR, CARD_SUFFIX
80
- )
81
- result = orig_path
82
-
83
- return result
76
+ check_dir = os.path.join(current_path, DATASTORE_LOCAL_DIR)
77
+ return os.path.join(check_dir, CARD_SUFFIX)
84
78
  else:
85
79
  # Let's make it obvious we need to update this block for each new datastore backend...
86
80
  raise NotImplementedError(
@@ -15,6 +15,7 @@ from .renderer_tools import render_safely
15
15
  from .json_viewer import JSONViewer as _JSONViewer, YAMLViewer as _YAMLViewer
16
16
  import uuid
17
17
  import inspect
18
+ import textwrap
18
19
 
19
20
 
20
21
  def _warning_with_component(component, msg):
@@ -656,19 +657,38 @@ class Markdown(UserComponent):
656
657
  )
657
658
  ```
658
659
 
660
+ Multi-line strings with indentation are automatically dedented:
661
+ ```
662
+ current.card.append(
663
+ Markdown(f'''
664
+ # Header
665
+ - Item 1
666
+ - Item 2
667
+ ''')
668
+ )
669
+ ```
670
+
659
671
  Parameters
660
672
  ----------
661
673
  text : str
662
- Text formatted in Markdown.
674
+ Text formatted in Markdown. Leading whitespace common to all lines
675
+ is automatically removed to support indented multi-line strings.
663
676
  """
664
677
 
665
678
  REALTIME_UPDATABLE = True
666
679
 
680
+ @staticmethod
681
+ def _dedent_text(text):
682
+ """Remove common leading whitespace from all lines."""
683
+ if text is None:
684
+ return None
685
+ return textwrap.dedent(text)
686
+
667
687
  def update(self, text=None):
668
- self._text = text
688
+ self._text = self._dedent_text(text)
669
689
 
670
690
  def __init__(self, text=None):
671
- self._text = text
691
+ self._text = self._dedent_text(text)
672
692
 
673
693
  @with_default_component_id
674
694
  @render_safely
@@ -351,8 +351,10 @@ class MetaflowAPI(object):
351
351
  class_dict = {
352
352
  "__module__": "metaflow",
353
353
  "_API_NAME": flow_file,
354
- "_internal_getattr": functools.partial(
355
- _lazy_load_command, cli_collection, "_compute_flow_parameters"
354
+ "_internal_getattr": staticmethod(
355
+ functools.partial(
356
+ _lazy_load_command, cli_collection, "_compute_flow_parameters"
357
+ )
356
358
  ),
357
359
  "__getattr__": getattr_wrapper,
358
360
  }
metaflow/runner/utils.py CHANGED
@@ -109,7 +109,6 @@ def read_from_fifo_when_ready(
109
109
  content = bytearray()
110
110
  poll = select.poll()
111
111
  poll.register(fifo_fd, select.POLLIN)
112
- max_timeout = 3 # Wait for 10 * 3 = 30 ms after last write
113
112
  while True:
114
113
  if check_process_exited(command_obj) and command_obj.process.returncode != 0:
115
114
  raise CalledProcessError(
@@ -137,15 +136,16 @@ def read_from_fifo_when_ready(
137
136
  else:
138
137
  # We had no events (just a timeout) and the read didn't return
139
138
  # an exception so the file is still open; we continue waiting for data
140
- # Unfortunately, on MacOS, it seems that even *after* the file is
141
- # closed on the other end, we still don't get a BlockingIOError so
142
- # we hack our way and timeout if there is no write in 30ms which is
143
- # a relative eternity for file writes.
144
- if content:
145
- if max_timeout <= 0:
146
- break
147
- max_timeout -= 1
148
- continue
139
+ # On some systems (notably MacOS), even after the file is closed on the
140
+ # other end, we may not get a BlockingIOError or proper EOF signal.
141
+ # Instead of using an arbitrary timeout, check if the writer process
142
+ # has actually exited. If it has and we have content, we can safely
143
+ # assume EOF. If the process is still running, continue waiting.
144
+ if content and check_process_exited(command_obj):
145
+ # Process has exited and we got an empty read with no poll events.
146
+ # This is EOF - break out to return the content we've collected.
147
+ break
148
+ # else: process is still running, continue waiting for more data
149
149
  except BlockingIOError:
150
150
  has_blocking_error = True
151
151
  if content:
metaflow/version.py CHANGED
@@ -1 +1 @@
1
- metaflow_version = "2.18.11"
1
+ metaflow_version = "2.18.13"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaflow
3
- Version: 2.18.11
3
+ Version: 2.18.13
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.18.11; extra == "stubs"
29
+ Requires-Dist: metaflow-stubs==2.18.13; extra == "stubs"
30
30
  Dynamic: author
31
31
  Dynamic: author-email
32
32
  Dynamic: classifier
@@ -11,7 +11,7 @@ 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
13
  metaflow/flowspec.py,sha256=9wsO2_QoO_VHKusKdpslfbwQREOwf0fAzF-DSEA0iZ8,41968
14
- metaflow/graph.py,sha256=UOeClj-JeORRlZWOQMI1CirkrCpTvVWvRcSwODCajMg,19263
14
+ metaflow/graph.py,sha256=b7-5hStqurdTO0RFVEhtUcwrPh2Xt3gTZkAE_B2LSOM,19311
15
15
  metaflow/includefile.py,sha256=NXERo_halboBCjvnS5iCjnBMyCMlQMnT2mRe6kxl2xU,21978
16
16
  metaflow/integrations.py,sha256=LlsaoePRg03DjENnmLxZDYto3NwWc9z_PtU6nJxLldg,1480
17
17
  metaflow/lint.py,sha256=A2NdUq_MnQal_RUCMC8ZOSR0VYZGyi2mSgwPQB0UzQo,15343
@@ -36,7 +36,7 @@ metaflow/tuple_util.py,sha256=_G5YIEhuugwJ_f6rrZoelMFak3DqAR2tt_5CapS1XTY,830
36
36
  metaflow/unbounded_foreach.py,sha256=p184WMbrMJ3xKYHwewj27ZhRUsSj_kw1jlye5gA9xJk,387
37
37
  metaflow/util.py,sha256=g2SOU_CRzJLgDM_UGF9QDMANMAIHAsDRXE6S76_YzsY,14594
38
38
  metaflow/vendor.py,sha256=A82CGHfStZGDP5pQ5XzRjFkbN1ZC-vFmghXIrzMDDNg,5868
39
- metaflow/version.py,sha256=q3OkFrD1pVtgUDvcF5KfpBd3SSEX2AEsbdqVS9ReFy4,29
39
+ metaflow/version.py,sha256=x5086WE7AkSw0-UOZF9Q1QaMHEZPAruxlGoHg71vRXs,29
40
40
  metaflow/_vendor/__init__.py,sha256=y_CiwUD3l4eAKvTVDZeqgVujMy31cAM1qjAB-HfI-9s,353
41
41
  metaflow/_vendor/typing_extensions.py,sha256=q9zxWa6p6CzF1zZvSkygSlklduHf_b3K7MCxGz7MJRc,134519
42
42
  metaflow/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425
@@ -231,16 +231,17 @@ metaflow/plugins/airflow/sensors/s3_sensor.py,sha256=iDReG-7FKnumrtQg-HY6cCUAAqN
231
231
  metaflow/plugins/argo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
232
232
  metaflow/plugins/argo/argo_client.py,sha256=oT4ZrCyE7CYEbqNN0SfoZfSHd5fYW9XtuOrQEiUd1co,17230
233
233
  metaflow/plugins/argo/argo_events.py,sha256=_C1KWztVqgi3zuH57pInaE9OzABc2NnncC-zdwOMZ-w,5909
234
- metaflow/plugins/argo/argo_workflows.py,sha256=r__mx04QOPbpBEe2c7F23NKn93-KPWhmU7LCh0Gx2cw,216218
235
- metaflow/plugins/argo/argo_workflows_cli.py,sha256=-blfZp-kAS8oWFTarfou9gRyE4QCnnJwa-0g8QuE0zk,52280
234
+ metaflow/plugins/argo/argo_workflows.py,sha256=eq_Q4gxjHoZuJItPKYjZvku_J3mc56g3GpMlSQTIiKE,217407
235
+ metaflow/plugins/argo/argo_workflows_cli.py,sha256=GRDsiE8QT9HEdeAUODtyyGiqePhShSkwJJ8tiPQwwiI,52992
236
236
  metaflow/plugins/argo/argo_workflows_decorator.py,sha256=CLSjPqFTGucZ2_dSQGAYkoWWUZBQ9TCBXul4rxhDj3w,8282
237
237
  metaflow/plugins/argo/argo_workflows_deployer.py,sha256=6kHxEnYXJwzNCM9swI8-0AckxtPWqwhZLerYkX8fxUM,4444
238
238
  metaflow/plugins/argo/argo_workflows_deployer_objects.py,sha256=ydBE-lP42eNKvep36nQdUBPS3rQQErvoA7rCgyp5M6I,14949
239
- metaflow/plugins/argo/capture_error.py,sha256=Ys9dscGrTpW-ZCirLBU0gD9qBM0BjxyxGlUMKcwewQc,1852
239
+ metaflow/plugins/argo/capture_error.py,sha256=9ggbGHyR9UBPswOqAHCbpE9kdXuV3uBYslKiybFxqhs,2042
240
240
  metaflow/plugins/argo/conditional_input_paths.py,sha256=Vtca74XbhnqAXgJJXKasLEa28jZbKBZPC5w4NAIOURc,1251
241
241
  metaflow/plugins/argo/exit_hooks.py,sha256=nh8IEkzAtQnbKVnh3N9CVnVKZB39Bjm3e0LFrACsLz8,6109
242
242
  metaflow/plugins/argo/generate_input_paths.py,sha256=loYsI6RFX9LlFsHb7Fe-mzlTTtRdySoOu7sYDy-uXK0,881
243
243
  metaflow/plugins/argo/jobset_input_paths.py,sha256=-h0E_e0w6FMiBUod9Rf_XOSCtZv_C0exacw4q1SfIfg,501
244
+ metaflow/plugins/argo/param_val.py,sha256=qfMsXyT6bjfUz0eqNpbitFcps2G5XwJqOAoGLt4Jpxw,390
244
245
  metaflow/plugins/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
245
246
  metaflow/plugins/aws/aws_client.py,sha256=BTiLMXa1agjja-N73oWinaOZHs-lGPbfKJG8CqdRgaU,4287
246
247
  metaflow/plugins/aws/aws_utils.py,sha256=5mGZLu6wwTo2KzIke_MFqiomM3sYjAkU7Fx55dIMLfg,8561
@@ -275,7 +276,7 @@ metaflow/plugins/cards/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
275
276
  metaflow/plugins/cards/card_cli.py,sha256=h-ib-SXjJjAm-jSQC4pEmVcsM4M3lljSjOkZBxvAvRo,35763
276
277
  metaflow/plugins/cards/card_client.py,sha256=30dFBoC3axc261GeV7QCIs_V1OHhRtS31S0wEWsjw90,9501
277
278
  metaflow/plugins/cards/card_creator.py,sha256=Da4LOkRY3IJNcGQn1V6zlSdgVjgiFm6XMcsKOe_6v70,8784
278
- metaflow/plugins/cards/card_datastore.py,sha256=bPLjBFWNlAgIjONAb0IjYXMmp9vMYlh3EYhRjAlDA0U,12714
279
+ metaflow/plugins/cards/card_datastore.py,sha256=rSiOZWNcFMGywFAU5CVb5h0WrAw74X-qzT3exFpR7yA,12741
279
280
  metaflow/plugins/cards/card_decorator.py,sha256=lu_m95tZRIkPp1wMlcT80aZRCbjuFapyuPXuelFCMAc,14073
280
281
  metaflow/plugins/cards/card_resolver.py,sha256=bjyujYpGUFbLJNwXNGHlHhL4f-gVdVKebl7XW1vWDtE,717
281
282
  metaflow/plugins/cards/card_server.py,sha256=DHv0RcepaPULWbkDahiEMrU5A281Cfb0DvHLUYd8JsU,11772
@@ -287,7 +288,7 @@ metaflow/plugins/cards/card_modules/base.html,sha256=Y208ZKIZqEWWUcoBFTLTdWKAG0C
287
288
  metaflow/plugins/cards/card_modules/basic.py,sha256=bKU_b_Wfs2OC6me6kPp1Jm_SLvaJ4dkUCMAt2VLampk,26430
288
289
  metaflow/plugins/cards/card_modules/bundle.css,sha256=zlYjv5rt7lMqiQzd_OAe4QdQeM3J3YbwljnEghlbTaU,28052
289
290
  metaflow/plugins/cards/card_modules/card.py,sha256=6sbqP5mwf7QWvQvX2N_bC78H9ixuI5sQ8612Q5islys,4627
290
- metaflow/plugins/cards/card_modules/components.py,sha256=hF204MUyJ2DZXSPhEt7d23isjdEf4TGK8pzmVkmXyQ0,45574
291
+ metaflow/plugins/cards/card_modules/components.py,sha256=z9IT9gVpI22hUhGtJbgcy5oMpGzPeTof_lEkOOfMa9Q,46150
291
292
  metaflow/plugins/cards/card_modules/convert_to_native_type.py,sha256=opjGOvWg7trOqzhTRZ7h1cFlYrNj68Wn3_EyDTIKEvw,17320
292
293
  metaflow/plugins/cards/card_modules/json_viewer.py,sha256=DWOcQPk6DXbeGuYEqv1gGrQW1eMVYlCXv3kMsVLnhNc,7113
293
294
  metaflow/plugins/cards/card_modules/main.css,sha256=avu7BTB9qj0M8LvqNLUhikUFQhmAJhQQ7REcUgh9zMw,11725
@@ -377,14 +378,14 @@ metaflow/plugins/uv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
377
378
  metaflow/plugins/uv/bootstrap.py,sha256=awFHAiZANkAlvHWCm3G1UbhVxEjJB8buoZoBa5GiKJc,4365
378
379
  metaflow/plugins/uv/uv_environment.py,sha256=AYZICrBEq3Bv-taXktJwu9DhKFxNooPFwlcH379EYMs,2719
379
380
  metaflow/runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
380
- metaflow/runner/click_api.py,sha256=7DVM8XuiFPpIm4vs5VUp17faEU05ixbkMwyhtJ54FWo,24478
381
+ metaflow/runner/click_api.py,sha256=WmhbrjS0H2gz-AZDEDe5Jrkctf9SvV4XrfgIBPW7nUI,24530
381
382
  metaflow/runner/deployer.py,sha256=OAAMG_l3Q1ClcY_603VZnhclVkfFe3Rf8bFRodC3poc,17138
382
383
  metaflow/runner/deployer_impl.py,sha256=q-IvwnNKPRUTpOkfzrZNrkIsjp-L-Ju75dtXmfDUqbI,7299
383
384
  metaflow/runner/metaflow_runner.py,sha256=uo3BzcAfZ67VT_f-TPe5ZHiWHn6uuojWusOMGksvX14,18178
384
385
  metaflow/runner/nbdeploy.py,sha256=Sp5w-6nCZwjHaRBHWxi8udya-RYnJOB76KNLjB4L7Gs,4166
385
386
  metaflow/runner/nbrun.py,sha256=LhJu-Teoi7wTkNxg0kpNPVXFxH_9P4lvtp0ysMEIFJ8,7299
386
387
  metaflow/runner/subprocess_manager.py,sha256=x-MtPpGGMQUkIbQ_oNOuR-45b91DFvsCJ0SPoFc0dF4,23028
387
- metaflow/runner/utils.py,sha256=fU4vPazBdi6ATAUW_DaBAQeVslRwrLT8Pn9s5wav3gg,10350
388
+ metaflow/runner/utils.py,sha256=x9EED11RZGf7J4OuK-cVuj8gxGlSjRQFSqqTehvBSjw,10588
388
389
  metaflow/sidecar/__init__.py,sha256=1mmNpmQ5puZCpRmmYlCOeieZ4108Su9XQ4_EqF1FGOU,131
389
390
  metaflow/sidecar/sidecar.py,sha256=EspKXvPPNiyRToaUZ51PS5TT_PzrBNAurn_wbFnmGr0,1334
390
391
  metaflow/sidecar/sidecar_messages.py,sha256=zPsCoYgDIcDkkvdC9MEpJTJ3y6TSGm2JWkRc4vxjbFA,1071
@@ -430,12 +431,12 @@ metaflow/user_decorators/mutable_flow.py,sha256=EywKTN3cnXPQF_s62wQaC4a4aH14j8oe
430
431
  metaflow/user_decorators/mutable_step.py,sha256=-BY0UDXf_RCAEnC5JlLzEXGdiw1KD9oSrSxS_SWaB9Y,16791
431
432
  metaflow/user_decorators/user_flow_decorator.py,sha256=2yDwZq9QGv9W-7kEuKwa8o4ZkTvuHJ5ESz7VVrGViAI,9890
432
433
  metaflow/user_decorators/user_step_decorator.py,sha256=4558NR8RJtN22OyTwCXO80bAMhMTaRGMoX12b1GMcPc,27232
433
- metaflow-2.18.11.data/data/share/metaflow/devtools/Makefile,sha256=TT4TCq8ALSfqYyGqDPocN5oPcZe2FqoCZxmGO1LmyCc,13760
434
- metaflow-2.18.11.data/data/share/metaflow/devtools/Tiltfile,sha256=b6l_fjDO0wtxOkO85lFvuf3HDa6wnzHhhBG8yv1kQqk,23949
435
- metaflow-2.18.11.data/data/share/metaflow/devtools/pick_services.sh,sha256=PGjQeDIigFHeoQ0asmYNdYDPIOdeYy1UYvkw2wdN4zg,2209
436
- metaflow-2.18.11.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
437
- metaflow-2.18.11.dist-info/METADATA,sha256=7lnNSVzLGJoGR8_RscIBX2R55lbQPIU1QqUOlUuWiUo,6743
438
- metaflow-2.18.11.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
439
- metaflow-2.18.11.dist-info/entry_points.txt,sha256=RvEq8VFlgGe_FfqGOZi0D7ze1hLD0pAtXeNyGfzc_Yc,103
440
- metaflow-2.18.11.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
441
- metaflow-2.18.11.dist-info/RECORD,,
434
+ metaflow-2.18.13.data/data/share/metaflow/devtools/Makefile,sha256=TT4TCq8ALSfqYyGqDPocN5oPcZe2FqoCZxmGO1LmyCc,13760
435
+ metaflow-2.18.13.data/data/share/metaflow/devtools/Tiltfile,sha256=b6l_fjDO0wtxOkO85lFvuf3HDa6wnzHhhBG8yv1kQqk,23949
436
+ metaflow-2.18.13.data/data/share/metaflow/devtools/pick_services.sh,sha256=PGjQeDIigFHeoQ0asmYNdYDPIOdeYy1UYvkw2wdN4zg,2209
437
+ metaflow-2.18.13.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
438
+ metaflow-2.18.13.dist-info/METADATA,sha256=PTPTKK93ldxAV0LUxH3dVL_rLlrAFqEzfIK2qbk07i4,6743
439
+ metaflow-2.18.13.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
440
+ metaflow-2.18.13.dist-info/entry_points.txt,sha256=RvEq8VFlgGe_FfqGOZi0D7ze1hLD0pAtXeNyGfzc_Yc,103
441
+ metaflow-2.18.13.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
442
+ metaflow-2.18.13.dist-info/RECORD,,