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
@@ -18,6 +18,7 @@ from metaflow.metaflow_config import (
18
18
  SFN_S3_DISTRIBUTED_MAP_OUTPUT_PATH,
19
19
  )
20
20
  from metaflow.parameters import deploy_time_eval
21
+ from metaflow.user_configs.config_options import ConfigInput
21
22
  from metaflow.util import dict_to_cli_options, to_pascalcase
22
23
 
23
24
  from ..batch.batch import Batch
@@ -39,6 +40,7 @@ class StepFunctions(object):
39
40
  name,
40
41
  graph,
41
42
  flow,
43
+ code_package_metadata,
42
44
  code_package_sha,
43
45
  code_package_url,
44
46
  production_token,
@@ -48,16 +50,19 @@ class StepFunctions(object):
48
50
  event_logger,
49
51
  monitor,
50
52
  tags=None,
53
+ aws_batch_tags=None,
51
54
  namespace=None,
52
55
  username=None,
53
56
  max_workers=None,
54
57
  workflow_timeout=None,
55
58
  is_project=False,
56
59
  use_distributed_map=False,
60
+ compress_state_machine=False,
57
61
  ):
58
62
  self.name = name
59
63
  self.graph = graph
60
64
  self.flow = flow
65
+ self.code_package_metadata = code_package_metadata
61
66
  self.code_package_sha = code_package_sha
62
67
  self.code_package_url = code_package_url
63
68
  self.production_token = production_token
@@ -67,14 +72,19 @@ class StepFunctions(object):
67
72
  self.event_logger = event_logger
68
73
  self.monitor = monitor
69
74
  self.tags = tags
75
+ self.aws_batch_tags = aws_batch_tags or {}
70
76
  self.namespace = namespace
71
77
  self.username = username
72
78
  self.max_workers = max_workers
73
79
  self.workflow_timeout = workflow_timeout
80
+ self.config_parameters = self._process_config_parameters()
74
81
 
75
82
  # https://aws.amazon.com/blogs/aws/step-functions-distributed-map-a-serverless-solution-for-large-scale-parallel-data-processing/
76
83
  self.use_distributed_map = use_distributed_map
77
84
 
85
+ # S3 command upload configuration
86
+ self.compress_state_machine = compress_state_machine
87
+
78
88
  self._client = StepFunctionsClient()
79
89
  self._workflow = self._compile()
80
90
  self._cron = self._cron()
@@ -190,6 +200,7 @@ class StepFunctions(object):
190
200
  "on AWS Step Functions. Please "
191
201
  "deploy your flow first." % name
192
202
  )
203
+
193
204
  # Dump parameters into `Parameters` input field.
194
205
  input = json.dumps({"Parameters": json.dumps(parameters)})
195
206
  # AWS Step Functions limits input to be 32KiB, but AWS Batch
@@ -234,7 +245,7 @@ class StepFunctions(object):
234
245
  return parameters.get("metaflow.owner"), parameters.get(
235
246
  "metaflow.production_token"
236
247
  )
237
- except KeyError as e:
248
+ except KeyError:
238
249
  raise StepFunctionsException(
239
250
  "An existing non-metaflow "
240
251
  "workflow with the same name as "
@@ -299,6 +310,12 @@ class StepFunctions(object):
299
310
  "to AWS Step Functions is not supported currently."
300
311
  )
301
312
 
313
+ if self.flow._flow_decorators.get("exit_hook"):
314
+ raise StepFunctionsException(
315
+ "Deploying flows with the @exit_hook decorator "
316
+ "to AWS Step Functions is not currently supported."
317
+ )
318
+
302
319
  # Visit every node of the flow and recursively build the state machine.
303
320
  def _visit(node, workflow, exit_node=None):
304
321
  if node.parallel_foreach:
@@ -307,6 +324,12 @@ class StepFunctions(object):
307
324
  "to AWS Step Functions is not supported currently."
308
325
  )
309
326
 
327
+ if node.type == "split-switch":
328
+ raise StepFunctionsException(
329
+ "Deploying flows with switch statement "
330
+ "to AWS Step Functions is not supported currently."
331
+ )
332
+
310
333
  # Assign an AWS Batch job to the AWS Step Functions state
311
334
  # and pass the intermediate state by exposing `JobId` and
312
335
  # `Parameters` to the child job(s) as outputs. `Index` and
@@ -485,6 +508,10 @@ class StepFunctions(object):
485
508
  "case-insensitive." % param.name
486
509
  )
487
510
  seen.add(norm)
511
+ # NOTE: We skip config parameters as these do not have dynamic values,
512
+ # and need to be treated differently.
513
+ if param.IS_CONFIG_PARAMETER:
514
+ continue
488
515
 
489
516
  is_required = param.kwargs.get("required", False)
490
517
  # Throw an exception if a schedule is set for a flow with required
@@ -501,6 +528,27 @@ class StepFunctions(object):
501
528
  parameters.append(dict(name=param.name, value=value))
502
529
  return parameters
503
530
 
531
+ def _process_config_parameters(self):
532
+ parameters = []
533
+ seen = set()
534
+ for var, param in self.flow._get_parameters():
535
+ if not param.IS_CONFIG_PARAMETER:
536
+ continue
537
+ # Throw an exception if the parameter is specified twice.
538
+ norm = param.name.lower()
539
+ if norm in seen:
540
+ raise MetaflowException(
541
+ "Parameter *%s* is specified twice. "
542
+ "Note that parameter names are "
543
+ "case-insensitive." % param.name
544
+ )
545
+ seen.add(norm)
546
+
547
+ parameters.append(
548
+ dict(name=param.name, kv_name=ConfigInput.make_key_name(param.name))
549
+ )
550
+ return parameters
551
+
504
552
  def _batch(self, node):
505
553
  attrs = {
506
554
  # metaflow.user is only used for setting the AWS Job Name.
@@ -664,9 +712,9 @@ class StepFunctions(object):
664
712
  # input to those descendent tasks. We set and propagate the
665
713
  # task ids pointing to split_parents through every state.
666
714
  if any(self.graph[n].type == "foreach" for n in node.in_funcs):
667
- attrs[
668
- "split_parent_task_id_%s.$" % node.split_parents[-1]
669
- ] = "$.SplitParentTaskId"
715
+ attrs["split_parent_task_id_%s.$" % node.split_parents[-1]] = (
716
+ "$.SplitParentTaskId"
717
+ )
670
718
  for parent in node.split_parents[:-1]:
671
719
  if self.graph[parent].type == "foreach":
672
720
  attrs["split_parent_task_id_%s.$" % parent] = (
@@ -747,6 +795,11 @@ class StepFunctions(object):
747
795
  metaflow_version["production_token"] = self.production_token
748
796
  env["METAFLOW_VERSION"] = json.dumps(metaflow_version)
749
797
 
798
+ # map config values
799
+ cfg_env = {param["name"]: param["kv_name"] for param in self.config_parameters}
800
+ if cfg_env:
801
+ env["METAFLOW_FLOW_CONFIG_VALUE"] = json.dumps(cfg_env)
802
+
750
803
  # Set AWS DynamoDb Table Name for state tracking for for-eaches.
751
804
  # There are three instances when metaflow runtime directly interacts
752
805
  # with AWS DynamoDB.
@@ -806,15 +859,17 @@ class StepFunctions(object):
806
859
  # AWS_BATCH_JOB_ATTEMPT as the job counter.
807
860
  "retry_count": "$((AWS_BATCH_JOB_ATTEMPT-1))",
808
861
  }
809
-
862
+ # merge batch tags supplied through step-fuctions CLI and ones defined in decorator
863
+ batch_tags = {**self.aws_batch_tags, **resources["aws_batch_tags"]}
810
864
  return (
811
- Batch(self.metadata, self.environment)
865
+ Batch(self.metadata, self.environment, self.flow_datastore)
812
866
  .create_job(
813
867
  step_name=node.name,
814
868
  step_cli=self._step_cli(
815
869
  node, input_paths, self.code_package_url, user_code_retries
816
870
  ),
817
871
  task_spec=task_spec,
872
+ code_package_metadata=self.code_package_metadata,
818
873
  code_package_sha=self.code_package_sha,
819
874
  code_package_url=self.code_package_url,
820
875
  code_package_ds=self.flow_datastore.TYPE,
@@ -831,6 +886,7 @@ class StepFunctions(object):
831
886
  swappiness=resources["swappiness"],
832
887
  efa=resources["efa"],
833
888
  use_tmpfs=resources["use_tmpfs"],
889
+ aws_batch_tags=batch_tags,
834
890
  tmpfs_tempdir=resources["tmpfs_tempdir"],
835
891
  tmpfs_size=resources["tmpfs_size"],
836
892
  tmpfs_path=resources["tmpfs_path"],
@@ -842,6 +898,7 @@ class StepFunctions(object):
842
898
  ephemeral_storage=resources["ephemeral_storage"],
843
899
  log_driver=resources["log_driver"],
844
900
  log_options=resources["log_options"],
901
+ offload_command_to_s3=self.compress_state_machine,
845
902
  )
846
903
  .attempts(total_retries + 1)
847
904
  )
@@ -875,13 +932,13 @@ class StepFunctions(object):
875
932
  "with": [
876
933
  decorator.make_decorator_spec()
877
934
  for decorator in node.decorators
878
- if not decorator.statically_defined
935
+ if not decorator.statically_defined and decorator.inserted_by is None
879
936
  ]
880
937
  }
881
938
  # FlowDecorators can define their own top-level options. They are
882
939
  # responsible for adding their own top-level options and values through
883
940
  # the get_top_level_options() hook. See similar logic in runtime.py.
884
- for deco in flow_decorators():
941
+ for deco in flow_decorators(self.flow):
885
942
  top_opts_dict.update(deco.get_top_level_options())
886
943
 
887
944
  top_opts = list(dict_to_cli_options(top_opts_dict))
@@ -7,8 +7,10 @@ from metaflow import JSONType, current, decorators, parameters
7
7
  from metaflow._vendor import click
8
8
  from metaflow.exception import MetaflowException, MetaflowInternalError
9
9
  from metaflow.metaflow_config import (
10
+ FEAT_ALWAYS_UPLOAD_CODE_PACKAGE,
10
11
  SERVICE_VERSION_CHECK,
11
12
  SFN_STATE_MACHINE_PREFIX,
13
+ SFN_COMPRESS_STATE_MACHINE,
12
14
  UI_URL,
13
15
  )
14
16
  from metaflow.package import MetaflowPackage
@@ -18,6 +20,8 @@ from metaflow.util import get_username, to_bytes, to_unicode, version_parse
18
20
 
19
21
  from .production_token import load_token, new_token, store_token
20
22
  from .step_functions import StepFunctions
23
+ from metaflow.tagging_util import validate_tags
24
+ from ..aws_utils import validate_aws_tag
21
25
 
22
26
  VALID_NAME = re.compile(r"[^a-zA-Z0-9_\-\.]")
23
27
 
@@ -96,6 +100,13 @@ def step_functions(obj, name=None):
96
100
  "with the given tag. You can specify this option multiple "
97
101
  "times to attach multiple tags.",
98
102
  )
103
+ @click.option(
104
+ "--aws-batch-tag",
105
+ "aws_batch_tags",
106
+ multiple=True,
107
+ default=None,
108
+ help="AWS Batch tags.",
109
+ )
99
110
  @click.option(
100
111
  "--namespace",
101
112
  "user_namespace",
@@ -130,10 +141,25 @@ def step_functions(obj, name=None):
130
141
  help="Use AWS Step Functions Distributed Map instead of Inline Map for "
131
142
  "defining foreach tasks in Amazon State Language.",
132
143
  )
144
+ @click.option(
145
+ "--compress-state-machine/--no-compress-state-machine",
146
+ is_flag=True,
147
+ default=SFN_COMPRESS_STATE_MACHINE,
148
+ help="Compress AWS Step Functions state machine to fit within the 8K limit.",
149
+ )
150
+ @click.option(
151
+ "--deployer-attribute-file",
152
+ default=None,
153
+ show_default=True,
154
+ type=str,
155
+ help="Write the workflow name to the file specified. Used internally for Metaflow's Deployer API.",
156
+ hidden=True,
157
+ )
133
158
  @click.pass_obj
134
159
  def create(
135
160
  obj,
136
161
  tags=None,
162
+ aws_batch_tags=None,
137
163
  user_namespace=None,
138
164
  only_json=False,
139
165
  authorize=None,
@@ -143,9 +169,29 @@ def create(
143
169
  workflow_timeout=None,
144
170
  log_execution_history=False,
145
171
  use_distributed_map=False,
172
+ compress_state_machine=False,
173
+ deployer_attribute_file=None,
146
174
  ):
175
+ for node in obj.graph:
176
+ if any([d.name == "slurm" for d in node.decorators]):
177
+ raise MetaflowException(
178
+ "Step *%s* is marked for execution on Slurm with AWS Step Functions which isn't currently supported."
179
+ % node.name
180
+ )
181
+
147
182
  validate_tags(tags)
148
183
 
184
+ if deployer_attribute_file:
185
+ with open(deployer_attribute_file, "w") as f:
186
+ json.dump(
187
+ {
188
+ "name": obj.state_machine_name,
189
+ "flow_name": obj.flow.name,
190
+ "metadata": obj.metadata.metadata_str(),
191
+ },
192
+ f,
193
+ )
194
+
149
195
  obj.echo(
150
196
  "Deploying *%s* to AWS Step Functions..." % obj.state_machine_name, bold=True
151
197
  )
@@ -168,11 +214,13 @@ def create(
168
214
  token,
169
215
  obj.state_machine_name,
170
216
  tags,
217
+ aws_batch_tags,
171
218
  user_namespace,
172
219
  max_workers,
173
220
  workflow_timeout,
174
221
  obj.is_project,
175
222
  use_distributed_map,
223
+ compress_state_machine,
176
224
  )
177
225
 
178
226
  if only_json:
@@ -231,8 +279,10 @@ def check_metadata_service_version(obj):
231
279
 
232
280
 
233
281
  def resolve_state_machine_name(obj, name):
234
- def attach_prefix(name):
235
- if SFN_STATE_MACHINE_PREFIX is not None:
282
+ def attach_prefix(name: str):
283
+ if SFN_STATE_MACHINE_PREFIX is not None and (
284
+ not name.startswith(SFN_STATE_MACHINE_PREFIX)
285
+ ):
236
286
  return SFN_STATE_MACHINE_PREFIX + "_" + name
237
287
  return name
238
288
 
@@ -285,32 +335,55 @@ def make_flow(
285
335
  token,
286
336
  name,
287
337
  tags,
338
+ aws_batch_tags,
288
339
  namespace,
289
340
  max_workers,
290
341
  workflow_timeout,
291
342
  is_project,
292
343
  use_distributed_map,
344
+ compress_state_machine=False,
293
345
  ):
294
346
  if obj.flow_datastore.TYPE != "s3":
295
347
  raise MetaflowException("AWS Step Functions requires --datastore=s3.")
296
348
 
297
349
  # Attach AWS Batch decorator to the flow
298
350
  decorators._attach_decorators(obj.flow, [BatchDecorator.name])
351
+ decorators._init(obj.flow)
299
352
  decorators._init_step_decorators(
300
353
  obj.flow, obj.graph, obj.environment, obj.flow_datastore, obj.logger
301
354
  )
355
+ obj.graph = obj.flow._graph
302
356
 
303
357
  obj.package = MetaflowPackage(
304
- obj.flow, obj.environment, obj.echo, obj.package_suffixes
358
+ obj.flow,
359
+ obj.environment,
360
+ obj.echo,
361
+ suffixes=obj.package_suffixes,
362
+ flow_datastore=obj.flow_datastore if FEAT_ALWAYS_UPLOAD_CODE_PACKAGE else None,
305
363
  )
306
- package_url, package_sha = obj.flow_datastore.save_data(
307
- [obj.package.blob], len_hint=1
308
- )[0]
364
+ # This blocks until the package is created
365
+ if FEAT_ALWAYS_UPLOAD_CODE_PACKAGE:
366
+ package_url = obj.package.package_url()
367
+ package_sha = obj.package.package_sha()
368
+ else:
369
+ package_url, package_sha = obj.flow_datastore.save_data(
370
+ [obj.package.blob], len_hint=1
371
+ )[0]
372
+
373
+ if aws_batch_tags is not None:
374
+ batch_tags = {}
375
+ for item in list(aws_batch_tags):
376
+ key, value = item.split("=")
377
+ # These are fresh AWS tags provided by the user through the CLI,
378
+ # so we must validate them.
379
+ validate_aws_tag(key, value)
380
+ batch_tags[key] = value
309
381
 
310
382
  return StepFunctions(
311
383
  name,
312
384
  obj.graph,
313
385
  obj.flow,
386
+ obj.package.package_metadata,
314
387
  package_sha,
315
388
  package_url,
316
389
  token,
@@ -320,12 +393,14 @@ def make_flow(
320
393
  obj.event_logger,
321
394
  obj.monitor,
322
395
  tags=tags,
396
+ aws_batch_tags=batch_tags,
323
397
  namespace=namespace,
324
398
  max_workers=max_workers,
325
399
  username=get_username(),
326
400
  workflow_timeout=workflow_timeout,
327
401
  is_project=is_project,
328
402
  use_distributed_map=use_distributed_map,
403
+ compress_state_machine=compress_state_machine,
329
404
  )
330
405
 
331
406
 
@@ -440,8 +515,16 @@ def resolve_token(
440
515
  type=str,
441
516
  help="Write the ID of this run to the file specified.",
442
517
  )
518
+ @click.option(
519
+ "--deployer-attribute-file",
520
+ default=None,
521
+ show_default=True,
522
+ type=str,
523
+ help="Write the metadata and pathspec of this run to the file specified.\nUsed internally for Metaflow's Deployer API.",
524
+ hidden=True,
525
+ )
443
526
  @click.pass_obj
444
- def trigger(obj, run_id_file=None, **kwargs):
527
+ def trigger(obj, run_id_file=None, deployer_attribute_file=None, **kwargs):
445
528
  def _convert_value(param):
446
529
  # Swap `-` with `_` in parameter name to match click's behavior
447
530
  val = kwargs.get(param.name.replace("-", "_").lower())
@@ -466,6 +549,17 @@ def trigger(obj, run_id_file=None, **kwargs):
466
549
  with open(run_id_file, "w") as f:
467
550
  f.write(str(run_id))
468
551
 
552
+ if deployer_attribute_file:
553
+ with open(deployer_attribute_file, "w") as f:
554
+ json.dump(
555
+ {
556
+ "name": obj.state_machine_name,
557
+ "metadata": obj.metadata.metadata_str(),
558
+ "pathspec": "/".join((obj.flow.name, run_id)),
559
+ },
560
+ f,
561
+ )
562
+
469
563
  obj.echo(
470
564
  "Workflow *{name}* triggered on AWS Step Functions "
471
565
  "(run-id *{run_id}*).".format(name=obj.state_machine_name, run_id=run_id),
@@ -1,9 +1,8 @@
1
- import json
2
1
  import os
3
2
  import time
4
3
 
5
4
  from metaflow.decorators import StepDecorator
6
- from metaflow.metadata import MetaDatum
5
+ from metaflow.metadata_provider import MetaDatum
7
6
 
8
7
  from .dynamo_db_client import DynamoDbClient
9
8
 
@@ -0,0 +1,97 @@
1
+ from typing import Any, ClassVar, Dict, Optional, TYPE_CHECKING, Type
2
+
3
+ from metaflow.runner.deployer_impl import DeployerImpl
4
+
5
+ if TYPE_CHECKING:
6
+ import metaflow.plugins.aws.step_functions.step_functions_deployer_objects
7
+
8
+
9
+ class StepFunctionsDeployer(DeployerImpl):
10
+ """
11
+ Deployer implementation for AWS Step Functions.
12
+
13
+ Parameters
14
+ ----------
15
+ name : str, optional, default None
16
+ State Machine name. The flow name is used instead if this option is not specified.
17
+ """
18
+
19
+ TYPE: ClassVar[Optional[str]] = "step-functions"
20
+
21
+ def __init__(self, deployer_kwargs: Dict[str, str], **kwargs):
22
+ """
23
+ Initialize the StepFunctionsDeployer.
24
+
25
+ Parameters
26
+ ----------
27
+ deployer_kwargs : Dict[str, str]
28
+ The deployer-specific keyword arguments.
29
+ **kwargs : Any
30
+ Additional arguments to pass to the superclass constructor.
31
+ """
32
+ self._deployer_kwargs = deployer_kwargs
33
+ super().__init__(**kwargs)
34
+
35
+ @property
36
+ def deployer_kwargs(self) -> Dict[str, Any]:
37
+ return self._deployer_kwargs
38
+
39
+ @staticmethod
40
+ def deployed_flow_type() -> (
41
+ Type[
42
+ "metaflow.plugins.aws.step_functions.step_functions_deployer_objects.StepFunctionsDeployedFlow"
43
+ ]
44
+ ):
45
+ from .step_functions_deployer_objects import StepFunctionsDeployedFlow
46
+
47
+ return StepFunctionsDeployedFlow
48
+
49
+ def create(
50
+ self, **kwargs
51
+ ) -> "metaflow.plugins.aws.step_functions.step_functions_deployer_objects.StepFunctionsDeployedFlow":
52
+ """
53
+ Create a new AWS Step Functions State Machine deployment.
54
+
55
+ Parameters
56
+ ----------
57
+ authorize : str, optional, default None
58
+ Authorize using this production token. Required when re-deploying an existing flow
59
+ for the first time. The token is cached in METAFLOW_HOME.
60
+ generate_new_token : bool, optional, default False
61
+ Generate a new production token for this flow. Moves the production flow to a new namespace.
62
+ given_token : str, optional, default None
63
+ Use the given production token for this flow. Moves the production flow to the given namespace.
64
+ tags : List[str], optional, default None
65
+ Annotate all objects produced by AWS Step Functions runs with these tags.
66
+ user_namespace : str, optional, default None
67
+ Change the namespace from the default (production token) to the given tag.
68
+ only_json : bool, optional, default False
69
+ Only print out JSON sent to AWS Step Functions without deploying anything.
70
+ max_workers : int, optional, default 100
71
+ Maximum number of parallel processes.
72
+ workflow_timeout : int, optional, default None
73
+ Workflow timeout in seconds.
74
+ log_execution_history : bool, optional, default False
75
+ Log AWS Step Functions execution history to AWS CloudWatch Logs log group.
76
+ use_distributed_map : bool, optional, default False
77
+ Use AWS Step Functions Distributed Map instead of Inline Map for defining foreach
78
+ tasks in Amazon State Language.
79
+ compress_state_machine : bool, optional, default False
80
+ Compress AWS Step Functions state machine to fit within the 8K limit.
81
+
82
+ deployer_attribute_file : str, optional, default None
83
+ Write the workflow name to the specified file. Used internally for Metaflow's Deployer API.
84
+
85
+ Returns
86
+ -------
87
+ StepFunctionsDeployedFlow
88
+ The Flow deployed to AWS Step Functions.
89
+ """
90
+ from .step_functions_deployer_objects import StepFunctionsDeployedFlow
91
+
92
+ return self._create(StepFunctionsDeployedFlow, **kwargs)
93
+
94
+
95
+ _addl_stubgen_modules = [
96
+ "metaflow.plugins.aws.step_functions.step_functions_deployer_objects"
97
+ ]