ob-metaflow 2.11.13.1__py2.py3-none-any.whl → 2.19.7.1rc0__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.
Files changed (289) hide show
  1. metaflow/R.py +10 -7
  2. metaflow/__init__.py +40 -25
  3. metaflow/_vendor/imghdr/__init__.py +186 -0
  4. metaflow/_vendor/importlib_metadata/__init__.py +1063 -0
  5. metaflow/_vendor/importlib_metadata/_adapters.py +68 -0
  6. metaflow/_vendor/importlib_metadata/_collections.py +30 -0
  7. metaflow/_vendor/importlib_metadata/_compat.py +71 -0
  8. metaflow/_vendor/importlib_metadata/_functools.py +104 -0
  9. metaflow/_vendor/importlib_metadata/_itertools.py +73 -0
  10. metaflow/_vendor/importlib_metadata/_meta.py +48 -0
  11. metaflow/_vendor/importlib_metadata/_text.py +99 -0
  12. metaflow/_vendor/importlib_metadata/py.typed +0 -0
  13. metaflow/_vendor/typeguard/__init__.py +48 -0
  14. metaflow/_vendor/typeguard/_checkers.py +1070 -0
  15. metaflow/_vendor/typeguard/_config.py +108 -0
  16. metaflow/_vendor/typeguard/_decorators.py +233 -0
  17. metaflow/_vendor/typeguard/_exceptions.py +42 -0
  18. metaflow/_vendor/typeguard/_functions.py +308 -0
  19. metaflow/_vendor/typeguard/_importhook.py +213 -0
  20. metaflow/_vendor/typeguard/_memo.py +48 -0
  21. metaflow/_vendor/typeguard/_pytest_plugin.py +127 -0
  22. metaflow/_vendor/typeguard/_suppression.py +86 -0
  23. metaflow/_vendor/typeguard/_transformer.py +1229 -0
  24. metaflow/_vendor/typeguard/_union_transformer.py +55 -0
  25. metaflow/_vendor/typeguard/_utils.py +173 -0
  26. metaflow/_vendor/typeguard/py.typed +0 -0
  27. metaflow/_vendor/typing_extensions.py +3641 -0
  28. metaflow/_vendor/v3_7/importlib_metadata/__init__.py +1063 -0
  29. metaflow/_vendor/v3_7/importlib_metadata/_adapters.py +68 -0
  30. metaflow/_vendor/v3_7/importlib_metadata/_collections.py +30 -0
  31. metaflow/_vendor/v3_7/importlib_metadata/_compat.py +71 -0
  32. metaflow/_vendor/v3_7/importlib_metadata/_functools.py +104 -0
  33. metaflow/_vendor/v3_7/importlib_metadata/_itertools.py +73 -0
  34. metaflow/_vendor/v3_7/importlib_metadata/_meta.py +48 -0
  35. metaflow/_vendor/v3_7/importlib_metadata/_text.py +99 -0
  36. metaflow/_vendor/v3_7/importlib_metadata/py.typed +0 -0
  37. metaflow/_vendor/v3_7/typeguard/__init__.py +48 -0
  38. metaflow/_vendor/v3_7/typeguard/_checkers.py +906 -0
  39. metaflow/_vendor/v3_7/typeguard/_config.py +108 -0
  40. metaflow/_vendor/v3_7/typeguard/_decorators.py +237 -0
  41. metaflow/_vendor/v3_7/typeguard/_exceptions.py +42 -0
  42. metaflow/_vendor/v3_7/typeguard/_functions.py +310 -0
  43. metaflow/_vendor/v3_7/typeguard/_importhook.py +213 -0
  44. metaflow/_vendor/v3_7/typeguard/_memo.py +48 -0
  45. metaflow/_vendor/v3_7/typeguard/_pytest_plugin.py +100 -0
  46. metaflow/_vendor/v3_7/typeguard/_suppression.py +88 -0
  47. metaflow/_vendor/v3_7/typeguard/_transformer.py +1207 -0
  48. metaflow/_vendor/v3_7/typeguard/_union_transformer.py +54 -0
  49. metaflow/_vendor/v3_7/typeguard/_utils.py +169 -0
  50. metaflow/_vendor/v3_7/typeguard/py.typed +0 -0
  51. metaflow/_vendor/v3_7/typing_extensions.py +3072 -0
  52. metaflow/_vendor/yaml/__init__.py +427 -0
  53. metaflow/_vendor/yaml/composer.py +139 -0
  54. metaflow/_vendor/yaml/constructor.py +748 -0
  55. metaflow/_vendor/yaml/cyaml.py +101 -0
  56. metaflow/_vendor/yaml/dumper.py +62 -0
  57. metaflow/_vendor/yaml/emitter.py +1137 -0
  58. metaflow/_vendor/yaml/error.py +75 -0
  59. metaflow/_vendor/yaml/events.py +86 -0
  60. metaflow/_vendor/yaml/loader.py +63 -0
  61. metaflow/_vendor/yaml/nodes.py +49 -0
  62. metaflow/_vendor/yaml/parser.py +589 -0
  63. metaflow/_vendor/yaml/reader.py +185 -0
  64. metaflow/_vendor/yaml/representer.py +389 -0
  65. metaflow/_vendor/yaml/resolver.py +227 -0
  66. metaflow/_vendor/yaml/scanner.py +1435 -0
  67. metaflow/_vendor/yaml/serializer.py +111 -0
  68. metaflow/_vendor/yaml/tokens.py +104 -0
  69. metaflow/cards.py +5 -0
  70. metaflow/cli.py +331 -785
  71. metaflow/cli_args.py +17 -0
  72. metaflow/cli_components/__init__.py +0 -0
  73. metaflow/cli_components/dump_cmd.py +96 -0
  74. metaflow/cli_components/init_cmd.py +52 -0
  75. metaflow/cli_components/run_cmds.py +546 -0
  76. metaflow/cli_components/step_cmd.py +334 -0
  77. metaflow/cli_components/utils.py +140 -0
  78. metaflow/client/__init__.py +1 -0
  79. metaflow/client/core.py +467 -73
  80. metaflow/client/filecache.py +75 -35
  81. metaflow/clone_util.py +7 -1
  82. metaflow/cmd/code/__init__.py +231 -0
  83. metaflow/cmd/develop/stub_generator.py +756 -288
  84. metaflow/cmd/develop/stubs.py +12 -28
  85. metaflow/cmd/main_cli.py +6 -4
  86. metaflow/cmd/make_wrapper.py +78 -0
  87. metaflow/datastore/__init__.py +1 -0
  88. metaflow/datastore/content_addressed_store.py +41 -10
  89. metaflow/datastore/datastore_set.py +11 -2
  90. metaflow/datastore/flow_datastore.py +156 -10
  91. metaflow/datastore/spin_datastore.py +91 -0
  92. metaflow/datastore/task_datastore.py +154 -39
  93. metaflow/debug.py +5 -0
  94. metaflow/decorators.py +404 -78
  95. metaflow/exception.py +8 -2
  96. metaflow/extension_support/__init__.py +527 -376
  97. metaflow/extension_support/_empty_file.py +2 -2
  98. metaflow/extension_support/plugins.py +49 -31
  99. metaflow/flowspec.py +482 -33
  100. metaflow/graph.py +210 -42
  101. metaflow/includefile.py +84 -40
  102. metaflow/lint.py +141 -22
  103. metaflow/meta_files.py +13 -0
  104. metaflow/{metadata → metadata_provider}/heartbeat.py +24 -8
  105. metaflow/{metadata → metadata_provider}/metadata.py +86 -1
  106. metaflow/metaflow_config.py +175 -28
  107. metaflow/metaflow_config_funcs.py +51 -3
  108. metaflow/metaflow_current.py +4 -10
  109. metaflow/metaflow_environment.py +139 -53
  110. metaflow/metaflow_git.py +115 -0
  111. metaflow/metaflow_profile.py +18 -0
  112. metaflow/metaflow_version.py +150 -66
  113. metaflow/mflog/__init__.py +4 -3
  114. metaflow/mflog/save_logs.py +2 -2
  115. metaflow/multicore_utils.py +31 -14
  116. metaflow/package/__init__.py +673 -0
  117. metaflow/packaging_sys/__init__.py +880 -0
  118. metaflow/packaging_sys/backend.py +128 -0
  119. metaflow/packaging_sys/distribution_support.py +153 -0
  120. metaflow/packaging_sys/tar_backend.py +99 -0
  121. metaflow/packaging_sys/utils.py +54 -0
  122. metaflow/packaging_sys/v1.py +527 -0
  123. metaflow/parameters.py +149 -28
  124. metaflow/plugins/__init__.py +74 -5
  125. metaflow/plugins/airflow/airflow.py +40 -25
  126. metaflow/plugins/airflow/airflow_cli.py +22 -5
  127. metaflow/plugins/airflow/airflow_decorator.py +1 -1
  128. metaflow/plugins/airflow/airflow_utils.py +5 -3
  129. metaflow/plugins/airflow/sensors/base_sensor.py +4 -4
  130. metaflow/plugins/airflow/sensors/external_task_sensor.py +2 -2
  131. metaflow/plugins/airflow/sensors/s3_sensor.py +2 -2
  132. metaflow/plugins/argo/argo_client.py +78 -33
  133. metaflow/plugins/argo/argo_events.py +6 -6
  134. metaflow/plugins/argo/argo_workflows.py +2410 -527
  135. metaflow/plugins/argo/argo_workflows_cli.py +571 -121
  136. metaflow/plugins/argo/argo_workflows_decorator.py +43 -12
  137. metaflow/plugins/argo/argo_workflows_deployer.py +106 -0
  138. metaflow/plugins/argo/argo_workflows_deployer_objects.py +453 -0
  139. metaflow/plugins/argo/capture_error.py +73 -0
  140. metaflow/plugins/argo/conditional_input_paths.py +35 -0
  141. metaflow/plugins/argo/exit_hooks.py +209 -0
  142. metaflow/plugins/argo/jobset_input_paths.py +15 -0
  143. metaflow/plugins/argo/param_val.py +19 -0
  144. metaflow/plugins/aws/aws_client.py +10 -3
  145. metaflow/plugins/aws/aws_utils.py +55 -2
  146. metaflow/plugins/aws/batch/batch.py +72 -5
  147. metaflow/plugins/aws/batch/batch_cli.py +33 -10
  148. metaflow/plugins/aws/batch/batch_client.py +4 -3
  149. metaflow/plugins/aws/batch/batch_decorator.py +102 -35
  150. metaflow/plugins/aws/secrets_manager/aws_secrets_manager_secrets_provider.py +13 -10
  151. metaflow/plugins/aws/step_functions/dynamo_db_client.py +0 -3
  152. metaflow/plugins/aws/step_functions/production_token.py +1 -1
  153. metaflow/plugins/aws/step_functions/step_functions.py +65 -8
  154. metaflow/plugins/aws/step_functions/step_functions_cli.py +101 -7
  155. metaflow/plugins/aws/step_functions/step_functions_decorator.py +1 -2
  156. metaflow/plugins/aws/step_functions/step_functions_deployer.py +97 -0
  157. metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +264 -0
  158. metaflow/plugins/azure/azure_exceptions.py +1 -1
  159. metaflow/plugins/azure/azure_secret_manager_secrets_provider.py +240 -0
  160. metaflow/plugins/azure/azure_tail.py +1 -1
  161. metaflow/plugins/azure/includefile_support.py +2 -0
  162. metaflow/plugins/cards/card_cli.py +66 -30
  163. metaflow/plugins/cards/card_creator.py +25 -1
  164. metaflow/plugins/cards/card_datastore.py +21 -49
  165. metaflow/plugins/cards/card_decorator.py +132 -8
  166. metaflow/plugins/cards/card_modules/basic.py +112 -17
  167. metaflow/plugins/cards/card_modules/bundle.css +1 -1
  168. metaflow/plugins/cards/card_modules/card.py +16 -1
  169. metaflow/plugins/cards/card_modules/chevron/renderer.py +1 -1
  170. metaflow/plugins/cards/card_modules/components.py +665 -28
  171. metaflow/plugins/cards/card_modules/convert_to_native_type.py +36 -7
  172. metaflow/plugins/cards/card_modules/json_viewer.py +232 -0
  173. metaflow/plugins/cards/card_modules/main.css +1 -0
  174. metaflow/plugins/cards/card_modules/main.js +68 -49
  175. metaflow/plugins/cards/card_modules/renderer_tools.py +1 -0
  176. metaflow/plugins/cards/card_modules/test_cards.py +26 -12
  177. metaflow/plugins/cards/card_server.py +39 -14
  178. metaflow/plugins/cards/component_serializer.py +2 -9
  179. metaflow/plugins/cards/metadata.py +22 -0
  180. metaflow/plugins/catch_decorator.py +9 -0
  181. metaflow/plugins/datastores/azure_storage.py +10 -1
  182. metaflow/plugins/datastores/gs_storage.py +6 -2
  183. metaflow/plugins/datastores/local_storage.py +12 -6
  184. metaflow/plugins/datastores/spin_storage.py +12 -0
  185. metaflow/plugins/datatools/local.py +2 -0
  186. metaflow/plugins/datatools/s3/s3.py +126 -75
  187. metaflow/plugins/datatools/s3/s3op.py +254 -121
  188. metaflow/plugins/env_escape/__init__.py +3 -3
  189. metaflow/plugins/env_escape/client_modules.py +102 -72
  190. metaflow/plugins/env_escape/server.py +7 -0
  191. metaflow/plugins/env_escape/stub.py +24 -5
  192. metaflow/plugins/events_decorator.py +343 -185
  193. metaflow/plugins/exit_hook/__init__.py +0 -0
  194. metaflow/plugins/exit_hook/exit_hook_decorator.py +46 -0
  195. metaflow/plugins/exit_hook/exit_hook_script.py +52 -0
  196. metaflow/plugins/gcp/__init__.py +1 -1
  197. metaflow/plugins/gcp/gcp_secret_manager_secrets_provider.py +11 -6
  198. metaflow/plugins/gcp/gs_tail.py +10 -6
  199. metaflow/plugins/gcp/includefile_support.py +3 -0
  200. metaflow/plugins/kubernetes/kube_utils.py +108 -0
  201. metaflow/plugins/kubernetes/kubernetes.py +411 -130
  202. metaflow/plugins/kubernetes/kubernetes_cli.py +168 -36
  203. metaflow/plugins/kubernetes/kubernetes_client.py +104 -2
  204. metaflow/plugins/kubernetes/kubernetes_decorator.py +246 -88
  205. metaflow/plugins/kubernetes/kubernetes_job.py +253 -581
  206. metaflow/plugins/kubernetes/kubernetes_jobsets.py +1071 -0
  207. metaflow/plugins/kubernetes/spot_metadata_cli.py +69 -0
  208. metaflow/plugins/kubernetes/spot_monitor_sidecar.py +109 -0
  209. metaflow/plugins/logs_cli.py +359 -0
  210. metaflow/plugins/{metadata → metadata_providers}/local.py +144 -84
  211. metaflow/plugins/{metadata → metadata_providers}/service.py +103 -26
  212. metaflow/plugins/metadata_providers/spin.py +16 -0
  213. metaflow/plugins/package_cli.py +36 -24
  214. metaflow/plugins/parallel_decorator.py +128 -11
  215. metaflow/plugins/parsers.py +16 -0
  216. metaflow/plugins/project_decorator.py +51 -5
  217. metaflow/plugins/pypi/bootstrap.py +357 -105
  218. metaflow/plugins/pypi/conda_decorator.py +82 -81
  219. metaflow/plugins/pypi/conda_environment.py +187 -52
  220. metaflow/plugins/pypi/micromamba.py +157 -47
  221. metaflow/plugins/pypi/parsers.py +268 -0
  222. metaflow/plugins/pypi/pip.py +88 -13
  223. metaflow/plugins/pypi/pypi_decorator.py +37 -1
  224. metaflow/plugins/pypi/utils.py +48 -2
  225. metaflow/plugins/resources_decorator.py +2 -2
  226. metaflow/plugins/secrets/__init__.py +3 -0
  227. metaflow/plugins/secrets/secrets_decorator.py +26 -181
  228. metaflow/plugins/secrets/secrets_func.py +49 -0
  229. metaflow/plugins/secrets/secrets_spec.py +101 -0
  230. metaflow/plugins/secrets/utils.py +74 -0
  231. metaflow/plugins/tag_cli.py +4 -7
  232. metaflow/plugins/test_unbounded_foreach_decorator.py +41 -6
  233. metaflow/plugins/timeout_decorator.py +3 -3
  234. metaflow/plugins/uv/__init__.py +0 -0
  235. metaflow/plugins/uv/bootstrap.py +128 -0
  236. metaflow/plugins/uv/uv_environment.py +72 -0
  237. metaflow/procpoll.py +1 -1
  238. metaflow/pylint_wrapper.py +5 -1
  239. metaflow/runner/__init__.py +0 -0
  240. metaflow/runner/click_api.py +717 -0
  241. metaflow/runner/deployer.py +470 -0
  242. metaflow/runner/deployer_impl.py +201 -0
  243. metaflow/runner/metaflow_runner.py +714 -0
  244. metaflow/runner/nbdeploy.py +132 -0
  245. metaflow/runner/nbrun.py +225 -0
  246. metaflow/runner/subprocess_manager.py +650 -0
  247. metaflow/runner/utils.py +335 -0
  248. metaflow/runtime.py +1078 -260
  249. metaflow/sidecar/sidecar_worker.py +1 -1
  250. metaflow/system/__init__.py +5 -0
  251. metaflow/system/system_logger.py +85 -0
  252. metaflow/system/system_monitor.py +108 -0
  253. metaflow/system/system_utils.py +19 -0
  254. metaflow/task.py +521 -225
  255. metaflow/tracing/__init__.py +7 -7
  256. metaflow/tracing/span_exporter.py +31 -38
  257. metaflow/tracing/tracing_modules.py +38 -43
  258. metaflow/tuple_util.py +27 -0
  259. metaflow/user_configs/__init__.py +0 -0
  260. metaflow/user_configs/config_options.py +563 -0
  261. metaflow/user_configs/config_parameters.py +598 -0
  262. metaflow/user_decorators/__init__.py +0 -0
  263. metaflow/user_decorators/common.py +144 -0
  264. metaflow/user_decorators/mutable_flow.py +512 -0
  265. metaflow/user_decorators/mutable_step.py +424 -0
  266. metaflow/user_decorators/user_flow_decorator.py +264 -0
  267. metaflow/user_decorators/user_step_decorator.py +749 -0
  268. metaflow/util.py +243 -27
  269. metaflow/vendor.py +23 -7
  270. metaflow/version.py +1 -1
  271. ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/Makefile +355 -0
  272. ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/Tiltfile +726 -0
  273. ob_metaflow-2.19.7.1rc0.data/data/share/metaflow/devtools/pick_services.sh +105 -0
  274. ob_metaflow-2.19.7.1rc0.dist-info/METADATA +87 -0
  275. ob_metaflow-2.19.7.1rc0.dist-info/RECORD +445 -0
  276. {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/WHEEL +1 -1
  277. {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/entry_points.txt +1 -0
  278. metaflow/_vendor/v3_5/__init__.py +0 -1
  279. metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -644
  280. metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -152
  281. metaflow/package.py +0 -188
  282. ob_metaflow-2.11.13.1.dist-info/METADATA +0 -85
  283. ob_metaflow-2.11.13.1.dist-info/RECORD +0 -308
  284. /metaflow/_vendor/{v3_5/zipp.py → zipp.py} +0 -0
  285. /metaflow/{metadata → metadata_provider}/__init__.py +0 -0
  286. /metaflow/{metadata → metadata_provider}/util.py +0 -0
  287. /metaflow/plugins/{metadata → metadata_providers}/__init__.py +0 -0
  288. {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info/licenses}/LICENSE +0 -0
  289. {ob_metaflow-2.11.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/top_level.txt +0 -0
@@ -2,20 +2,30 @@ import collections
2
2
  import glob
3
3
  import json
4
4
  import os
5
+ import re
5
6
  import random
6
7
  import tempfile
7
8
  import time
8
9
  from collections import namedtuple
10
+ from typing import List
9
11
 
10
12
  from metaflow.exception import MetaflowInternalError, MetaflowTaggingError
11
- from metaflow.metadata.metadata import ObjectOrder
13
+ from metaflow.metadata_provider.metadata import ObjectOrder
12
14
  from metaflow.metaflow_config import DATASTORE_LOCAL_DIR
13
- from metaflow.metadata import MetadataProvider
15
+ from metaflow.metadata_provider import MetadataProvider
14
16
  from metaflow.tagging_util import MAX_USER_TAG_SET_SIZE, validate_tags
15
17
 
16
18
 
17
19
  class LocalMetadataProvider(MetadataProvider):
18
20
  TYPE = "local"
21
+ DATASTORE_DIR = DATASTORE_LOCAL_DIR # ".metaflow"
22
+
23
+ @classmethod
24
+ def _get_storage_class(cls):
25
+ # This method is meant to be overridden
26
+ from metaflow.plugins.datastores.local_storage import LocalStorage
27
+
28
+ return LocalStorage
19
29
 
20
30
  def __init__(self, environment, flow, event_logger, monitor):
21
31
  super(LocalMetadataProvider, self).__init__(
@@ -24,30 +34,28 @@ class LocalMetadataProvider(MetadataProvider):
24
34
 
25
35
  @classmethod
26
36
  def compute_info(cls, val):
27
- from metaflow.plugins.datastores.local_storage import LocalStorage
37
+ storage_class = cls._get_storage_class()
28
38
 
29
- v = os.path.realpath(os.path.join(val, DATASTORE_LOCAL_DIR))
39
+ v = os.path.realpath(os.path.join(val, cls.DATASTORE_DIR))
30
40
  if os.path.isdir(v):
31
- LocalStorage.datastore_root = v
41
+ storage_class.datastore_root = v
32
42
  return val
33
43
  raise ValueError(
34
- "Could not find directory %s in directory %s" % (DATASTORE_LOCAL_DIR, val)
44
+ "Could not find directory %s in directory %s" % (cls.DATASTORE_DIR, val)
35
45
  )
36
46
 
37
47
  @classmethod
38
48
  def default_info(cls):
39
- from metaflow.plugins.datastores.local_storage import LocalStorage
49
+ storage_class = cls._get_storage_class()
40
50
 
41
51
  def print_clean(line, **kwargs):
42
52
  print(line)
43
53
 
44
- v = LocalStorage.get_datastore_root_from_config(
54
+ v = storage_class.get_datastore_root_from_config(
45
55
  print_clean, create_on_absent=False
46
56
  )
47
57
  if v is None:
48
- return (
49
- "<No %s directory found in current working tree>" % DATASTORE_LOCAL_DIR
50
- )
58
+ return "<No %s directory found in current working tree>" % cls.DATASTORE_DIR
51
59
  return os.path.dirname(v)
52
60
 
53
61
  def version(self):
@@ -100,7 +108,7 @@ class LocalMetadataProvider(MetadataProvider):
100
108
  def register_data_artifacts(
101
109
  self, run_id, step_name, task_id, attempt_id, artifacts
102
110
  ):
103
- meta_dir = self._create_and_get_metadir(
111
+ meta_dir = self.__class__._create_and_get_metadir(
104
112
  self._flow_name, run_id, step_name, task_id
105
113
  )
106
114
  artlist = self._artifacts_to_json(
@@ -110,7 +118,7 @@ class LocalMetadataProvider(MetadataProvider):
110
118
  self._save_meta(meta_dir, artdict)
111
119
 
112
120
  def register_metadata(self, run_id, step_name, task_id, metadata):
113
- meta_dir = self._create_and_get_metadir(
121
+ meta_dir = self.__class__._create_and_get_metadir(
114
122
  self._flow_name, run_id, step_name, task_id
115
123
  )
116
124
  metalist = self._metadata_to_json(run_id, step_name, task_id, metadata)
@@ -130,9 +138,7 @@ class LocalMetadataProvider(MetadataProvider):
130
138
 
131
139
  def _optimistically_mutate():
132
140
  # get existing tags
133
- run = LocalMetadataProvider.get_object(
134
- "run", "self", {}, None, flow_id, run_id
135
- )
141
+ run = cls.get_object("run", "self", {}, None, flow_id, run_id)
136
142
  if not run:
137
143
  raise MetaflowTaggingError(
138
144
  msg="Run not found (%s, %s)" % (flow_id, run_id)
@@ -165,15 +171,13 @@ class LocalMetadataProvider(MetadataProvider):
165
171
  validate_tags(next_user_tags_set, existing_tags=existing_user_tag_set)
166
172
 
167
173
  # write new tag set to file system
168
- LocalMetadataProvider._persist_tags_for_run(
174
+ cls._persist_tags_for_run(
169
175
  flow_id, run_id, next_user_tags_set, existing_system_tag_set
170
176
  )
171
177
 
172
178
  # read tags back from file system to see if our optimism is misplaced
173
179
  # I.e. did a concurrent mutate overwrite our change
174
- run = LocalMetadataProvider.get_object(
175
- "run", "self", {}, None, flow_id, run_id
176
- )
180
+ run = cls.get_object("run", "self", {}, None, flow_id, run_id)
177
181
  if not run:
178
182
  raise MetaflowTaggingError(
179
183
  msg="Run not found for read-back check (%s, %s)" % (flow_id, run_id)
@@ -202,6 +206,70 @@ class LocalMetadataProvider(MetadataProvider):
202
206
  "Tagging failed due to too many conflicting updates from other processes"
203
207
  )
204
208
 
209
+ @classmethod
210
+ def filter_tasks_by_metadata(
211
+ cls,
212
+ flow_name: str,
213
+ run_id: str,
214
+ step_name: str,
215
+ field_name: str,
216
+ pattern: str,
217
+ ) -> List[str]:
218
+ """
219
+ Filter tasks by metadata field and pattern, returning task pathspecs that match criteria.
220
+
221
+ Parameters
222
+ ----------
223
+ flow_name : str
224
+ Identifier for the flow
225
+ run_id : str
226
+ Identifier for the run
227
+ step_name : str
228
+ Name of the step to query tasks from
229
+ field_name : str
230
+ Name of metadata field to query
231
+ pattern : str
232
+ Pattern to match in metadata field value
233
+
234
+ Returns
235
+ -------
236
+ List[str]
237
+ List of task pathspecs that match the query criteria
238
+ """
239
+ tasks = cls.get_object("step", "task", {}, None, flow_name, run_id, step_name)
240
+ if not tasks:
241
+ return []
242
+
243
+ regex = re.compile(pattern)
244
+ matching_task_pathspecs = []
245
+
246
+ for task in tasks:
247
+ task_id = task.get("task_id")
248
+ if not task_id:
249
+ continue
250
+
251
+ if pattern == ".*":
252
+ # If the pattern is ".*", we can match all tasks without reading metadata
253
+ matching_task_pathspecs.append(
254
+ f"{flow_name}/{run_id}/{step_name}/{task_id}"
255
+ )
256
+ continue
257
+
258
+ metadata = cls.get_object(
259
+ "task", "metadata", {}, None, flow_name, run_id, step_name, task_id
260
+ )
261
+
262
+ if any(
263
+ meta.get("field_name") == field_name
264
+ and regex.match(meta.get("value", ""))
265
+ for meta in metadata
266
+ ):
267
+ matching_task_pathspecs.append(
268
+ f"{flow_name}/{run_id}/{step_name}/{task_id}"
269
+ )
270
+
271
+ return matching_task_pathspecs
272
+
205
273
  @classmethod
206
274
  def _get_object_internal(
207
275
  cls, obj_type, obj_order, sub_type, sub_order, filters, attempt, *args
@@ -213,8 +281,6 @@ class LocalMetadataProvider(MetadataProvider):
213
281
  if obj_type not in ("root", "flow", "run", "step", "task", "artifact"):
214
282
  raise MetaflowInternalError(msg="Unexpected object type %s" % obj_type)
215
283
 
216
- from metaflow.plugins.datastores.local_storage import LocalStorage
217
-
218
284
  if obj_type == "artifact":
219
285
  # Artifacts are actually part of the tasks in the filesystem
220
286
  # E.g. we get here for (obj_type, sub_type) == (artifact, self)
@@ -241,13 +307,13 @@ class LocalMetadataProvider(MetadataProvider):
241
307
 
242
308
  # Special handling of self, artifact, and metadata
243
309
  if sub_type == "self":
244
- meta_path = LocalMetadataProvider._get_metadir(*args[:obj_order])
310
+ meta_path = cls._get_metadir(*args[:obj_order])
245
311
  if meta_path is None:
246
312
  return None
247
313
  self_file = os.path.join(meta_path, "_self.json")
248
314
  if os.path.isfile(self_file):
249
315
  obj = MetadataProvider._apply_filter(
250
- [LocalMetadataProvider._read_json_file(self_file)], filters
316
+ [cls._read_json_file(self_file)], filters
251
317
  )[0]
252
318
  # For non-descendants of a run, we are done
253
319
 
@@ -258,7 +324,7 @@ class LocalMetadataProvider(MetadataProvider):
258
324
  raise MetaflowInternalError(
259
325
  msg="Unexpected object type %s" % obj_type
260
326
  )
261
- run = LocalMetadataProvider.get_object(
327
+ run = cls.get_object(
262
328
  "run", "self", {}, None, *args[:RUN_ORDER] # *[flow_id, run_id]
263
329
  )
264
330
  if not run:
@@ -275,7 +341,7 @@ class LocalMetadataProvider(MetadataProvider):
275
341
  if obj_type not in ("root", "flow", "run", "step", "task"):
276
342
  raise MetaflowInternalError(msg="Unexpected object type %s" % obj_type)
277
343
 
278
- meta_path = LocalMetadataProvider._get_metadir(*args[:obj_order])
344
+ meta_path = cls._get_metadir(*args[:obj_order])
279
345
  result = []
280
346
  if meta_path is None:
281
347
  return result
@@ -286,9 +352,7 @@ class LocalMetadataProvider(MetadataProvider):
286
352
  attempts_done = sorted(glob.iglob(attempt_done_files))
287
353
  if attempts_done:
288
354
  successful_attempt = int(
289
- LocalMetadataProvider._read_json_file(attempts_done[-1])[
290
- "value"
291
- ]
355
+ cls._read_json_file(attempts_done[-1])["value"]
292
356
  )
293
357
  if successful_attempt is not None:
294
358
  which_artifact = "*"
@@ -299,10 +363,10 @@ class LocalMetadataProvider(MetadataProvider):
299
363
  "%d_artifact_%s.json" % (successful_attempt, which_artifact),
300
364
  )
301
365
  for obj in glob.iglob(artifact_files):
302
- result.append(LocalMetadataProvider._read_json_file(obj))
366
+ result.append(cls._read_json_file(obj))
303
367
 
304
368
  # We are getting artifacts. We should overlay with ancestral run's tags
305
- run = LocalMetadataProvider.get_object(
369
+ run = cls.get_object(
306
370
  "run", "self", {}, None, *args[:RUN_ORDER] # *[flow_id, run_id]
307
371
  )
308
372
  if not run:
@@ -322,12 +386,12 @@ class LocalMetadataProvider(MetadataProvider):
322
386
  if obj_type not in ("root", "flow", "run", "step", "task"):
323
387
  raise MetaflowInternalError(msg="Unexpected object type %s" % obj_type)
324
388
  result = []
325
- meta_path = LocalMetadataProvider._get_metadir(*args[:obj_order])
389
+ meta_path = cls._get_metadir(*args[:obj_order])
326
390
  if meta_path is None:
327
391
  return result
328
392
  files = os.path.join(meta_path, "sysmeta_*")
329
393
  for obj in glob.iglob(files):
330
- result.append(LocalMetadataProvider._read_json_file(obj))
394
+ result.append(cls._read_json_file(obj))
331
395
  return result
332
396
 
333
397
  # For the other types, we locate all the objects we need to find and return them
@@ -335,14 +399,13 @@ class LocalMetadataProvider(MetadataProvider):
335
399
  raise MetaflowInternalError(msg="Unexpected object type %s" % obj_type)
336
400
  if sub_type not in ("flow", "run", "step", "task"):
337
401
  raise MetaflowInternalError(msg="unexpected sub type %s" % sub_type)
338
- obj_path = LocalMetadataProvider._make_path(
339
- *args[:obj_order], create_on_absent=False
340
- )
402
+ obj_path = cls._make_path(*args[:obj_order], create_on_absent=False)
341
403
  result = []
342
404
  if obj_path is None:
343
405
  return result
344
406
  skip_dirs = "*/" * (sub_order - obj_order)
345
- all_meta = os.path.join(obj_path, skip_dirs, LocalStorage.METADATA_DIR)
407
+ storage_class = cls._get_storage_class()
408
+ all_meta = os.path.join(obj_path, skip_dirs, storage_class.METADATA_DIR)
346
409
  SelfInfo = collections.namedtuple("SelfInfo", ["filepath", "run_id"])
347
410
  self_infos = []
348
411
  for meta_path in glob.iglob(all_meta):
@@ -352,9 +415,7 @@ class LocalMetadataProvider(MetadataProvider):
352
415
  run_id = None
353
416
  # flow and run do not need info from ancestral run
354
417
  if sub_type in ("step", "task"):
355
- run_id = LocalMetadataProvider._deduce_run_id_from_meta_dir(
356
- meta_path, sub_type
357
- )
418
+ run_id = cls._deduce_run_id_from_meta_dir(meta_path, sub_type)
358
419
  # obj_type IS run, or more granular than run, let's do sanity check vs args
359
420
  if obj_order >= RUN_ORDER:
360
421
  if run_id != args[RUN_ORDER - 1]:
@@ -364,10 +425,10 @@ class LocalMetadataProvider(MetadataProvider):
364
425
  self_infos.append(SelfInfo(filepath=self_file, run_id=run_id))
365
426
 
366
427
  for self_info in self_infos:
367
- obj = LocalMetadataProvider._read_json_file(self_info.filepath)
428
+ obj = cls._read_json_file(self_info.filepath)
368
429
  if self_info.run_id:
369
430
  flow_id_from_args = args[0]
370
- run = LocalMetadataProvider.get_object(
431
+ run = cls.get_object(
371
432
  "run",
372
433
  "self",
373
434
  {},
@@ -386,8 +447,8 @@ class LocalMetadataProvider(MetadataProvider):
386
447
 
387
448
  return MetadataProvider._apply_filter(result, filters)
388
449
 
389
- @staticmethod
390
- def _deduce_run_id_from_meta_dir(meta_dir_path, sub_type):
450
+ @classmethod
451
+ def _deduce_run_id_from_meta_dir(cls, meta_dir_path, sub_type):
391
452
  curr_order = ObjectOrder.type_to_order(sub_type)
392
453
  levels_to_ascend = curr_order - ObjectOrder.type_to_order("run")
393
454
  if levels_to_ascend < 0:
@@ -402,8 +463,8 @@ class LocalMetadataProvider(MetadataProvider):
402
463
  )
403
464
  return run_id
404
465
 
405
- @staticmethod
406
- def _makedirs(path):
466
+ @classmethod
467
+ def _makedirs(cls, path):
407
468
  # this is for python2 compatibility.
408
469
  # Python3 has os.makedirs(exist_ok=True).
409
470
  try:
@@ -415,17 +476,15 @@ class LocalMetadataProvider(MetadataProvider):
415
476
  else:
416
477
  raise
417
478
 
418
- @staticmethod
419
- def _persist_tags_for_run(flow_id, run_id, tags, system_tags):
420
- subpath = LocalMetadataProvider._create_and_get_metadir(
421
- flow_name=flow_id, run_id=run_id
422
- )
479
+ @classmethod
480
+ def _persist_tags_for_run(cls, flow_id, run_id, tags, system_tags):
481
+ subpath = cls._create_and_get_metadir(flow_name=flow_id, run_id=run_id)
423
482
  selfname = os.path.join(subpath, "_self.json")
424
483
  if not os.path.isfile(selfname):
425
484
  raise MetaflowInternalError(
426
485
  msg="Could not verify Run existence on disk - missing %s" % selfname
427
486
  )
428
- LocalMetadataProvider._save_meta(
487
+ cls._save_meta(
429
488
  subpath,
430
489
  {
431
490
  "_self": MetadataProvider._run_to_json_static(
@@ -442,11 +501,11 @@ class LocalMetadataProvider(MetadataProvider):
442
501
  tags = set()
443
502
  if sys_tags is None:
444
503
  sys_tags = set()
445
- subpath = self._create_and_get_metadir(
504
+ subpath = self.__class__._create_and_get_metadir(
446
505
  self._flow_name, run_id, step_name, task_id
447
506
  )
448
507
  selfname = os.path.join(subpath, "_self.json")
449
- self._makedirs(subpath)
508
+ self.__class__._makedirs(subpath)
450
509
  if os.path.isfile(selfname):
451
510
  # There is a race here, but we are not aiming to make this as solid as
452
511
  # the metadata service. This is used primarily for concurrent resumes,
@@ -483,26 +542,31 @@ class LocalMetadataProvider(MetadataProvider):
483
542
  self._register_system_metadata(run_id, step_name, task_id, attempt)
484
543
  return to_return
485
544
 
486
- @staticmethod
545
+ @classmethod
487
546
  def _make_path(
488
- flow_name=None, run_id=None, step_name=None, task_id=None, create_on_absent=True
547
+ cls,
548
+ flow_name=None,
549
+ run_id=None,
550
+ step_name=None,
551
+ task_id=None,
552
+ create_on_absent=True,
489
553
  ):
490
554
 
491
- from metaflow.plugins.datastores.local_storage import LocalStorage
555
+ storage_class = cls._get_storage_class()
492
556
 
493
- if LocalStorage.datastore_root is None:
557
+ if storage_class.datastore_root is None:
494
558
 
495
559
  def print_clean(line, **kwargs):
496
560
  print(line)
497
561
 
498
- LocalStorage.datastore_root = LocalStorage.get_datastore_root_from_config(
562
+ storage_class.datastore_root = storage_class.get_datastore_root_from_config(
499
563
  print_clean, create_on_absent=create_on_absent
500
564
  )
501
- if LocalStorage.datastore_root is None:
565
+ if storage_class.datastore_root is None:
502
566
  return None
503
567
 
504
568
  if flow_name is None:
505
- return LocalStorage.datastore_root
569
+ return storage_class.datastore_root
506
570
  components = []
507
571
  if flow_name:
508
572
  components.append(flow_name)
@@ -512,37 +576,35 @@ class LocalMetadataProvider(MetadataProvider):
512
576
  components.append(step_name)
513
577
  if task_id:
514
578
  components.append(task_id)
515
- return LocalStorage().full_uri(LocalStorage.path_join(*components))
579
+ return storage_class().full_uri(storage_class.path_join(*components))
516
580
 
517
- @staticmethod
581
+ @classmethod
518
582
  def _create_and_get_metadir(
519
- flow_name=None, run_id=None, step_name=None, task_id=None
583
+ cls, flow_name=None, run_id=None, step_name=None, task_id=None
520
584
  ):
521
- from metaflow.plugins.datastores.local_storage import LocalStorage
585
+ storage_class = cls._get_storage_class()
522
586
 
523
- root_path = LocalMetadataProvider._make_path(
524
- flow_name, run_id, step_name, task_id
525
- )
526
- subpath = os.path.join(root_path, LocalStorage.METADATA_DIR)
527
- LocalMetadataProvider._makedirs(subpath)
587
+ root_path = cls._make_path(flow_name, run_id, step_name, task_id)
588
+ subpath = os.path.join(root_path, storage_class.METADATA_DIR)
589
+ cls._makedirs(subpath)
528
590
  return subpath
529
591
 
530
- @staticmethod
531
- def _get_metadir(flow_name=None, run_id=None, step_name=None, task_id=None):
532
- from metaflow.plugins.datastores.local_storage import LocalStorage
592
+ @classmethod
593
+ def _get_metadir(cls, flow_name=None, run_id=None, step_name=None, task_id=None):
594
+ storage_class = cls._get_storage_class()
533
595
 
534
- root_path = LocalMetadataProvider._make_path(
596
+ root_path = cls._make_path(
535
597
  flow_name, run_id, step_name, task_id, create_on_absent=False
536
598
  )
537
599
  if root_path is None:
538
600
  return None
539
- subpath = os.path.join(root_path, LocalStorage.METADATA_DIR)
601
+ subpath = os.path.join(root_path, storage_class.METADATA_DIR)
540
602
  if os.path.isdir(subpath):
541
603
  return subpath
542
604
  return None
543
605
 
544
- @staticmethod
545
- def _dump_json_to_file(filepath, data, allow_overwrite=False):
606
+ @classmethod
607
+ def _dump_json_to_file(cls, filepath, data, allow_overwrite=False):
546
608
  if os.path.isfile(filepath) and not allow_overwrite:
547
609
  return
548
610
  try:
@@ -556,15 +618,13 @@ class LocalMetadataProvider(MetadataProvider):
556
618
  if f and os.path.isfile(f.name):
557
619
  os.remove(f.name)
558
620
 
559
- @staticmethod
560
- def _read_json_file(filepath):
621
+ @classmethod
622
+ def _read_json_file(cls, filepath):
561
623
  with open(filepath, "r") as f:
562
624
  return json.load(f)
563
625
 
564
- @staticmethod
565
- def _save_meta(root_dir, metadict, allow_overwrite=False):
626
+ @classmethod
627
+ def _save_meta(cls, root_dir, metadict, allow_overwrite=False):
566
628
  for name, datum in metadict.items():
567
629
  filename = os.path.join(root_dir, "%s.json" % name)
568
- LocalMetadataProvider._dump_json_to_file(
569
- filename, datum, allow_overwrite=allow_overwrite
570
- )
630
+ cls._dump_json_to_file(filename, datum, allow_overwrite=allow_overwrite)
@@ -1,23 +1,20 @@
1
1
  import os
2
2
  import random
3
+ import time
3
4
 
4
5
  import requests
5
- import time
6
6
 
7
+ from typing import List
7
8
  from metaflow.exception import (
8
9
  MetaflowException,
9
- MetaflowTaggingError,
10
10
  MetaflowInternalError,
11
+ MetaflowTaggingError,
11
12
  )
12
- from metaflow.metaflow_config import (
13
- SERVICE_RETRY_COUNT,
14
- SERVICE_HEADERS,
15
- SERVICE_URL,
16
- )
17
- from metaflow.metadata import MetadataProvider
18
- from metaflow.metadata.heartbeat import HB_URL_KEY
13
+ from metaflow.metadata_provider import MetadataProvider
14
+ from metaflow.metadata_provider.heartbeat import HB_URL_KEY
15
+ from metaflow.metaflow_config import SERVICE_HEADERS, SERVICE_RETRY_COUNT, SERVICE_URL
19
16
  from metaflow.sidecar import Message, MessageTypes, Sidecar
20
-
17
+ from urllib.parse import urlencode
21
18
  from metaflow.util import version_parse
22
19
 
23
20
 
@@ -39,6 +36,23 @@ class ServiceException(MetaflowException):
39
36
  class ServiceMetadataProvider(MetadataProvider):
40
37
  TYPE = "service"
41
38
 
39
+ _session = requests.Session()
40
+ _session.mount(
41
+ "http://",
42
+ requests.adapters.HTTPAdapter(
43
+ pool_connections=20,
44
+ pool_maxsize=20,
45
+ max_retries=0, # Handle retries explicitly
46
+ pool_block=False,
47
+ ),
48
+ )
49
+ _session.mount(
50
+ "https://",
51
+ requests.adapters.HTTPAdapter(
52
+ pool_connections=20, pool_maxsize=20, max_retries=0, pool_block=False
53
+ ),
54
+ )
55
+
42
56
  _supports_attempt_gets = None
43
57
  _supports_tag_mutation = None
44
58
 
@@ -58,12 +72,18 @@ class ServiceMetadataProvider(MetadataProvider):
58
72
  @classmethod
59
73
  def compute_info(cls, val):
60
74
  v = val.rstrip("/")
61
- try:
62
- resp = requests.get(os.path.join(v, "ping"), headers=SERVICE_HEADERS.copy())
63
- resp.raise_for_status()
64
- except: # noqa E722
65
- raise ValueError("Metaflow service [%s] unreachable." % v)
66
- return v
75
+ for i in range(SERVICE_RETRY_COUNT):
76
+ try:
77
+ resp = cls._session.get(
78
+ os.path.join(v, "ping"), headers=SERVICE_HEADERS.copy()
79
+ )
80
+ resp.raise_for_status()
81
+ except: # noqa E722
82
+ time.sleep(2 ** (i - 1))
83
+ else:
84
+ return v
85
+
86
+ raise ValueError("Metaflow service [%s] unreachable." % v)
67
87
 
68
88
  @classmethod
69
89
  def default_info(cls):
@@ -304,6 +324,64 @@ class ServiceMetadataProvider(MetadataProvider):
304
324
  self._register_system_metadata(run_id, step_name, task["task_id"], attempt)
305
325
  return task["task_id"], did_create
306
326
 
327
+ @classmethod
328
+ def filter_tasks_by_metadata(
329
+ cls,
330
+ flow_name: str,
331
+ run_id: str,
332
+ step_name: str,
333
+ field_name: str,
334
+ pattern: str,
335
+ ) -> List[str]:
336
+ """
337
+ Filter tasks by metadata field and pattern, returning task pathspecs that match criteria.
338
+
339
+ Parameters
340
+ ----------
341
+ flow_name : str
342
+ Flow name, that the run belongs to.
343
+ run_id: str
344
+ Run id, together with flow_id, that identifies the specific Run whose tasks to query
345
+ step_name: str
346
+ Step name to query tasks from
347
+ field_name: str
348
+ Metadata field name to query
349
+ pattern: str
350
+ Pattern to match in metadata field value
351
+
352
+ Returns
353
+ -------
354
+ List[str]
355
+ List of task pathspecs that satisfy the query
356
+ """
357
+ query_params = {}
358
+
359
+ if pattern == ".*":
360
+ # we do not need to filter tasks at all if pattern allows 'any'
361
+ query_params = {}
362
+ else:
363
+ if field_name:
364
+ query_params["metadata_field_name"] = field_name
365
+ if pattern:
366
+ query_params["pattern"] = pattern
367
+
368
+ url = ServiceMetadataProvider._obj_path(flow_name, run_id, step_name)
369
+ url = f"{url}/filtered_tasks?{urlencode(query_params)}"
370
+
371
+ try:
372
+ resp, _ = cls._request(None, url, "GET")
373
+ except Exception as e:
374
+ if e.http_code == 404:
375
+ # filter_tasks_by_metadata endpoint does not exist in the version of metadata service
376
+ # deployed currently. Raise a more informative error message.
377
+ raise MetaflowInternalError(
378
+ "The version of metadata service deployed currently does not support filtering tasks by metadata. "
379
+ "Upgrade Metadata service to version 2.5.0 or greater to use this feature."
380
+ ) from e
381
+ # Other unknown exception
382
+ raise e
383
+ return resp
384
+
307
385
  @staticmethod
308
386
  def _obj_path(
309
387
  flow_name,
@@ -412,27 +490,27 @@ class ServiceMetadataProvider(MetadataProvider):
412
490
  if method == "GET":
413
491
  if monitor:
414
492
  with monitor.measure("metaflow.service_metadata.get"):
415
- resp = requests.get(url, headers=SERVICE_HEADERS.copy())
493
+ resp = cls._session.get(url, headers=SERVICE_HEADERS.copy())
416
494
  else:
417
- resp = requests.get(url, headers=SERVICE_HEADERS.copy())
495
+ resp = cls._session.get(url, headers=SERVICE_HEADERS.copy())
418
496
  elif method == "POST":
419
497
  if monitor:
420
498
  with monitor.measure("metaflow.service_metadata.post"):
421
- resp = requests.post(
499
+ resp = cls._session.post(
422
500
  url, headers=SERVICE_HEADERS.copy(), json=data
423
501
  )
424
502
  else:
425
- resp = requests.post(
503
+ resp = cls._session.post(
426
504
  url, headers=SERVICE_HEADERS.copy(), json=data
427
505
  )
428
506
  elif method == "PATCH":
429
507
  if monitor:
430
508
  with monitor.measure("metaflow.service_metadata.patch"):
431
- resp = requests.patch(
509
+ resp = cls._session.patch(
432
510
  url, headers=SERVICE_HEADERS.copy(), json=data
433
511
  )
434
512
  else:
435
- resp = requests.patch(
513
+ resp = cls._session.patch(
436
514
  url, headers=SERVICE_HEADERS.copy(), json=data
437
515
  )
438
516
  else:
@@ -475,7 +553,6 @@ class ServiceMetadataProvider(MetadataProvider):
475
553
  resp.text,
476
554
  )
477
555
  time.sleep(2**i)
478
-
479
556
  if resp:
480
557
  raise ServiceException(
481
558
  "Metadata request (%s) failed (code %s): %s"
@@ -499,9 +576,9 @@ class ServiceMetadataProvider(MetadataProvider):
499
576
  try:
500
577
  if monitor:
501
578
  with monitor.measure("metaflow.service_metadata.get"):
502
- resp = requests.get(url, headers=SERVICE_HEADERS.copy())
579
+ resp = cls._session.get(url, headers=SERVICE_HEADERS.copy())
503
580
  else:
504
- resp = requests.get(url, headers=SERVICE_HEADERS.copy())
581
+ resp = cls._session.get(url, headers=SERVICE_HEADERS.copy())
505
582
  except:
506
583
  if monitor:
507
584
  with monitor.count("metaflow.service_metadata.failed_request"):
@@ -514,7 +591,7 @@ class ServiceMetadataProvider(MetadataProvider):
514
591
  else:
515
592
  if resp.status_code < 300:
516
593
  return resp.headers.get("METADATA_SERVICE_VERSION", None)
517
- elif resp.status_code != 503:
594
+ elif resp.status_code not in (503, 500):
518
595
  raise ServiceException(
519
596
  "Metadata request (%s) failed"
520
597
  " (code %s): %s" % (url, resp.status_code, resp.text),