ob-metaflow 2.12.23.1__py2.py3-none-any.whl → 2.12.25.1__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.

Potentially problematic release.


This version of ob-metaflow might be problematic. Click here for more details.

@@ -51,7 +51,7 @@ from metaflow.metaflow_config import (
51
51
  UI_URL,
52
52
  PAGERDUTY_TEMPLATE_URL,
53
53
  )
54
- from metaflow.metaflow_config_funcs import config_values
54
+ from metaflow.metaflow_config_funcs import config_values, init_config
55
55
  from metaflow.mflog import BASH_SAVE_LOGS, bash_capture_logs, export_mflog_env_vars
56
56
  from metaflow.parameters import deploy_time_eval
57
57
  from metaflow.plugins.kubernetes.kubernetes import (
@@ -1822,6 +1822,21 @@ class ArgoWorkflows(object):
1822
1822
  and k not in set(ARGO_WORKFLOWS_ENV_VARS_TO_SKIP.split(","))
1823
1823
  }
1824
1824
 
1825
+ # get initial configs
1826
+ initial_configs = init_config()
1827
+ for entry in ["OBP_PERIMETER", "OBP_INTEGRATIONS_SECRETS_METADATA_URL"]:
1828
+ if entry not in initial_configs:
1829
+ raise ArgoWorkflowsException(
1830
+ f"{entry} was not found in metaflow config. Please make sure to run `outerbounds configure <...>` command which can be found on the Ourebounds UI or reach out to your Outerbounds support team."
1831
+ )
1832
+
1833
+ additional_obp_configs = {
1834
+ "OBP_PERIMETER": initial_configs["OBP_PERIMETER"],
1835
+ "OBP_INTEGRATIONS_SECRETS_METADATA_URL": initial_configs[
1836
+ "OBP_INTEGRATIONS_SECRETS_METADATA_URL"
1837
+ ],
1838
+ }
1839
+
1825
1840
  # Tmpfs variables
1826
1841
  use_tmpfs = resources["use_tmpfs"]
1827
1842
  tmpfs_size = resources["tmpfs_size"]
@@ -2083,6 +2098,13 @@ class ArgoWorkflows(object):
2083
2098
  "METAFLOW_KUBERNETES_SERVICE_ACCOUNT_NAME": "spec.serviceAccountName",
2084
2099
  "METAFLOW_KUBERNETES_NODE_IP": "status.hostIP",
2085
2100
  }.items()
2101
+ ]
2102
+ + [
2103
+ kubernetes_sdk.V1EnvVar(
2104
+ name=k,
2105
+ value=v,
2106
+ )
2107
+ for k, v in additional_obp_configs.items()
2086
2108
  ],
2087
2109
  image=resources["image"],
2088
2110
  image_pull_policy=resources["image_pull_policy"],
@@ -2642,6 +2664,9 @@ class ArgoWorkflows(object):
2642
2664
 
2643
2665
  return (
2644
2666
  DaemonTemplate("heartbeat-daemon")
2667
+ # NOTE: Even though a retry strategy does not work for Argo daemon containers,
2668
+ # this has the side-effect of protecting the exit hooks of the workflow from failing in case the daemon container errors out.
2669
+ .retry_strategy(10, 1)
2645
2670
  .service_account_name(resources["service_account"])
2646
2671
  .container(
2647
2672
  to_camelcase(
@@ -3313,6 +3338,15 @@ class DaemonTemplate(object):
3313
3338
  self.payload["serviceAccountName"] = service_account_name
3314
3339
  return self
3315
3340
 
3341
+ def retry_strategy(self, times, minutes_between_retries):
3342
+ if times > 0:
3343
+ self.payload["retryStrategy"] = {
3344
+ "retryPolicy": "Always",
3345
+ "limit": times,
3346
+ "backoff": {"duration": "%sm" % minutes_between_retries},
3347
+ }
3348
+ return self
3349
+
3316
3350
  def to_json(self):
3317
3351
  return self.payload
3318
3352
 
@@ -179,7 +179,7 @@ def argo_workflows(obj, name=None):
179
179
  )
180
180
  @click.option(
181
181
  "--enable-heartbeat-daemon/--no-enable-heartbeat-daemon",
182
- default=True,
182
+ default=False,
183
183
  show_default=True,
184
184
  help="Use a daemon container to broadcast heartbeats.",
185
185
  )
@@ -45,7 +45,7 @@ from metaflow.metaflow_config import (
45
45
  SERVICE_INTERNAL_URL,
46
46
  )
47
47
  from metaflow.unbounded_foreach import UBF_CONTROL, UBF_TASK
48
- from metaflow.metaflow_config_funcs import config_values
48
+ from metaflow.metaflow_config_funcs import config_values, init_config
49
49
  from metaflow.mflog import (
50
50
  BASH_SAVE_LOGS,
51
51
  bash_capture_logs,
@@ -311,6 +311,22 @@ class Kubernetes(object):
311
311
  ) + KUBERNETES_SECRETS.split(","):
312
312
  jobset.secret(k)
313
313
 
314
+ initial_configs = init_config()
315
+ for entry in ["OBP_PERIMETER", "OBP_INTEGRATIONS_SECRETS_METADATA_URL"]:
316
+ if entry not in initial_configs:
317
+ raise KubernetesException(
318
+ f"{entry} was not found in metaflow config. Please make sure to run `outerbounds configure <...>` command which can be found on the Ourebounds UI or reach out to your Outerbounds support team."
319
+ )
320
+
321
+ additional_obp_configs = {
322
+ "OBP_PERIMETER": initial_configs["OBP_PERIMETER"],
323
+ "OBP_INTEGRATIONS_SECRETS_METADATA_URL": initial_configs[
324
+ "OBP_INTEGRATIONS_SECRETS_METADATA_URL"
325
+ ],
326
+ }
327
+ for k, v in additional_obp_configs.items():
328
+ jobset.environment_variable(k, v)
329
+
314
330
  jobset.environment_variables_from_selectors(
315
331
  {
316
332
  "METAFLOW_KUBERNETES_NAMESPACE": "metadata.namespace",
@@ -121,10 +121,7 @@ class KubernetesClient(object):
121
121
  job_api = self._client.BatchV1Api()
122
122
  pods = self._find_active_pods(flow_name, run_id, user)
123
123
 
124
- active_pods = False
125
-
126
124
  def _kill_pod(pod):
127
- active_pods = True
128
125
  echo("Killing Kubernetes pod %s\n" % pod.metadata.name)
129
126
  try:
130
127
  stream(
@@ -158,10 +155,10 @@ class KubernetesClient(object):
158
155
  echo("failed to kill pod %s - %s" % (pod.metadata.name, str(e)))
159
156
 
160
157
  with ThreadPoolExecutor() as executor:
161
- executor.map(_kill_pod, pods)
158
+ operated_pods = list(executor.map(_kill_pod, pods))
162
159
 
163
- if not active_pods:
164
- echo("No active Kubernetes pods found for run *%s*" % run_id)
160
+ if not operated_pods:
161
+ echo("No active Kubernetes pods found for run *%s*" % run_id)
165
162
 
166
163
  def jobset(self, **kwargs):
167
164
  return KubernetesJobSet(self, **kwargs)
@@ -9,6 +9,7 @@ from metaflow.exception import MetaflowException
9
9
  from metaflow.metaflow_config import KUBERNETES_SECRETS
10
10
  from metaflow.tracing import inject_tracing_vars
11
11
  from metaflow.unbounded_foreach import UBF_CONTROL, UBF_TASK
12
+ from metaflow.metaflow_config_funcs import init_config
12
13
 
13
14
  CLIENT_REFRESH_INTERVAL_SECONDS = 300
14
15
  from .kubernetes_jobsets import (
@@ -74,6 +75,20 @@ class KubernetesJob(object):
74
75
  if self._kwargs["shared_memory"]
75
76
  else None
76
77
  )
78
+ initial_configs = init_config()
79
+ for entry in ["OBP_PERIMETER", "OBP_INTEGRATIONS_SECRETS_METADATA_URL"]:
80
+ if entry not in initial_configs:
81
+ raise KubernetesJobException(
82
+ f"{entry} was not found in metaflow config. Please make sure to run `outerbounds configure <...>` command which can be found on the Ourebounds UI or reach out to your Outerbounds support team."
83
+ )
84
+
85
+ additional_obp_configs = {
86
+ "OBP_PERIMETER": initial_configs["OBP_PERIMETER"],
87
+ "OBP_INTEGRATIONS_SECRETS_METADATA_URL": initial_configs[
88
+ "OBP_INTEGRATIONS_SECRETS_METADATA_URL"
89
+ ],
90
+ }
91
+
77
92
  return client.V1JobSpec(
78
93
  # Retries are handled by Metaflow when it is responsible for
79
94
  # executing the flow. The responsibility is moved to Kubernetes
@@ -135,6 +150,13 @@ class KubernetesJob(object):
135
150
  "METAFLOW_KUBERNETES_NODE_IP": "status.hostIP",
136
151
  }.items()
137
152
  ]
153
+ + [
154
+ client.V1EnvVar(
155
+ name=k,
156
+ value=v,
157
+ )
158
+ for k, v in additional_obp_configs.items()
159
+ ]
138
160
  + [
139
161
  client.V1EnvVar(name=k, value=str(v))
140
162
  for k, v in inject_tracing_vars({}).items()
@@ -270,15 +270,22 @@ class Micromamba(object):
270
270
  except ValueError:
271
271
  vpkg_version = None
272
272
  raise MicromambaException(
273
- "Please set the environment variable CONDA_OVERRIDE_{var} to a specific version{version} of {name}.\n"
274
- "Here is an example of supplying environment variables through the command line -\n\n"
273
+ "{msg}\n\n"
274
+ "*Please set the environment variable CONDA_OVERRIDE_{var} to a specific version{version} of {name}.*\n\n"
275
+ "Here is an example of supplying environment variables through the command line\n"
275
276
  "CONDA_OVERRIDE_{var}=<{name}-version> python flow.py <args>".format(
277
+ msg=msg.format(
278
+ cmd=" ".join(e.cmd),
279
+ code=e.returncode,
280
+ output=e.output.decode(),
281
+ stderr=error,
282
+ ),
276
283
  var=vpkg_name.upper(),
277
284
  version=(
278
- "" if not vpkg_version else (" (%s)" % vpkg_version)
285
+ "" if not vpkg_version else f" ({vpkg_version})"
279
286
  ),
280
287
  name=vpkg_name,
281
- ),
288
+ )
282
289
  )
283
290
  err.append(error)
284
291
  raise MicromambaException(
@@ -140,7 +140,10 @@ class Pip(object):
140
140
  metadata_file = METADATA_FILE.format(prefix=prefix)
141
141
  # download packages only if they haven't ever been downloaded before
142
142
  if os.path.isfile(metadata_file):
143
- return
143
+ with open(metadata_file, "r") as file:
144
+ metadata = json.load(file)
145
+ if all(package["url"] in metadata for package in packages):
146
+ return
144
147
 
145
148
  metadata = {}
146
149
  custom_index_url, extra_index_urls = self.indices(prefix)
metaflow/task.py CHANGED
@@ -180,6 +180,10 @@ class MetaflowTask(object):
180
180
  # 2) join - pop the topmost frame from the stack
181
181
  # 3) step following a split - push a new frame in the stack
182
182
 
183
+ # We have a non-modifying case (case 4)) where we propagate the
184
+ # foreach-stack information to all tasks in the foreach. This is
185
+ # then used later to write the foreach-stack metadata for that task
186
+
183
187
  # case 1) - reset the stack
184
188
  if step_name == "start":
185
189
  self.flow._foreach_stack = []
@@ -264,6 +268,9 @@ class MetaflowTask(object):
264
268
  stack = inputs[0]["_foreach_stack"]
265
269
  stack.append(frame)
266
270
  self.flow._foreach_stack = stack
271
+ # case 4) - propagate in the foreach nest
272
+ elif "_foreach_stack" in inputs[0]:
273
+ self.flow._foreach_stack = inputs[0]["_foreach_stack"]
267
274
 
268
275
  def _clone_flow(self, datastore):
269
276
  x = self.flow.__class__(use_cli=False)
metaflow/version.py CHANGED
@@ -1 +1 @@
1
- metaflow_version = "2.12.23.1"
1
+ metaflow_version = "2.12.25.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob-metaflow
3
- Version: 2.12.23.1
3
+ Version: 2.12.25.1
4
4
  Summary: Metaflow: More Data Science, Less Engineering
5
5
  Author: Netflix, Outerbounds & the Metaflow Community
6
6
  Author-email: help@outerbounds.co
@@ -12,7 +12,7 @@ Requires-Dist: boto3
12
12
  Requires-Dist: pylint
13
13
  Requires-Dist: kubernetes
14
14
  Provides-Extra: stubs
15
- Requires-Dist: metaflow-stubs==2.12.23.1; extra == "stubs"
15
+ Requires-Dist: metaflow-stubs==2.12.25.1; extra == "stubs"
16
16
 
17
17
  ![Metaflow_Logo_Horizontal_FullColor_Ribbon_Dark_RGB](https://user-images.githubusercontent.com/763451/89453116-96a57e00-d713-11ea-9fa6-82b29d4d6eff.png)
18
18
 
@@ -31,12 +31,12 @@ metaflow/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  metaflow/pylint_wrapper.py,sha256=zzBY9YaSUZOGH-ypDKAv2B_7XcoyMZj-zCoCrmYqNRc,2865
32
32
  metaflow/runtime.py,sha256=fbBObJJciagHWPzR3T7x9e_jez_RBnLZIHsXMvYnW_M,68875
33
33
  metaflow/tagging_util.py,sha256=ctyf0Q1gBi0RyZX6J0e9DQGNkNHblV_CITfy66axXB4,2346
34
- metaflow/task.py,sha256=uJHl8K4n3jNllWHSsG1vAZtDza0U2QbQcdg9GS_YPBE,28660
34
+ metaflow/task.py,sha256=5-Qy6wAm7dt7DnhnX1KVhVAKl4DWb3IZWIN5YCdRGIg,29043
35
35
  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=olAvJK3y1it_k99MhLulTaAJo7OFVt5rnrD-ulIFLCU,13616
38
38
  metaflow/vendor.py,sha256=FchtA9tH22JM-eEtJ2c9FpUdMn8sSb1VHuQS56EcdZk,5139
39
- metaflow/version.py,sha256=05uFYfkjTqeZGmqF8PVV-sZGW8rNNdsGp_jJnwXcr4I,31
39
+ metaflow/version.py,sha256=pu5ibRx5X5exQtS3_CEK5XaDBp0Hh7eQMXagfHHVqoA,31
40
40
  metaflow/_vendor/__init__.py,sha256=y_CiwUD3l4eAKvTVDZeqgVujMy31cAM1qjAB-HfI-9s,353
41
41
  metaflow/_vendor/typing_extensions.py,sha256=0nUs5p1A_UrZigrAVBoOEM6TxU37zzPDUtiij1ZwpNc,110417
42
42
  metaflow/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425
@@ -175,8 +175,8 @@ metaflow/plugins/airflow/sensors/s3_sensor.py,sha256=iDReG-7FKnumrtQg-HY6cCUAAqN
175
175
  metaflow/plugins/argo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
176
176
  metaflow/plugins/argo/argo_client.py,sha256=KTUpP0DmnmNsMp4tbdNyKX_zOdTFRVpUkrf7Vv79d-o,16011
177
177
  metaflow/plugins/argo/argo_events.py,sha256=_C1KWztVqgi3zuH57pInaE9OzABc2NnncC-zdwOMZ-w,5909
178
- metaflow/plugins/argo/argo_workflows.py,sha256=dbqZsqn6aHO7HCy23vLkN_a2g2TTzjMv8aMTNAkeDtE,173506
179
- metaflow/plugins/argo/argo_workflows_cli.py,sha256=E_PyhOtxuS2F8DwhBANsRZCMxpeZ5rfID8eksfSOPm8,37231
178
+ metaflow/plugins/argo/argo_workflows.py,sha256=AFP0ZmtsxoAAnReYEgfkGYOIWDdG6Ee-hu37CLMo4gY,175217
179
+ metaflow/plugins/argo/argo_workflows_cli.py,sha256=0qAGo0YlC1Y9-1zqYAzhVCpCcITotfOI421VOIRpseM,37232
180
180
  metaflow/plugins/argo/argo_workflows_decorator.py,sha256=yprszMdbE3rBTcEA9VR0IEnPjTprUauZBc4SBb-Q7sA,7878
181
181
  metaflow/plugins/argo/argo_workflows_deployer.py,sha256=wSSZtThn_VPvE_Wu6NB1L0Q86LmBJh9g009v_lpvBPM,8125
182
182
  metaflow/plugins/argo/capture_error.py,sha256=Ys9dscGrTpW-ZCirLBU0gD9qBM0BjxyxGlUMKcwewQc,1852
@@ -280,11 +280,11 @@ metaflow/plugins/gcp/gs_utils.py,sha256=ZmIGFse1qYyvAVrwga23PQUzF6dXEDLLsZ2F-YRm
280
280
  metaflow/plugins/gcp/includefile_support.py,sha256=vIDeR-MiJuUh-2S2pV7Z7FBkhIWwtHXaRrj76MWGRiY,3869
281
281
  metaflow/plugins/kubernetes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
282
282
  metaflow/plugins/kubernetes/kube_utils.py,sha256=fYDlvqi8jYPsWijDwT6Z2qhQswyFqv7tiwtic_I80Vg,749
283
- metaflow/plugins/kubernetes/kubernetes.py,sha256=bKBqgZXnIDkoa4xKtKoV6InPtYQy4CujfvcbQ3Pvsbc,31305
283
+ metaflow/plugins/kubernetes/kubernetes.py,sha256=HYNIicCfzTL-9q-nEhwURe2z7_dNIe8eOSyzJEBnd4o,32108
284
284
  metaflow/plugins/kubernetes/kubernetes_cli.py,sha256=sFZ9Zrjef85vCO0MGpUF-em8Pw3dePFb3hbX3PtAH4I,13463
285
- metaflow/plugins/kubernetes/kubernetes_client.py,sha256=y_CswSO_OdDW8eC56lwKwC69JqIfo9tYVw0njXc_sj8,6519
285
+ metaflow/plugins/kubernetes/kubernetes_client.py,sha256=tuvXP-QKpdeSmzVolB2R_TaacOr5DIb0j642eKcjsiM,6491
286
286
  metaflow/plugins/kubernetes/kubernetes_decorator.py,sha256=Pr4nzigafYyHgZK4gPnQaQuyxViHozp_idl-AWY3cgk,26871
287
- metaflow/plugins/kubernetes/kubernetes_job.py,sha256=Cfkee8LbXC17jSXWoeNdomQRvF_8YSeXNg1gvxm6E_M,31806
287
+ metaflow/plugins/kubernetes/kubernetes_job.py,sha256=E2Aa-IItwYErlwAbPgwdqJI_l6axBQ-IzKY__psW-nE,32865
288
288
  metaflow/plugins/kubernetes/kubernetes_jobsets.py,sha256=wb0sK1OxW7pRbKdj6bWB4JsskXDsoKKqjyUWo4N9Y6E,41196
289
289
  metaflow/plugins/metadata/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
290
290
  metaflow/plugins/metadata/local.py,sha256=YhLJC5zjVJrvQFIyQ92ZBByiUmhCC762RUX7ITX12O8,22428
@@ -293,8 +293,8 @@ metaflow/plugins/pypi/__init__.py,sha256=0YFZpXvX7HCkyBFglatual7XGifdA1RwC3U4kci
293
293
  metaflow/plugins/pypi/bootstrap.py,sha256=FI-itExqIz7DUzLnnkGwoB60rFBviygpIFThUtqk_4E,5227
294
294
  metaflow/plugins/pypi/conda_decorator.py,sha256=fPeXxvmg51oSFTnlguNlcWUIdXHA9OuMnp9ElaxQPFo,15695
295
295
  metaflow/plugins/pypi/conda_environment.py,sha256=NSBcN4oD_RZONOUrnubLh-ur8EfS0h9PM4r7GNZczyc,19685
296
- metaflow/plugins/pypi/micromamba.py,sha256=HQIxsixkLjqs0ukWGTlATNu5DrbisReOr39Qd21_GZo,13737
297
- metaflow/plugins/pypi/pip.py,sha256=7B06mPOs5MvY33xbzPVYZlBr1iKMYaN-n8uulL9zSVg,13649
296
+ metaflow/plugins/pypi/micromamba.py,sha256=QaZYMy5w4esW2w_Lb9kZdWU07EtZD_Ky00MVlA4FJw0,14079
297
+ metaflow/plugins/pypi/pip.py,sha256=Uewmt6-meLyPhNLiAOAkDdfd1P4Go07bkQUD0uE5VIs,13827
298
298
  metaflow/plugins/pypi/pypi_decorator.py,sha256=rDMbHl7r81Ye7-TuIlKAVJ_CDnfjl9jV44ZPws-UsTY,7229
299
299
  metaflow/plugins/pypi/pypi_environment.py,sha256=FYMg8kF3lXqcLfRYWD83a9zpVjcoo_TARqMGZ763rRk,230
300
300
  metaflow/plugins/pypi/utils.py,sha256=ds1Mnv_DaxGnLAYp7ozg_K6oyguGyNhvHfE-75Ia1YA,2836
@@ -345,9 +345,9 @@ metaflow/tutorials/07-worldview/README.md,sha256=5vQTrFqulJ7rWN6r20dhot9lI2sVj9W
345
345
  metaflow/tutorials/07-worldview/worldview.ipynb,sha256=ztPZPI9BXxvW1QdS2Tfe7LBuVzvFvv0AToDnsDJhLdE,2237
346
346
  metaflow/tutorials/08-autopilot/README.md,sha256=GnePFp_q76jPs991lMUqfIIh5zSorIeWznyiUxzeUVE,1039
347
347
  metaflow/tutorials/08-autopilot/autopilot.ipynb,sha256=DQoJlILV7Mq9vfPBGW-QV_kNhWPjS5n6SJLqePjFYLY,3191
348
- ob_metaflow-2.12.23.1.dist-info/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
349
- ob_metaflow-2.12.23.1.dist-info/METADATA,sha256=81s4jcZ3L8Ugru9il9sH2Yv-FFvbxBrpA_WUvLP4MG8,5143
350
- ob_metaflow-2.12.23.1.dist-info/WHEEL,sha256=AHX6tWk3qWuce7vKLrj7lnulVHEdWoltgauo8bgCXgU,109
351
- ob_metaflow-2.12.23.1.dist-info/entry_points.txt,sha256=IKwTN1T3I5eJL3uo_vnkyxVffcgnRdFbKwlghZfn27k,57
352
- ob_metaflow-2.12.23.1.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
353
- ob_metaflow-2.12.23.1.dist-info/RECORD,,
348
+ ob_metaflow-2.12.25.1.dist-info/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
349
+ ob_metaflow-2.12.25.1.dist-info/METADATA,sha256=YvcCRA52Tr57kElZwUHgPRc1XxTP63gKsjsIQ0ojl-M,5143
350
+ ob_metaflow-2.12.25.1.dist-info/WHEEL,sha256=AHX6tWk3qWuce7vKLrj7lnulVHEdWoltgauo8bgCXgU,109
351
+ ob_metaflow-2.12.25.1.dist-info/entry_points.txt,sha256=IKwTN1T3I5eJL3uo_vnkyxVffcgnRdFbKwlghZfn27k,57
352
+ ob_metaflow-2.12.25.1.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
353
+ ob_metaflow-2.12.25.1.dist-info/RECORD,,