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

metaflow/decorators.py CHANGED
@@ -518,7 +518,8 @@ def _init_flow_decorators(
518
518
  else:
519
519
  # Each "non-multiple" flow decorator is only allowed to have one set of options
520
520
  deco_flow_init_options = {
521
- option: deco_options[option] for option in deco.options
521
+ option: deco_options[option.replace("-", "_")]
522
+ for option in deco.options
522
523
  }
523
524
  for deco in decorators:
524
525
  deco.flow_init(
@@ -324,6 +324,8 @@ KUBERNETES_FETCH_EC2_METADATA = from_conf("KUBERNETES_FETCH_EC2_METADATA", False
324
324
  KUBERNETES_PORT = from_conf("KUBERNETES_PORT", None)
325
325
  # Shared memory in MB to use for this step
326
326
  KUBERNETES_SHARED_MEMORY = from_conf("KUBERNETES_SHARED_MEMORY", None)
327
+ # Default port number to open on the pods
328
+ KUBERNETES_PORT = from_conf("KUBERNETES_PORT", None)
327
329
 
328
330
 
329
331
  ARGO_WORKFLOWS_KUBERNETES_SECRETS = from_conf("ARGO_WORKFLOWS_KUBERNETES_SECRETS", "")
@@ -1386,12 +1386,14 @@ class ArgoWorkflows(object):
1386
1386
  # Set shared_memory to 0 if it isn't specified. This results
1387
1387
  # in Kubernetes using it's default value when the pod is created.
1388
1388
  shared_memory = resources.get("shared_memory", 0)
1389
+ port = resources.get("port", None)
1390
+ if port:
1391
+ port = int(port)
1389
1392
 
1390
1393
  tmpfs_enabled = use_tmpfs or (tmpfs_size and not use_tmpfs)
1391
1394
 
1392
1395
  if tmpfs_enabled and tmpfs_tempdir:
1393
1396
  env["METAFLOW_TEMPDIR"] = tmpfs_path
1394
-
1395
1397
  # Create a ContainerTemplate for this node. Ideally, we would have
1396
1398
  # liked to inline this ContainerTemplate and avoid scanning the workflow
1397
1399
  # twice, but due to issues with variable substitution, we will have to
@@ -1450,6 +1452,9 @@ class ArgoWorkflows(object):
1450
1452
  kubernetes_sdk.V1Container(
1451
1453
  name=self._sanitize(node.name),
1452
1454
  command=cmds,
1455
+ ports=[kubernetes_sdk.V1ContainerPort(container_port=port)]
1456
+ if port
1457
+ else None,
1453
1458
  env=[
1454
1459
  kubernetes_sdk.V1EnvVar(name=k, value=str(v))
1455
1460
  for k, v in env.items()
@@ -1998,8 +2003,10 @@ class ArgoWorkflows(object):
1998
2003
  # Technically, we don't need to create
1999
2004
  # a payload carry-on and can stuff
2000
2005
  # everything within the body.
2001
- data_template="{{ .Input.body.payload.%s | toJson }}"
2002
- % v,
2006
+ # NOTE: We need the conditional logic in order to successfully fall back to the default value
2007
+ # when the event payload does not contain a key for a parameter.
2008
+ data_template='{{ if (hasKey $.Input.body.payload "%s") }}{{- (.Input.body.payload.%s | toJson) -}}{{- else -}}{{ (fail "use-default-instead") }}{{- end -}}'
2009
+ % (v, v),
2003
2010
  # Unfortunately the sensor needs to
2004
2011
  # record the default values for
2005
2012
  # the parameters - there doesn't seem
@@ -72,6 +72,7 @@ class ArgoWorkflowsInternalDecorator(StepDecorator):
72
72
  meta["argo-workflow-name"] = os.environ["ARGO_WORKFLOW_NAME"]
73
73
  meta["argo-workflow-namespace"] = os.environ["ARGO_WORKFLOW_NAMESPACE"]
74
74
  meta["auto-emit-argo-events"] = self.attributes["auto-emit-argo-events"]
75
+ meta["argo-workflow-template-owner"] = os.environ["METAFLOW_OWNER"]
75
76
  entries = [
76
77
  MetaDatum(
77
78
  field=k, value=v, type=k, tags=["attempt_id:{0}".format(retry_count)]
@@ -180,8 +180,8 @@ class Kubernetes(object):
180
180
  annotations=None,
181
181
  num_parallel=0,
182
182
  attrs={},
183
- port=None,
184
183
  shared_memory=None,
184
+ port=None,
185
185
  ):
186
186
  if env is None:
187
187
  env = {}
@@ -223,8 +223,8 @@ class Kubernetes(object):
223
223
  persistent_volume_claims=persistent_volume_claims,
224
224
  num_parallel=num_parallel,
225
225
  attrs=attrs,
226
- port=port,
227
226
  shared_memory=shared_memory,
227
+ port=port,
228
228
  )
229
229
  .environment_variable("METAFLOW_CODE_SHA", code_package_sha)
230
230
  .environment_variable("METAFLOW_CODE_URL", code_package_url)
@@ -126,8 +126,8 @@ def kubernetes():
126
126
  type=int,
127
127
  help="Number of parallel nodes to run as a multi-node job.",
128
128
  )
129
- @click.option("--port", default=None, help="port number")
130
129
  @click.option("--shared-memory", default=None, help="Size of shared memory in MiB")
130
+ @click.option("--port", default=None, help="Port number to expose from the container")
131
131
  @click.pass_context
132
132
  def step(
133
133
  ctx,
@@ -156,8 +156,8 @@ def step(
156
156
  labels=None,
157
157
  annotations=None,
158
158
  num_parallel=None,
159
- port=None,
160
159
  shared_memory=None,
160
+ port=None,
161
161
  **kwargs
162
162
  ):
163
163
  def echo(msg, stream="stderr", job_id=None, **kwargs):
@@ -284,8 +284,8 @@ def step(
284
284
  labels=labels,
285
285
  annotations=annotations,
286
286
  num_parallel=num_parallel,
287
- port=port,
288
287
  shared_memory=shared_memory,
288
+ port=port,
289
289
  attrs=attrs,
290
290
  )
291
291
  except Exception as e:
@@ -23,6 +23,7 @@ from metaflow.metaflow_config import (
23
23
  KUBERNETES_SERVICE_ACCOUNT,
24
24
  KUBERNETES_PORT,
25
25
  KUBERNETES_SHARED_MEMORY,
26
+ KUBERNETES_PORT,
26
27
  )
27
28
  from metaflow.plugins.resources_decorator import ResourcesDecorator
28
29
  from metaflow.plugins.timeout_decorator import get_run_time_limit_for_task
@@ -93,10 +94,10 @@ class KubernetesDecorator(StepDecorator):
93
94
  persistent_volume_claims : Dict[str, str], optional, default None
94
95
  A map (dictionary) of persistent volumes to be mounted to the pod for this step. The map is from persistent
95
96
  volumes to the path to which the volume is to be mounted, e.g., `{'pvc-name': '/path/to/mount/on'}`.
96
- port: int, optional
97
- Number of the port to specify in the Kubernetes job object
98
97
  shared_memory: int, optional
99
- Shared memory size (in MiB) required for this steps
98
+ Shared memory size (in MiB) required for this step
99
+ port: int, optional
100
+ Port number to specify in the Kubernetes job object
100
101
  """
101
102
 
102
103
  name = "kubernetes"
@@ -119,8 +120,8 @@ class KubernetesDecorator(StepDecorator):
119
120
  "tmpfs_size": None,
120
121
  "tmpfs_path": "/metaflow_temp",
121
122
  "persistent_volume_claims": None, # e.g., {"pvc-name": "/mnt/vol", "another-pvc": "/mnt/vol2"}
122
- "port": None,
123
123
  "shared_memory": None,
124
+ "port": None,
124
125
  }
125
126
  package_url = None
126
127
  package_sha = None
@@ -206,10 +207,10 @@ class KubernetesDecorator(StepDecorator):
206
207
  if not self.attributes["tmpfs_size"]:
207
208
  # default tmpfs behavior - https://man7.org/linux/man-pages/man5/tmpfs.5.html
208
209
  self.attributes["tmpfs_size"] = int(self.attributes["memory"]) // 2
209
- if not self.attributes["port"]:
210
- self.attributes["port"] = KUBERNETES_PORT
211
210
  if not self.attributes["shared_memory"]:
212
211
  self.attributes["shared_memory"] = KUBERNETES_SHARED_MEMORY
212
+ if not self.attributes["port"]:
213
+ self.attributes["port"] = KUBERNETES_PORT
213
214
 
214
215
  # Refer https://github.com/Netflix/metaflow/blob/master/docs/lifecycle.png
215
216
  def step_init(self, flow, graph, step, decos, environment, flow_datastore, logger):
@@ -287,7 +288,7 @@ class KubernetesDecorator(StepDecorator):
287
288
  if "memory" in self.attributes and MAX_MEMORY_PER_TASK:
288
289
  if float(self.attributes["memory"]) > float(MAX_MEMORY_PER_TASK):
289
290
  raise MetaflowException(
290
- "Step %s requires %s CPU units, but you cannot use more than %s per step in this environment"
291
+ "Step %s requires %s memory, but you cannot use more than %s per step in this environment"
291
292
  % (step, self.attributes["memory"], MAX_MEMORY_PER_TASK)
292
293
  )
293
294
 
@@ -423,6 +423,12 @@ class KubernetesJob(object):
423
423
  main_commands[-1] = "/usr/sbin/sshd -D & %s" % main_commands[-1]
424
424
  secondary_commands[-1] = "/usr/sbin/sshd -D & %s" % secondary_commands[-1]
425
425
 
426
+ replicated_jobs = [_get_replicated_job("control", 1, main_commands)]
427
+ if self._kwargs["num_parallel"] > 1:
428
+ replicated_jobs.append(
429
+ _get_replicated_job("worker", self._kwargs["num_parallel"] - 1, secondary_commands)
430
+ )
431
+
426
432
  self._jobset = jobset.models.jobset_v1alpha2_job_set.JobsetV1alpha2JobSet(
427
433
  api_version="jobset.x-k8s.io/v1alpha2",
428
434
  kind="JobSet",
@@ -437,14 +443,7 @@ class KubernetesJob(object):
437
443
  enable_dns_hostnames=True if not self._kwargs['attrs']['requires_passwordless_ssh'] else False,
438
444
  subdomain=subdomain
439
445
  ),
440
- replicated_jobs=[
441
- _get_replicated_job("control", 1, main_commands),
442
- _get_replicated_job(
443
- "worker",
444
- self._kwargs["num_parallel"] - 1,
445
- secondary_commands,
446
- ),
447
- ],
446
+ replicated_jobs=replicated_jobs
448
447
  ),
449
448
  )
450
449
  self._passwordless_ssh_service = _get_passwordless_ssh_service()
@@ -484,6 +483,13 @@ class KubernetesJob(object):
484
483
  containers=[
485
484
  client.V1Container(
486
485
  command=self._kwargs["command"],
486
+ ports=[
487
+ client.V1ContainerPort(
488
+ container_port=int(self._kwargs["port"])
489
+ )
490
+ ]
491
+ if "port" in self._kwargs and self._kwargs["port"]
492
+ else None,
487
493
  env=[
488
494
  client.V1EnvVar(name=k, value=str(v))
489
495
  for k, v in self._kwargs.get(
metaflow/version.py CHANGED
@@ -1 +1 @@
1
- metaflow_version = "2.11.9.1"
1
+ metaflow_version = "2.11.10.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ob-metaflow
3
- Version: 2.11.9.1
3
+ Version: 2.11.10.2
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: ob-metaflow-stubs ==2.11.9.1 ; extra == 'stubs'
15
+ Requires-Dist: ob-metaflow-stubs ==2.11.10.2 ; 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
 
@@ -6,7 +6,7 @@ metaflow/cli_args.py,sha256=lcgBGNTvfaiPxiUnejAe60Upt9swG6lRy1_3OqbU6MY,2616
6
6
  metaflow/clone_util.py,sha256=ar4jSZt2aTd4monBpkIQmcLcsOd0relAB42qTUGt2j8,1810
7
7
  metaflow/cmd_with_io.py,sha256=kl53HkAIyv0ecpItv08wZYczv7u3msD1VCcciqigqf0,588
8
8
  metaflow/debug.py,sha256=HEmt_16tJtqHXQXsqD9pqOFe3CWR5GZ7VwpaYQgnRdU,1466
9
- metaflow/decorators.py,sha256=EGL1_nkdxoYG5AZiOQ8sLGA1bprGK8ENwlSIOYQmLhs,21357
9
+ metaflow/decorators.py,sha256=n91bvWA4JJWHwZnI02-rFGBZsWWMtaABYlWYcOvHuRw,21391
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=KC1LHJQzzYkWib0DeQ4l_A2r8VaudywsSqIQuq1RDZU,4954
@@ -15,7 +15,7 @@ metaflow/graph.py,sha256=ZPxyG8uwVMk5YYgX4pQEQaPZtZM5Wy-G4NtJK73IEuA,11818
15
15
  metaflow/includefile.py,sha256=yHczcZ_U0SrasxSNhZb3DIBzx8UZnrJCl3FzvpEQLOA,19753
16
16
  metaflow/integrations.py,sha256=LlsaoePRg03DjENnmLxZDYto3NwWc9z_PtU6nJxLldg,1480
17
17
  metaflow/lint.py,sha256=_kYAbAtsP7IG1Rd0FqNbo8I8Zs66_0WXbaZJFARO3dE,10394
18
- metaflow/metaflow_config.py,sha256=WmO8-gQeLlbUJb88REHuR77nll8FF_yQ68pS9bT9Pfs,20624
18
+ metaflow/metaflow_config.py,sha256=mcbOTNN6sFX64oAxGU8i-sgv2Eb9xaK2C31zfWUCzYw,20719
19
19
  metaflow/metaflow_config_funcs.py,sha256=pCaiQ2ez9wXixJI3ehmf3QiW9lUqFrZnBZx1my_0wIg,4874
20
20
  metaflow/metaflow_current.py,sha256=sCENPBiji3LcPbwgOG0ukGd_yEc5tST8EowES8DzRtA,7430
21
21
  metaflow/metaflow_environment.py,sha256=XiMmBZiq3_dwaw0Oi3B8588BahYxzgfqWGMePPZqUUc,7359
@@ -34,7 +34,7 @@ metaflow/task.py,sha256=ecGaULbK8kXPnyWzH1u6wtGclm0qeJm7K95amEL17sQ,25863
34
34
  metaflow/unbounded_foreach.py,sha256=p184WMbrMJ3xKYHwewj27ZhRUsSj_kw1jlye5gA9xJk,387
35
35
  metaflow/util.py,sha256=RrjsvADLKxSqjL76CxKh_J4OJl840B9Ak3V-vXleGas,13429
36
36
  metaflow/vendor.py,sha256=LZgXrh7ZSDmD32D1T5jj3OKKpXIqqxKzdMAOc5V0SD4,5162
37
- metaflow/version.py,sha256=yKncWWFL4OF_XHTiyjxLWbQHk0S4UO7_4qNT0J936-s,30
37
+ metaflow/version.py,sha256=0OX3kt6OXRJDfZgJNAG22iVhu6nDCYv5HFtwAFqZOd8,31
38
38
  metaflow/_vendor/__init__.py,sha256=y_CiwUD3l4eAKvTVDZeqgVujMy31cAM1qjAB-HfI-9s,353
39
39
  metaflow/_vendor/click/__init__.py,sha256=FkyGDQ-cbiQxP_lxgUspyFYS48f2S_pTcfKPz-d_RMo,2463
40
40
  metaflow/_vendor/click/_bashcomplete.py,sha256=9J98IHQYmCAr2Jup6TDshUr5FJEen-AoQCZR0K5nKxQ,12309
@@ -149,9 +149,9 @@ metaflow/plugins/airflow/sensors/s3_sensor.py,sha256=JUKoGNoTCtrO9MNEneEC7ldRNwg
149
149
  metaflow/plugins/argo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
150
  metaflow/plugins/argo/argo_client.py,sha256=MKKhMCbWOPzf6z5zQQiyDRHHkAXcO7ipboDZDqAAvOk,15849
151
151
  metaflow/plugins/argo/argo_events.py,sha256=_C1KWztVqgi3zuH57pInaE9OzABc2NnncC-zdwOMZ-w,5909
152
- metaflow/plugins/argo/argo_workflows.py,sha256=lwfCFmgnQiAO5VscqkRWjVtOvcwoZ2gYX0zo3DxtGig,122919
152
+ metaflow/plugins/argo/argo_workflows.py,sha256=uEjOTAOr6y8tExuDjQuSIHZFS_2HsW-tTdRJtTcO4cc,123546
153
153
  metaflow/plugins/argo/argo_workflows_cli.py,sha256=sZTpgfmc50eT3e0qIxpVqUgWhTcYlO1HM4gU6Oaya8g,33259
154
- metaflow/plugins/argo/argo_workflows_decorator.py,sha256=CfKVoHCOsCCQMghhPE30xw15gacwp3hR23HCo9ZZFVg,6580
154
+ metaflow/plugins/argo/argo_workflows_decorator.py,sha256=kCtwB6grJso5UwxKSirJn7L9BWP5rd3arBunAyS-uuU,6656
155
155
  metaflow/plugins/argo/process_input_paths.py,sha256=LjUSP8PVU-DRGEPxjas99nzyAO-fI82Bxxbr_QETE88,565
156
156
  metaflow/plugins/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
157
  metaflow/plugins/aws/aws_client.py,sha256=mO8UD6pxFaOnxDb3hTP3HB7Gqb_ZxoR-76LT683WHvI,4036
@@ -248,11 +248,11 @@ metaflow/plugins/gcp/gs_tail.py,sha256=Jl_wvnzU7dub07A-DOAuP5FeccNIrPM-CeL1xKFs1
248
248
  metaflow/plugins/gcp/gs_utils.py,sha256=ZmIGFse1qYyvAVrwga23PQUzF6dXEDLLsZ2F-YRmvow,2030
249
249
  metaflow/plugins/gcp/includefile_support.py,sha256=vIDeR-MiJuUh-2S2pV7Z7FBkhIWwtHXaRrj76MWGRiY,3869
250
250
  metaflow/plugins/kubernetes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
251
- metaflow/plugins/kubernetes/kubernetes.py,sha256=Mbah7ALEpExO3NM_Tnrme8DvSLVUpb5tKPAChD84LwQ,19233
252
- metaflow/plugins/kubernetes/kubernetes_cli.py,sha256=Erx2fKijcpDuotdugak7PzWcp1ZmO-Pr-mP6B7LHV7Q,10245
251
+ metaflow/plugins/kubernetes/kubernetes.py,sha256=5wM8_gRuyyyIv9mbX2lCePsLHoiDgJnbzYwnJy_NEoE,19233
252
+ metaflow/plugins/kubernetes/kubernetes_cli.py,sha256=wSByGQEaoQo1aV9kJoKYmbVVeFQVsMw9RfG4Bw2sMm8,10274
253
253
  metaflow/plugins/kubernetes/kubernetes_client.py,sha256=irATJpAob4jINkJw0zT_Xoa6JHRtYxx2IOeimlbzvPo,2373
254
- metaflow/plugins/kubernetes/kubernetes_decorator.py,sha256=obJicDXD5tZP_GO0SpoaTKqjcnR4uSN2q_r6W_vvqWA,24994
255
- metaflow/plugins/kubernetes/kubernetes_job.py,sha256=X9wgxQsvKlJ_yLIg0jHnIXUELhnNmGRq_8XnDvyn3bk,52259
254
+ metaflow/plugins/kubernetes/kubernetes_decorator.py,sha256=3zzCETYE5DtCzcuxQxh60ELTWD6Z4UIJyBqOBSh4rl4,25004
255
+ metaflow/plugins/kubernetes/kubernetes_job.py,sha256=OUAol0FxrXw_g7QSn85f6SHECmtfEGDFLNbEqh4lL4Q,52656
256
256
  metaflow/plugins/metadata/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
257
257
  metaflow/plugins/metadata/local.py,sha256=YhLJC5zjVJrvQFIyQ92ZBByiUmhCC762RUX7ITX12O8,22428
258
258
  metaflow/plugins/metadata/service.py,sha256=ihq5F7KQZlxvYwzH_-jyP2aWN_I96i2vp92j_d697s8,20204
@@ -300,9 +300,9 @@ metaflow/tutorials/07-worldview/README.md,sha256=5vQTrFqulJ7rWN6r20dhot9lI2sVj9W
300
300
  metaflow/tutorials/07-worldview/worldview.ipynb,sha256=ztPZPI9BXxvW1QdS2Tfe7LBuVzvFvv0AToDnsDJhLdE,2237
301
301
  metaflow/tutorials/08-autopilot/README.md,sha256=GnePFp_q76jPs991lMUqfIIh5zSorIeWznyiUxzeUVE,1039
302
302
  metaflow/tutorials/08-autopilot/autopilot.ipynb,sha256=DQoJlILV7Mq9vfPBGW-QV_kNhWPjS5n6SJLqePjFYLY,3191
303
- ob_metaflow-2.11.9.1.dist-info/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
304
- ob_metaflow-2.11.9.1.dist-info/METADATA,sha256=64Tiuqy8ZT3w-c-taFJlO9-WwgcjT2LxLfX3t-LBfAI,5146
305
- ob_metaflow-2.11.9.1.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
306
- ob_metaflow-2.11.9.1.dist-info/entry_points.txt,sha256=IKwTN1T3I5eJL3uo_vnkyxVffcgnRdFbKwlghZfn27k,57
307
- ob_metaflow-2.11.9.1.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
308
- ob_metaflow-2.11.9.1.dist-info/RECORD,,
303
+ ob_metaflow-2.11.10.2.dist-info/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
304
+ ob_metaflow-2.11.10.2.dist-info/METADATA,sha256=se5ZQsb_11McpFE5wdLOh9KeraVfAIjnYcpav3oLt5E,5148
305
+ ob_metaflow-2.11.10.2.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
306
+ ob_metaflow-2.11.10.2.dist-info/entry_points.txt,sha256=IKwTN1T3I5eJL3uo_vnkyxVffcgnRdFbKwlghZfn27k,57
307
+ ob_metaflow-2.11.10.2.dist-info/top_level.txt,sha256=v1pDHoWaSaKeuc5fKTRSfsXCKSdW1zvNVmvA-i0if3o,9
308
+ ob_metaflow-2.11.10.2.dist-info/RECORD,,