metaflow 2.18.5__py2.py3-none-any.whl → 2.18.7__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.
@@ -70,7 +70,26 @@ class TriggerDecorator(FlowDecorator):
70
70
  "options": {},
71
71
  }
72
72
 
73
- def process_event_name(self, event):
73
+ def process_event(self, event):
74
+ """
75
+ Process a single event and return a dictionary if static trigger and a function
76
+ if deploy-time trigger.
77
+
78
+ Parameters
79
+ ----------
80
+ event : Union[str, Dict[str, Any], Callable]
81
+ Event to process
82
+
83
+ Returns
84
+ -------
85
+ Union[Dict[str, Union[str, Callable]], Callable]
86
+ Processed event
87
+
88
+ Raises
89
+ ------
90
+ MetaflowException
91
+ If the event is not in the correct format
92
+ """
74
93
  if is_stringish(event):
75
94
  return {"name": str(event)}
76
95
  elif isinstance(event, dict):
@@ -82,12 +101,26 @@ class TriggerDecorator(FlowDecorator):
82
101
  event["name"], DeployTimeField
83
102
  ):
84
103
  event["name"] = DeployTimeField(
85
- "event_name", str, None, event["name"], False
104
+ "event_name",
105
+ str,
106
+ None,
107
+ event["name"],
108
+ False,
109
+ print_representation=str(event["name"]),
86
110
  )
87
- event["parameters"] = self.process_parameters(event.get("parameters", {}))
111
+ event["parameters"] = self.process_parameters(
112
+ event.get("parameters", {}), event["name"]
113
+ )
88
114
  return event
89
115
  elif callable(event) and not isinstance(event, DeployTimeField):
90
- return DeployTimeField("event", [str, dict], None, event, False)
116
+ return DeployTimeField(
117
+ "event",
118
+ [str, dict],
119
+ None,
120
+ event,
121
+ False,
122
+ print_representation=str(event),
123
+ )
91
124
  else:
92
125
  raise MetaflowException(
93
126
  "Incorrect format for *event* attribute in *@trigger* decorator. "
@@ -96,47 +129,67 @@ class TriggerDecorator(FlowDecorator):
96
129
  "'parameters': {'alpha': 'beta'}})"
97
130
  )
98
131
 
99
- def process_parameters(self, parameters):
132
+ def process_parameters(self, parameters, event_name):
133
+ """
134
+ Process the parameters for an event and return a dictionary of parameter mappings if
135
+ parameters was statically defined or a function if deploy-time trigger.
136
+
137
+ Parameters
138
+ ----------
139
+ Parameters : Union[Dict[str, str], List[Union[str, Tuple[str, str]]], Callable]
140
+ Parameters to process
141
+
142
+ event_name : Union[str, callable]
143
+ Name of the event
144
+
145
+ Returns
146
+ -------
147
+ Union[Dict[str, str], Callable]
148
+ Processed parameters
149
+
150
+ Raises
151
+ ------
152
+ MetaflowException
153
+ If the parameters are not in the correct format
154
+ """
100
155
  new_param_values = {}
101
- if isinstance(parameters, (list, tuple)):
156
+ if isinstance(parameters, list):
102
157
  for mapping in parameters:
103
158
  if is_stringish(mapping):
159
+ # param_name
104
160
  new_param_values[mapping] = mapping
105
- elif callable(mapping) and not isinstance(mapping, DeployTimeField):
106
- mapping = DeployTimeField(
107
- "parameter_val", str, None, mapping, False
108
- )
109
- new_param_values[mapping] = mapping
110
- elif isinstance(mapping, (list, tuple)) and len(mapping) == 2:
111
- if callable(mapping[0]) and not isinstance(
112
- mapping[0], DeployTimeField
113
- ):
114
- mapping[0] = DeployTimeField(
115
- "parameter_val", str, None, mapping[0], False
116
- )
117
- if callable(mapping[1]) and not isinstance(
118
- mapping[1], DeployTimeField
119
- ):
120
- mapping[1] = DeployTimeField(
121
- "parameter_val", str, None, mapping[1], False
161
+ elif isinstance(mapping, tuple) and len(mapping) == 2:
162
+ # (param_name, field_name)
163
+ param_name, field_name = mapping
164
+ if not is_stringish(param_name) or not is_stringish(field_name):
165
+ raise MetaflowException(
166
+ f"The *parameters* attribute for event {event_name} is invalid. "
167
+ "It should be a list/tuple of strings and lists/tuples of size 2."
122
168
  )
123
- new_param_values[mapping[0]] = mapping[1]
169
+ new_param_values[param_name] = field_name
124
170
  else:
125
171
  raise MetaflowException(
126
172
  "The *parameters* attribute for event is invalid. "
127
173
  "It should be a list/tuple of strings and lists/tuples of size 2"
128
174
  )
129
- elif callable(parameters) and not isinstance(parameters, DeployTimeField):
130
- return DeployTimeField(
131
- "parameters", [list, dict, tuple], None, parameters, False
132
- )
133
175
  elif isinstance(parameters, dict):
134
176
  for key, value in parameters.items():
135
- if callable(key) and not isinstance(key, DeployTimeField):
136
- key = DeployTimeField("flow_parameter", str, None, key, False)
137
- if callable(value) and not isinstance(value, DeployTimeField):
138
- value = DeployTimeField("signal_parameter", str, None, value, False)
177
+ if not is_stringish(key) or not is_stringish(value):
178
+ raise MetaflowException(
179
+ f"The *parameters* attribute for event {event_name} is invalid. "
180
+ "It should be a dictionary of string keys and string values."
181
+ )
139
182
  new_param_values[key] = value
183
+ elif callable(parameters) and not isinstance(parameters, DeployTimeField):
184
+ # func
185
+ return DeployTimeField(
186
+ "parameters",
187
+ [list, dict, tuple],
188
+ None,
189
+ parameters,
190
+ False,
191
+ print_representation=str(parameters),
192
+ )
140
193
  return new_param_values
141
194
 
142
195
  def flow_init(
@@ -158,7 +211,7 @@ class TriggerDecorator(FlowDecorator):
158
211
  )
159
212
  elif self.attributes["event"]:
160
213
  event = self.attributes["event"]
161
- processed_event = self.process_event_name(event)
214
+ processed_event = self.process_event(event)
162
215
  self.triggers.append(processed_event)
163
216
  elif self.attributes["events"]:
164
217
  # events attribute supports the following formats -
@@ -169,13 +222,18 @@ class TriggerDecorator(FlowDecorator):
169
222
  if isinstance(self.attributes["events"], list):
170
223
  # process every event in events
171
224
  for event in self.attributes["events"]:
172
- processed_event = self.process_event_name(event)
225
+ processed_event = self.process_event(event)
173
226
  self.triggers.append(processed_event)
174
227
  elif callable(self.attributes["events"]) and not isinstance(
175
228
  self.attributes["events"], DeployTimeField
176
229
  ):
177
230
  trig = DeployTimeField(
178
- "events", list, None, self.attributes["events"], False
231
+ "events",
232
+ list,
233
+ None,
234
+ self.attributes["events"],
235
+ False,
236
+ print_representation=str(self.attributes["events"]),
179
237
  )
180
238
  self.triggers.append(trig)
181
239
  else:
@@ -208,101 +266,40 @@ class TriggerDecorator(FlowDecorator):
208
266
 
209
267
  def format_deploytime_value(self):
210
268
  new_triggers = []
269
+
270
+ # First pass to evaluate DeployTimeFields
211
271
  for trigger in self.triggers:
212
272
  # Case where trigger is a function that returns a list of events
213
273
  # Need to do this bc we need to iterate over list later
214
274
  if isinstance(trigger, DeployTimeField):
215
275
  evaluated_trigger = deploy_time_eval(trigger)
216
- if isinstance(evaluated_trigger, dict):
217
- trigger = evaluated_trigger
218
- elif isinstance(evaluated_trigger, str):
219
- trigger = {"name": evaluated_trigger}
220
276
  if isinstance(evaluated_trigger, list):
221
- for trig in evaluated_trigger:
222
- if is_stringish(trig):
223
- new_triggers.append({"name": trig})
224
- else: # dict or another deploytimefield
225
- new_triggers.append(trig)
277
+ for event in evaluated_trigger:
278
+ new_triggers.append(self.process_event(event))
226
279
  else:
227
- new_triggers.append(trigger)
280
+ new_triggers.append(self.process_event(evaluated_trigger))
228
281
  else:
229
282
  new_triggers.append(trigger)
230
283
 
284
+ # Second pass to evaluate names
285
+ for trigger in new_triggers:
286
+ name = trigger.get("name")
287
+ if isinstance(name, DeployTimeField):
288
+ trigger["name"] = deploy_time_eval(name)
289
+ if not is_stringish(trigger["name"]):
290
+ raise MetaflowException(
291
+ f"The *name* attribute for event {trigger} is not a valid string"
292
+ )
293
+
294
+ # third pass to evaluate parameters
295
+ for trigger in new_triggers:
296
+ parameters = trigger.get("parameters", {})
297
+ if isinstance(parameters, DeployTimeField):
298
+ parameters_eval = deploy_time_eval(parameters)
299
+ parameters = self.process_parameters(parameters_eval, trigger["name"])
300
+ trigger["parameters"] = parameters
301
+
231
302
  self.triggers = new_triggers
232
- for trigger in self.triggers:
233
- old_trigger = trigger
234
- trigger_params = trigger.get("parameters", {})
235
- # Case where param is a function (can return list or dict)
236
- if isinstance(trigger_params, DeployTimeField):
237
- trigger_params = deploy_time_eval(trigger_params)
238
- # If params is a list of strings, convert to dict with same key and value
239
- if isinstance(trigger_params, (list, tuple)):
240
- new_trigger_params = {}
241
- for mapping in trigger_params:
242
- if is_stringish(mapping) or callable(mapping):
243
- new_trigger_params[mapping] = mapping
244
- elif callable(mapping) and not isinstance(mapping, DeployTimeField):
245
- mapping = DeployTimeField(
246
- "parameter_val", str, None, mapping, False
247
- )
248
- new_trigger_params[mapping] = mapping
249
- elif isinstance(mapping, (list, tuple)) and len(mapping) == 2:
250
- if callable(mapping[0]) and not isinstance(
251
- mapping[0], DeployTimeField
252
- ):
253
- mapping[0] = DeployTimeField(
254
- "parameter_val",
255
- str,
256
- None,
257
- mapping[1],
258
- False,
259
- )
260
- if callable(mapping[1]) and not isinstance(
261
- mapping[1], DeployTimeField
262
- ):
263
- mapping[1] = DeployTimeField(
264
- "parameter_val",
265
- str,
266
- None,
267
- mapping[1],
268
- False,
269
- )
270
-
271
- new_trigger_params[mapping[0]] = mapping[1]
272
- else:
273
- raise MetaflowException(
274
- "The *parameters* attribute for event '%s' is invalid. "
275
- "It should be a list/tuple of strings and lists/tuples "
276
- "of size 2" % self.attributes["event"]["name"]
277
- )
278
- trigger_params = new_trigger_params
279
- trigger["parameters"] = trigger_params
280
-
281
- trigger_name = trigger.get("name")
282
- # Case where just the name is a function (always a str)
283
- if isinstance(trigger_name, DeployTimeField):
284
- trigger_name = deploy_time_eval(trigger_name)
285
- trigger["name"] = trigger_name
286
-
287
- # Third layer
288
- # {name:, parameters:[func, ..., ...]}
289
- # {name:, parameters:{func : func2}}
290
- for trigger in self.triggers:
291
- old_trigger = trigger
292
- trigger_params = trigger.get("parameters", {})
293
- new_trigger_params = {}
294
- for key, value in trigger_params.items():
295
- if isinstance(value, DeployTimeField) and key is value:
296
- evaluated_param = deploy_time_eval(value)
297
- new_trigger_params[evaluated_param] = evaluated_param
298
- elif isinstance(value, DeployTimeField):
299
- new_trigger_params[key] = deploy_time_eval(value)
300
- elif isinstance(key, DeployTimeField):
301
- new_trigger_params[deploy_time_eval(key)] = value
302
- else:
303
- new_trigger_params[key] = value
304
- trigger["parameters"] = new_trigger_params
305
- self.triggers[self.triggers.index(old_trigger)] = trigger
306
303
 
307
304
 
308
305
  class TriggerOnFinishDecorator(FlowDecorator):
@@ -402,7 +399,14 @@ class TriggerOnFinishDecorator(FlowDecorator):
402
399
  if callable(flow) and not isinstance(
403
400
  self.attributes["flow"], DeployTimeField
404
401
  ):
405
- trig = DeployTimeField("fq_name", [str, dict], None, flow, False)
402
+ trig = DeployTimeField(
403
+ "fq_name",
404
+ [str, dict],
405
+ None,
406
+ flow,
407
+ False,
408
+ print_representation=str(flow),
409
+ )
406
410
  self.triggers.append(trig)
407
411
  else:
408
412
  self.triggers.extend(self._parse_static_triggers([flow]))
@@ -411,7 +415,9 @@ class TriggerOnFinishDecorator(FlowDecorator):
411
415
  # 1. flows=['FooFlow', 'BarFlow']
412
416
  flows = self.attributes["flows"]
413
417
  if callable(flows) and not isinstance(flows, DeployTimeField):
414
- trig = DeployTimeField("flows", list, None, flows, False)
418
+ trig = DeployTimeField(
419
+ "flows", list, None, flows, False, print_representation=str(flows)
420
+ )
415
421
  self.triggers.append(trig)
416
422
  elif isinstance(flows, list):
417
423
  self.triggers.extend(self._parse_static_triggers(flows))
@@ -60,6 +60,15 @@ class Pip(object):
60
60
  else:
61
61
  self.logger = lambda *args, **kwargs: None # No-op logger if not provided
62
62
 
63
+ def _get_resolved_python_version(self, prefix):
64
+ try:
65
+ result = self.micromamba._call(["list", "--prefix", prefix, "--json"])
66
+ for package in result:
67
+ if package.get("name") == "python":
68
+ return package["version"]
69
+ except Exception:
70
+ return None
71
+
63
72
  def solve(self, id_, packages, python, platform):
64
73
  prefix = self.micromamba.path_to_environment(id_)
65
74
  if prefix is None:
@@ -67,13 +76,19 @@ class Pip(object):
67
76
  msg += "for id {id}".format(id=id_)
68
77
  raise PipException(msg)
69
78
 
79
+ resolved_python = self._get_resolved_python_version(prefix)
80
+ if not resolved_python:
81
+ raise PipException(
82
+ "Could not determine Python version from conda environment"
83
+ )
84
+
70
85
  debug.conda_exec("Solving packages for PyPI environment %s" % id_)
71
86
  with tempfile.TemporaryDirectory() as tmp_dir:
72
87
  report = "{tmp_dir}/report.json".format(tmp_dir=tmp_dir)
73
88
  implementations, platforms, abis = zip(
74
89
  *[
75
90
  (tag.interpreter, tag.platform, tag.abi)
76
- for tag in pip_tags(python, platform)
91
+ for tag in pip_tags(resolved_python, platform)
77
92
  ]
78
93
  )
79
94
  custom_index_url, extra_index_urls = self.indices(prefix)
@@ -142,6 +157,13 @@ class Pip(object):
142
157
 
143
158
  def download(self, id_, packages, python, platform):
144
159
  prefix = self.micromamba.path_to_environment(id_)
160
+
161
+ resolved_python = self._get_resolved_python_version(prefix)
162
+ if not resolved_python:
163
+ raise PipException(
164
+ "Could not determine Python version from conda environment"
165
+ )
166
+
145
167
  metadata_file = METADATA_FILE.format(prefix=prefix)
146
168
  # download packages only if they haven't ever been downloaded before
147
169
  if os.path.isfile(metadata_file):
@@ -192,7 +214,11 @@ class Pip(object):
192
214
  if os.path.isfile(os.path.join(path, f)) and f.endswith(".whl")
193
215
  ]
194
216
  if (
195
- len(set(pip_tags(python, platform)).intersection(wheel_tags(wheel)))
217
+ len(
218
+ set(pip_tags(resolved_python, platform)).intersection(
219
+ wheel_tags(wheel)
220
+ )
221
+ )
196
222
  == 0
197
223
  ):
198
224
  raise PipException(
@@ -211,7 +237,7 @@ class Pip(object):
211
237
  implementations, platforms, abis = zip(
212
238
  *[
213
239
  (tag.interpreter, tag.platform, tag.abi)
214
- for tag in pip_tags(python, platform)
240
+ for tag in pip_tags(resolved_python, platform)
215
241
  ]
216
242
  )
217
243
 
metaflow/version.py CHANGED
@@ -1 +1 @@
1
- metaflow_version = "2.18.5"
1
+ metaflow_version = "2.18.7"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaflow
3
- Version: 2.18.5
3
+ Version: 2.18.7
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.5; extra == "stubs"
29
+ Requires-Dist: metaflow-stubs==2.18.7; extra == "stubs"
30
30
  Dynamic: author
31
31
  Dynamic: author-email
32
32
  Dynamic: classifier
@@ -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=j-5Xjp6k9jr89uo7zqXR9auyDCCWozyQgBHgn9_8I8M,28
39
+ metaflow/version.py,sha256=AIRLGaVLM-FX3-8i8T2EI3rpQbi7la4g-ypfTc6tIww,28
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
@@ -203,7 +203,7 @@ metaflow/plugins/catch_decorator.py,sha256=vorlDA6MLB2yHSsEuBoNzAZbrJ6Vknj1qJO9v
203
203
  metaflow/plugins/debug_logger.py,sha256=mcF5HYzJ0NQmqCMjyVUk3iAP-heroHRIiVWQC6Ha2-I,879
204
204
  metaflow/plugins/debug_monitor.py,sha256=Md5X_sDOSssN9pt2D8YcaIjTK5JaQD55UAYTcF6xYF0,1099
205
205
  metaflow/plugins/environment_decorator.py,sha256=6m9j2B77d-Ja_l_9CTJ__0O6aB2a8Qt_lAZu6UjAcUA,587
206
- metaflow/plugins/events_decorator.py,sha256=T_YSK-DlgZhd3ge9PlpTRNaMi15GK0tKZMZl1NdV9DQ,24403
206
+ metaflow/plugins/events_decorator.py,sha256=FULT_Iuue9KsLyNhHOL46uw8cdT-Viq8rmcgEHVRlF0,22704
207
207
  metaflow/plugins/logs_cli.py,sha256=77W5UNagU2mOKSMMvrQxQmBLRzvmjK-c8dWxd-Ygbqs,11410
208
208
  metaflow/plugins/package_cli.py,sha256=GOxKJs9Wt0x9VtcTJ2EG_wj6pWnlS0XBFAyHpCzzuvs,2000
209
209
  metaflow/plugins/parallel_decorator.py,sha256=wtR_3eRIP3eV7fBIm15oouRjmHBFZ9OklxdaNvttLEQ,9702
@@ -361,7 +361,7 @@ metaflow/plugins/pypi/conda_decorator.py,sha256=fXG9EvImP4Eqle_Trhb3tQhs40xTc4cx
361
361
  metaflow/plugins/pypi/conda_environment.py,sha256=j6QaIWmP50K2veN6Sywa04S2hfByR1YMqy7OyZpwvYs,24925
362
362
  metaflow/plugins/pypi/micromamba.py,sha256=UltfY8NmLphfZ-AbpaMFIdxIeOXLdTYDrMrabvPrYVU,17352
363
363
  metaflow/plugins/pypi/parsers.py,sha256=gpOOG2Ph95wI73MWCAi7XjpK0gYhv5k5YIGBs73QPuE,8556
364
- metaflow/plugins/pypi/pip.py,sha256=WhPyA18RoVT40sqbZRJdCEij4euL9PZwLfm1SrAKqmU,14333
364
+ metaflow/plugins/pypi/pip.py,sha256=N5C3tjuWG2pr4VGZR8YgnRc0HwfRL7LZmOnxxA9ZmEc,15239
365
365
  metaflow/plugins/pypi/pypi_decorator.py,sha256=sBxmDH3WIWVfJDsSauiMy58fevOJuJeLSuS6MnIpw44,7312
366
366
  metaflow/plugins/pypi/pypi_environment.py,sha256=FYMg8kF3lXqcLfRYWD83a9zpVjcoo_TARqMGZ763rRk,230
367
367
  metaflow/plugins/pypi/utils.py,sha256=W8OhDrhz7YIE-2MSSN5Rj7AmESwsN5YDmdnro152J4w,3551
@@ -428,12 +428,12 @@ metaflow/user_decorators/mutable_flow.py,sha256=EywKTN3cnXPQF_s62wQaC4a4aH14j8oe
428
428
  metaflow/user_decorators/mutable_step.py,sha256=-BY0UDXf_RCAEnC5JlLzEXGdiw1KD9oSrSxS_SWaB9Y,16791
429
429
  metaflow/user_decorators/user_flow_decorator.py,sha256=2yDwZq9QGv9W-7kEuKwa8o4ZkTvuHJ5ESz7VVrGViAI,9890
430
430
  metaflow/user_decorators/user_step_decorator.py,sha256=4558NR8RJtN22OyTwCXO80bAMhMTaRGMoX12b1GMcPc,27232
431
- metaflow-2.18.5.data/data/share/metaflow/devtools/Makefile,sha256=TT4TCq8ALSfqYyGqDPocN5oPcZe2FqoCZxmGO1LmyCc,13760
432
- metaflow-2.18.5.data/data/share/metaflow/devtools/Tiltfile,sha256=Ty5p6AD3MwJAcAnOGv4yMz8fExAsnNQ11r8whK6uzzw,21381
433
- metaflow-2.18.5.data/data/share/metaflow/devtools/pick_services.sh,sha256=DCnrMXwtApfx3B4S-YiZESMyAFHbXa3VuNL0MxPLyiE,2196
434
- metaflow-2.18.5.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
435
- metaflow-2.18.5.dist-info/METADATA,sha256=sjfM1I825FwjvAscfoOhfUei4-SO9W_kWlZBXgbJGKc,6740
436
- metaflow-2.18.5.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
437
- metaflow-2.18.5.dist-info/entry_points.txt,sha256=RvEq8VFlgGe_FfqGOZi0D7ze1hLD0pAtXeNyGfzc_Yc,103
438
- metaflow-2.18.5.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
439
- metaflow-2.18.5.dist-info/RECORD,,
431
+ metaflow-2.18.7.data/data/share/metaflow/devtools/Makefile,sha256=TT4TCq8ALSfqYyGqDPocN5oPcZe2FqoCZxmGO1LmyCc,13760
432
+ metaflow-2.18.7.data/data/share/metaflow/devtools/Tiltfile,sha256=Ty5p6AD3MwJAcAnOGv4yMz8fExAsnNQ11r8whK6uzzw,21381
433
+ metaflow-2.18.7.data/data/share/metaflow/devtools/pick_services.sh,sha256=DCnrMXwtApfx3B4S-YiZESMyAFHbXa3VuNL0MxPLyiE,2196
434
+ metaflow-2.18.7.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
435
+ metaflow-2.18.7.dist-info/METADATA,sha256=rjd-ZidDUaQyWvbyExLrzZmadNpHPsqEiOkg-TRTlZ4,6740
436
+ metaflow-2.18.7.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
437
+ metaflow-2.18.7.dist-info/entry_points.txt,sha256=RvEq8VFlgGe_FfqGOZi0D7ze1hLD0pAtXeNyGfzc_Yc,103
438
+ metaflow-2.18.7.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
439
+ metaflow-2.18.7.dist-info/RECORD,,