ob-metaflow 2.15.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 (169) hide show
  1. metaflow/__init__.py +10 -3
  2. metaflow/_vendor/imghdr/__init__.py +186 -0
  3. metaflow/_vendor/yaml/__init__.py +427 -0
  4. metaflow/_vendor/yaml/composer.py +139 -0
  5. metaflow/_vendor/yaml/constructor.py +748 -0
  6. metaflow/_vendor/yaml/cyaml.py +101 -0
  7. metaflow/_vendor/yaml/dumper.py +62 -0
  8. metaflow/_vendor/yaml/emitter.py +1137 -0
  9. metaflow/_vendor/yaml/error.py +75 -0
  10. metaflow/_vendor/yaml/events.py +86 -0
  11. metaflow/_vendor/yaml/loader.py +63 -0
  12. metaflow/_vendor/yaml/nodes.py +49 -0
  13. metaflow/_vendor/yaml/parser.py +589 -0
  14. metaflow/_vendor/yaml/reader.py +185 -0
  15. metaflow/_vendor/yaml/representer.py +389 -0
  16. metaflow/_vendor/yaml/resolver.py +227 -0
  17. metaflow/_vendor/yaml/scanner.py +1435 -0
  18. metaflow/_vendor/yaml/serializer.py +111 -0
  19. metaflow/_vendor/yaml/tokens.py +104 -0
  20. metaflow/cards.py +4 -0
  21. metaflow/cli.py +125 -21
  22. metaflow/cli_components/init_cmd.py +1 -0
  23. metaflow/cli_components/run_cmds.py +204 -40
  24. metaflow/cli_components/step_cmd.py +160 -4
  25. metaflow/client/__init__.py +1 -0
  26. metaflow/client/core.py +198 -130
  27. metaflow/client/filecache.py +59 -32
  28. metaflow/cmd/code/__init__.py +2 -1
  29. metaflow/cmd/develop/stub_generator.py +49 -18
  30. metaflow/cmd/develop/stubs.py +9 -27
  31. metaflow/cmd/make_wrapper.py +30 -0
  32. metaflow/datastore/__init__.py +1 -0
  33. metaflow/datastore/content_addressed_store.py +40 -9
  34. metaflow/datastore/datastore_set.py +10 -1
  35. metaflow/datastore/flow_datastore.py +124 -4
  36. metaflow/datastore/spin_datastore.py +91 -0
  37. metaflow/datastore/task_datastore.py +92 -6
  38. metaflow/debug.py +5 -0
  39. metaflow/decorators.py +331 -82
  40. metaflow/extension_support/__init__.py +414 -356
  41. metaflow/extension_support/_empty_file.py +2 -2
  42. metaflow/flowspec.py +322 -82
  43. metaflow/graph.py +178 -15
  44. metaflow/includefile.py +25 -3
  45. metaflow/lint.py +94 -3
  46. metaflow/meta_files.py +13 -0
  47. metaflow/metadata_provider/metadata.py +13 -2
  48. metaflow/metaflow_config.py +66 -4
  49. metaflow/metaflow_environment.py +91 -25
  50. metaflow/metaflow_profile.py +18 -0
  51. metaflow/metaflow_version.py +16 -1
  52. metaflow/package/__init__.py +673 -0
  53. metaflow/packaging_sys/__init__.py +880 -0
  54. metaflow/packaging_sys/backend.py +128 -0
  55. metaflow/packaging_sys/distribution_support.py +153 -0
  56. metaflow/packaging_sys/tar_backend.py +99 -0
  57. metaflow/packaging_sys/utils.py +54 -0
  58. metaflow/packaging_sys/v1.py +527 -0
  59. metaflow/parameters.py +6 -2
  60. metaflow/plugins/__init__.py +6 -0
  61. metaflow/plugins/airflow/airflow.py +11 -1
  62. metaflow/plugins/airflow/airflow_cli.py +16 -5
  63. metaflow/plugins/argo/argo_client.py +42 -20
  64. metaflow/plugins/argo/argo_events.py +6 -6
  65. metaflow/plugins/argo/argo_workflows.py +1023 -344
  66. metaflow/plugins/argo/argo_workflows_cli.py +396 -94
  67. metaflow/plugins/argo/argo_workflows_decorator.py +9 -0
  68. metaflow/plugins/argo/argo_workflows_deployer_objects.py +75 -49
  69. metaflow/plugins/argo/capture_error.py +5 -2
  70. metaflow/plugins/argo/conditional_input_paths.py +35 -0
  71. metaflow/plugins/argo/exit_hooks.py +209 -0
  72. metaflow/plugins/argo/param_val.py +19 -0
  73. metaflow/plugins/aws/aws_client.py +6 -0
  74. metaflow/plugins/aws/aws_utils.py +33 -1
  75. metaflow/plugins/aws/batch/batch.py +72 -5
  76. metaflow/plugins/aws/batch/batch_cli.py +24 -3
  77. metaflow/plugins/aws/batch/batch_decorator.py +57 -6
  78. metaflow/plugins/aws/step_functions/step_functions.py +28 -3
  79. metaflow/plugins/aws/step_functions/step_functions_cli.py +49 -4
  80. metaflow/plugins/aws/step_functions/step_functions_deployer.py +3 -0
  81. metaflow/plugins/aws/step_functions/step_functions_deployer_objects.py +30 -0
  82. metaflow/plugins/cards/card_cli.py +20 -1
  83. metaflow/plugins/cards/card_creator.py +24 -1
  84. metaflow/plugins/cards/card_datastore.py +21 -49
  85. metaflow/plugins/cards/card_decorator.py +58 -6
  86. metaflow/plugins/cards/card_modules/basic.py +38 -9
  87. metaflow/plugins/cards/card_modules/bundle.css +1 -1
  88. metaflow/plugins/cards/card_modules/chevron/renderer.py +1 -1
  89. metaflow/plugins/cards/card_modules/components.py +592 -3
  90. metaflow/plugins/cards/card_modules/convert_to_native_type.py +34 -5
  91. metaflow/plugins/cards/card_modules/json_viewer.py +232 -0
  92. metaflow/plugins/cards/card_modules/main.css +1 -0
  93. metaflow/plugins/cards/card_modules/main.js +56 -41
  94. metaflow/plugins/cards/card_modules/test_cards.py +22 -6
  95. metaflow/plugins/cards/component_serializer.py +1 -8
  96. metaflow/plugins/cards/metadata.py +22 -0
  97. metaflow/plugins/catch_decorator.py +9 -0
  98. metaflow/plugins/datastores/local_storage.py +12 -6
  99. metaflow/plugins/datastores/spin_storage.py +12 -0
  100. metaflow/plugins/datatools/s3/s3.py +49 -17
  101. metaflow/plugins/datatools/s3/s3op.py +113 -66
  102. metaflow/plugins/env_escape/client_modules.py +102 -72
  103. metaflow/plugins/events_decorator.py +127 -121
  104. metaflow/plugins/exit_hook/__init__.py +0 -0
  105. metaflow/plugins/exit_hook/exit_hook_decorator.py +46 -0
  106. metaflow/plugins/exit_hook/exit_hook_script.py +52 -0
  107. metaflow/plugins/kubernetes/kubernetes.py +12 -1
  108. metaflow/plugins/kubernetes/kubernetes_cli.py +11 -0
  109. metaflow/plugins/kubernetes/kubernetes_decorator.py +25 -6
  110. metaflow/plugins/kubernetes/kubernetes_job.py +12 -4
  111. metaflow/plugins/kubernetes/kubernetes_jobsets.py +31 -30
  112. metaflow/plugins/metadata_providers/local.py +76 -82
  113. metaflow/plugins/metadata_providers/service.py +13 -9
  114. metaflow/plugins/metadata_providers/spin.py +16 -0
  115. metaflow/plugins/package_cli.py +36 -24
  116. metaflow/plugins/parallel_decorator.py +11 -2
  117. metaflow/plugins/parsers.py +16 -0
  118. metaflow/plugins/pypi/bootstrap.py +7 -1
  119. metaflow/plugins/pypi/conda_decorator.py +41 -82
  120. metaflow/plugins/pypi/conda_environment.py +14 -6
  121. metaflow/plugins/pypi/micromamba.py +9 -1
  122. metaflow/plugins/pypi/pip.py +41 -5
  123. metaflow/plugins/pypi/pypi_decorator.py +4 -4
  124. metaflow/plugins/pypi/utils.py +22 -0
  125. metaflow/plugins/secrets/__init__.py +3 -0
  126. metaflow/plugins/secrets/secrets_decorator.py +14 -178
  127. metaflow/plugins/secrets/secrets_func.py +49 -0
  128. metaflow/plugins/secrets/secrets_spec.py +101 -0
  129. metaflow/plugins/secrets/utils.py +74 -0
  130. metaflow/plugins/test_unbounded_foreach_decorator.py +2 -2
  131. metaflow/plugins/timeout_decorator.py +0 -1
  132. metaflow/plugins/uv/bootstrap.py +29 -1
  133. metaflow/plugins/uv/uv_environment.py +5 -3
  134. metaflow/pylint_wrapper.py +5 -1
  135. metaflow/runner/click_api.py +79 -26
  136. metaflow/runner/deployer.py +208 -6
  137. metaflow/runner/deployer_impl.py +32 -12
  138. metaflow/runner/metaflow_runner.py +266 -33
  139. metaflow/runner/subprocess_manager.py +21 -1
  140. metaflow/runner/utils.py +27 -16
  141. metaflow/runtime.py +660 -66
  142. metaflow/task.py +255 -26
  143. metaflow/user_configs/config_options.py +33 -21
  144. metaflow/user_configs/config_parameters.py +220 -58
  145. metaflow/user_decorators/__init__.py +0 -0
  146. metaflow/user_decorators/common.py +144 -0
  147. metaflow/user_decorators/mutable_flow.py +512 -0
  148. metaflow/user_decorators/mutable_step.py +424 -0
  149. metaflow/user_decorators/user_flow_decorator.py +264 -0
  150. metaflow/user_decorators/user_step_decorator.py +749 -0
  151. metaflow/util.py +197 -7
  152. metaflow/vendor.py +23 -7
  153. metaflow/version.py +1 -1
  154. {ob_metaflow-2.15.13.1.data → ob_metaflow-2.19.7.1rc0.data}/data/share/metaflow/devtools/Makefile +13 -2
  155. {ob_metaflow-2.15.13.1.data → ob_metaflow-2.19.7.1rc0.data}/data/share/metaflow/devtools/Tiltfile +107 -7
  156. {ob_metaflow-2.15.13.1.data → ob_metaflow-2.19.7.1rc0.data}/data/share/metaflow/devtools/pick_services.sh +1 -0
  157. {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/METADATA +2 -3
  158. {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/RECORD +162 -121
  159. {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/WHEEL +1 -1
  160. metaflow/_vendor/v3_5/__init__.py +0 -1
  161. metaflow/_vendor/v3_5/importlib_metadata/__init__.py +0 -644
  162. metaflow/_vendor/v3_5/importlib_metadata/_compat.py +0 -152
  163. metaflow/_vendor/v3_5/zipp.py +0 -329
  164. metaflow/info_file.py +0 -25
  165. metaflow/package.py +0 -203
  166. metaflow/user_configs/config_decorators.py +0 -568
  167. {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/entry_points.txt +0 -0
  168. {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/licenses/LICENSE +0 -0
  169. {ob_metaflow-2.15.13.1.dist-info → ob_metaflow-2.19.7.1rc0.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,9 @@ TypeResolvedObject = namedtuple("TypeResolvedObject", ["data", "is_image", "is_t
8
8
 
9
9
 
10
10
  TIME_FORMAT = "%Y-%m-%d %I:%M:%S %p"
11
- MAX_ARTIFACT_SIZE = 1 # in 1 MB
11
+ # Maximum artifact size to render in cards: 200MB (in bytes)
12
+ # Artifacts larger than this will be skipped during card rendering to avoid memory issues
13
+ MAX_ARTIFACT_SIZE = 256 * 1024 * 1024 # 256 MB = 268435456 bytes
12
14
 
13
15
 
14
16
  def _get_object_size(obj, seen=None):
@@ -44,7 +46,7 @@ def _full_classname(obj):
44
46
 
45
47
 
46
48
  class TaskToDict:
47
- def __init__(self, only_repr=False, runtime=False):
49
+ def __init__(self, only_repr=False, runtime=False, max_artifact_size=None):
48
50
  # this dictionary holds all the supported functions
49
51
  import reprlib
50
52
  import pprint
@@ -61,6 +63,10 @@ class TaskToDict:
61
63
  self._repr = r
62
64
  self._runtime = runtime
63
65
  self._only_repr = only_repr
66
+ # Use the global MAX_ARTIFACT_SIZE constant if not specified
67
+ self._max_artifact_size = (
68
+ max_artifact_size if max_artifact_size is not None else MAX_ARTIFACT_SIZE
69
+ )
64
70
  self._supported_types = {
65
71
  "tuple": self._parse_tuple,
66
72
  "NoneType": self._parse_nonetype,
@@ -110,6 +116,19 @@ class TaskToDict:
110
116
  task_data_dict = {}
111
117
  type_inferred_objects = {"images": {}, "tables": {}}
112
118
  for data in task:
119
+ # Check if artifact size exceeds the maximum allowed size
120
+ if data.size > self._max_artifact_size:
121
+ # Skip artifacts that are too large
122
+ task_data_dict[data.id] = dict(
123
+ type="skipped",
124
+ data=f"<artifact too large: {data.size} bytes, max: {self._max_artifact_size} bytes>",
125
+ large_object=True,
126
+ supported_type=False,
127
+ only_repr=self._only_repr,
128
+ name=data.id,
129
+ )
130
+ continue
131
+
113
132
  try:
114
133
  data_object = data.data
115
134
  task_data_dict[data.id] = self._convert_to_native_type(data_object)
@@ -143,7 +162,16 @@ class TaskToDict:
143
162
  obj_type_name = self._get_object_type(data_object)
144
163
  if obj_type_name == "bytes":
145
164
  # Works for python 3.1+
146
- import imghdr
165
+ # Python 3.13 removes the standard ``imghdr`` module. Metaflow
166
+ # vendors a copy so we can keep using ``what`` to detect image
167
+ # formats irrespective of the Python version.
168
+ import warnings
169
+
170
+ with warnings.catch_warnings():
171
+ warnings.filterwarnings(
172
+ "ignore", category=DeprecationWarning, module="imghdr"
173
+ )
174
+ from metaflow._vendor import imghdr
147
175
 
148
176
  resp = imghdr.what(None, h=data_object)
149
177
  # Only accept types supported on the web
@@ -157,7 +185,7 @@ class TaskToDict:
157
185
  obj_type_name = self._get_object_type(data_object)
158
186
  if obj_type_name == "bytes":
159
187
  # Works for python 3.1+
160
- import imghdr
188
+ from metaflow._vendor import imghdr
161
189
 
162
190
  resp = imghdr.what(None, h=data_object)
163
191
  # Only accept types supported on the web
@@ -232,7 +260,8 @@ class TaskToDict:
232
260
  supported_type = True
233
261
  type_parsing_func = self._supported_types[obj_type_name]
234
262
  data_obj = type_parsing_func(data_object)
235
- if _get_object_size(data_obj) * 1e-6 > MAX_ARTIFACT_SIZE:
263
+ # Secondary check: if the in-memory object size exceeds our limit, use repr instead
264
+ if _get_object_size(data_obj) > self._max_artifact_size:
236
265
  data_obj = rep.repr(data_obj)
237
266
  large_object = True
238
267
  else:
@@ -0,0 +1,232 @@
1
+ """
2
+ JSONViewer component for displaying JSON data with syntax highlighting and collapsible sections.
3
+ """
4
+
5
+ from typing import Any, Optional, Union
6
+ from .card import MetaflowCardComponent, with_default_component_id
7
+ from .renderer_tools import render_safely
8
+ import json
9
+ from metaflow._vendor import yaml
10
+
11
+
12
+ class JSONViewer(MetaflowCardComponent):
13
+ """
14
+ A component for displaying JSON data with syntax highlighting and collapsible sections.
15
+
16
+ This component provides a rich view of JSON data with proper formatting, syntax highlighting,
17
+ and the ability to collapse/expand sections for better readability.
18
+
19
+ Example:
20
+ ```python
21
+ from metaflow.cards import JSONViewer
22
+ from metaflow import current
23
+
24
+ data = {
25
+ "user": {"name": "Alice", "age": 30},
26
+ "items": [{"id": 1, "name": "Item 1"}, {"id": 2, "name": "Item 2"}],
27
+ "metadata": {"created": "2024-01-01", "version": "1.0"}
28
+ }
29
+
30
+ json_viewer = JSONViewer(data, collapsible=True, max_height="400px")
31
+ current.card.append(json_viewer)
32
+ ```
33
+
34
+ Parameters
35
+ ----------
36
+ data : Any
37
+ The data to display as JSON. Will be serialized using json.dumps().
38
+ collapsible : bool, default True
39
+ Whether to make the JSON viewer collapsible.
40
+ max_height : str, optional
41
+ Maximum height for the viewer (CSS value like "300px" or "20rem").
42
+ show_copy_button : bool, default True
43
+ Whether to show a copy-to-clipboard button.
44
+ """
45
+
46
+ type = "jsonViewer"
47
+
48
+ REALTIME_UPDATABLE = True
49
+
50
+ def __init__(
51
+ self,
52
+ data: Any,
53
+ collapsible: bool = True,
54
+ max_height: Optional[str] = None,
55
+ show_copy_button: bool = True,
56
+ title: Optional[str] = None,
57
+ ):
58
+ self._data = data
59
+ self._collapsible = collapsible
60
+ self._max_height = max_height
61
+ self._show_copy_button = show_copy_button
62
+ self._title = title
63
+
64
+ def update(self, data: Any):
65
+ """
66
+ Update the JSON data.
67
+
68
+ Parameters
69
+ ----------
70
+ data : Any
71
+ New data to display as JSON.
72
+ """
73
+ self._data = data
74
+
75
+ @with_default_component_id
76
+ @render_safely
77
+ def render(self):
78
+ # Serialize data to JSON string
79
+ try:
80
+ if isinstance(self._data, str):
81
+ # If already a string, try to parse and re-serialize for formatting
82
+ try:
83
+ parsed = json.loads(self._data)
84
+ json_string = json.dumps(parsed, indent=2, ensure_ascii=False)
85
+ except json.JSONDecodeError:
86
+ # If not valid JSON, treat as plain string
87
+ json_string = json.dumps(self._data, indent=2, ensure_ascii=False)
88
+ else:
89
+ json_string = json.dumps(
90
+ self._data, indent=2, ensure_ascii=False, default=str
91
+ )
92
+ except Exception as e:
93
+ # Fallback for non-serializable objects
94
+ json_string = json.dumps(
95
+ {"error": f"Could not serialize data: {str(e)}"}, indent=2
96
+ )
97
+
98
+ data = {
99
+ "type": self.type,
100
+ "id": self.component_id,
101
+ "json_string": json_string,
102
+ "collapsible": self._collapsible,
103
+ "show_copy_button": self._show_copy_button,
104
+ "title": self._title or "JSON",
105
+ }
106
+
107
+ if self._max_height:
108
+ data["max_height"] = self._max_height
109
+
110
+ return data
111
+
112
+
113
+ class YAMLViewer(MetaflowCardComponent):
114
+ """
115
+ A component for displaying YAML data with syntax highlighting and collapsible sections.
116
+
117
+ This component provides a rich view of YAML data with proper formatting and syntax highlighting.
118
+
119
+ Example:
120
+ ```python
121
+ from metaflow.cards import YAMLViewer
122
+ from metaflow import current
123
+
124
+ data = {
125
+ "database": {
126
+ "host": "localhost",
127
+ "port": 5432,
128
+ "credentials": {"username": "admin", "password": "secret"}
129
+ },
130
+ "features": ["auth", "logging", "monitoring"]
131
+ }
132
+
133
+ yaml_viewer = YAMLViewer(data, collapsible=True)
134
+ current.card.append(yaml_viewer)
135
+ ```
136
+
137
+ Parameters
138
+ ----------
139
+ data : Any
140
+ The data to display as YAML. Will be serialized to YAML format.
141
+ collapsible : bool, default True
142
+ Whether to make the YAML viewer collapsible.
143
+ max_height : str, optional
144
+ Maximum height for the viewer (CSS value like "300px" or "20rem").
145
+ show_copy_button : bool, default True
146
+ Whether to show a copy-to-clipboard button.
147
+ """
148
+
149
+ type = "yamlViewer"
150
+
151
+ REALTIME_UPDATABLE = True
152
+
153
+ def __init__(
154
+ self,
155
+ data: Any,
156
+ collapsible: bool = True,
157
+ max_height: Optional[str] = None,
158
+ show_copy_button: bool = True,
159
+ title: Optional[str] = None,
160
+ ):
161
+ self._data = data
162
+ self._collapsible = collapsible
163
+ self._max_height = max_height
164
+ self._show_copy_button = show_copy_button
165
+ self._title = title
166
+
167
+ def update(self, data: Any):
168
+ """
169
+ Update the YAML data.
170
+
171
+ Parameters
172
+ ----------
173
+ data : Any
174
+ New data to display as YAML.
175
+ """
176
+ self._data = data
177
+
178
+ def _to_yaml_string(self, data: Any) -> str:
179
+ """
180
+ Convert data to YAML string format using vendored YAML module.
181
+ """
182
+ try:
183
+ if isinstance(data, str):
184
+ # Try to parse as JSON first, then convert to YAML
185
+ try:
186
+ import json
187
+
188
+ parsed = json.loads(data)
189
+ yaml_result = yaml.dump(
190
+ parsed, default_flow_style=False, indent=2, sort_keys=False
191
+ )
192
+ return (
193
+ str(yaml_result)
194
+ if yaml_result is not None
195
+ else "# Empty YAML result"
196
+ )
197
+ except json.JSONDecodeError:
198
+ # If not JSON, return as-is
199
+ return data
200
+ else:
201
+ yaml_result = yaml.dump(
202
+ data, default_flow_style=False, indent=2, sort_keys=False
203
+ )
204
+ return (
205
+ str(yaml_result)
206
+ if yaml_result is not None
207
+ else "# Empty YAML result"
208
+ )
209
+ except Exception as e:
210
+ # Fallback to JSON on any error
211
+ import json
212
+
213
+ return f"# Error converting to YAML: {str(e)}\n{json.dumps(data, indent=2, default=str)}"
214
+
215
+ @with_default_component_id
216
+ @render_safely
217
+ def render(self):
218
+ yaml_string = self._to_yaml_string(self._data)
219
+
220
+ data = {
221
+ "type": self.type,
222
+ "id": self.component_id,
223
+ "yaml_string": yaml_string,
224
+ "collapsible": self._collapsible,
225
+ "show_copy_button": self._show_copy_button,
226
+ "title": self._title or "YAML",
227
+ }
228
+
229
+ if self._max_height:
230
+ data["max_height"] = self._max_height
231
+
232
+ return data
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap";code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:#ffffff80}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}:root{--bg: #ffffff;--black: #333;--blue: #0c66de;--dk-grey: #767676;--dk-primary: #ef863b;--dk-secondary: #13172d;--dk-tertiary: #0f426e;--error: #cf483e;--grey: rgba(0, 0, 0, .125);--highlight: #f8d9d8;--lt-blue: #4fa7ff;--lt-grey: #f3f3f3;--lt-lt-grey: #f9f9f9;--lt-primary: #ffcb8b;--lt-secondary: #434d81;--lt-tertiary: #4189c9;--primary: #faab4a;--quadrary: #f8d9d8;--secondary: #2e3454;--tertiary: #2a679d;--white: #ffffff;--component-spacer: 3rem;--aside-width: 20rem;--embed-card-min-height: 12rem;--mono-font: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace}html,body{margin:0;min-height:100vh;overflow-y:visible;padding:0;width:100%}.card_app{width:100%;min-height:100vh}.embed .card_app{min-height:var(--embed-card-min-height)}.mf-card *{box-sizing:border-box}.mf-card{background:var(--bg);color:var(--black);font-family:Roboto,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-size:14px;font-weight:400;line-height:1.5;text-size-adjust:100%;margin:0;min-height:100vh;overflow-y:visible;padding:0;text-align:left;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;width:100%}.embed .mf-card{min-height:var(--embed-card-min-height)}.mf-card :is(.mono,code.mono,pre.mono){font-family:var(--mono-font);font-weight:lighter}.mf-card :is(table,th,td){border-spacing:1px;text-align:center;color:var(--black)}.mf-card table{position:relative;min-width:100%;table-layout:inherit!important}.mf-card td{padding:.66rem 1.25rem;background:var(--lt-lt-grey);border:none}.mf-card th{border:none;color:var(--dk-grey);font-weight:400;padding:.5rem}.mf-card :is(h1,h2,h3,h4,h5){font-weight:700;margin:.5rem 0}.mf-card ul{margin:0;padding:0}.mf-card p{margin:0 0 1rem}.mf-card p:last-of-type{margin:0}.mf-card button{font-size:1rem}.mf-card .textButton{cursor:pointer;text-align:left;background:none;border:1px solid transparent;outline:none;padding:0}.mf-card :is(button.textButton:focus,a:focus,button.textButton:active){border:1px dashed var(--grey);background:transparent}.mf-card button.textButton:hover{color:var(--blue);text-decoration:none}.mf-card :is(:not(pre)>code[class*=language-],pre[class*=language-]){background:transparent!important;text-shadow:none;-webkit-user-select:auto;user-select:auto}aside.svelte-1okdv0e{display:none;line-height:2;text-align:left}@media (min-width: 60rem){aside.svelte-1okdv0e{display:flex;flex-direction:column;height:100vh;justify-content:space-between;padding:2.5rem 0 1.5rem 1.5rem;position:fixed;width:var(--aside-width)}}.embed aside{display:none}aside ul{list-style-type:none}aside a,aside button,aside a:visited{text-decoration:none;cursor:pointer;font-weight:700;color:var(--black)}aside a:hover,aside button:hover{text-decoration:underline}.logoContainer svg{width:100%;max-width:140px;margin-bottom:3.75rem;height:auto}.idCell.svelte-pt8vzv{font-weight:700;text-align:right;background:var(--lt-grey);width:12%}.codeCell.svelte-pt8vzv{text-align:left;-webkit-user-select:all;user-select:all}.container.svelte-ubs992{width:100%;overflow:auto}table.svelte-ubs992{width:100%}:root{--dag-border: #282828;--dag-bg-static: var(--lt-grey);--dag-bg-success: #a5d46a;--dag-bg-running: #ffdf80;--dag-bg-error: #ffa080;--dag-connector: #cccccc;--dag-gap: 5rem;--dag-step-height: 6.25rem;--dag-step-width: 11.25rem;--dag-selected: #ffd700}.connectorwrapper.svelte-1hyaq5f{transform-origin:0 0;position:absolute;z-index:0;min-width:var(--strokeWidth)}.flip.svelte-1hyaq5f{transform:scaleX(-1)}.path.svelte-1hyaq5f{--strokeWidth: .5rem;--strokeColor: var(--dag-connector);--borderRadius: 1.25rem;box-sizing:border-box}.straightLine.svelte-1hyaq5f{position:absolute;inset:0;border-left:var(--strokeWidth) solid var(--strokeColor)}.topLeft.svelte-1hyaq5f{position:absolute;top:0;left:0;right:50%;bottom:calc(var(--dag-gap) / 2 - var(--strokeWidth) / 2);border-radius:0 0 0 var(--borderRadius);border-left:var(--strokeWidth) solid var(--strokeColor);border-bottom:var(--strokeWidth) solid var(--strokeColor)}.bottomRight.svelte-1hyaq5f{position:absolute;top:calc(100% - (var(--dag-gap) / 2 + var(--strokeWidth) / 2));left:50%;right:0;bottom:0;border-radius:0 var(--borderRadius) 0 0;border-top:var(--strokeWidth) solid var(--strokeColor);border-right:var(--strokeWidth) solid var(--strokeColor)}.wrapper.svelte-117ceti{position:relative;z-index:1}.step.svelte-117ceti{font-size:.75rem;padding:.5rem;color:var(--dk-grey)}.rectangle.svelte-117ceti{background-color:var(--dag-bg-static);border:1px solid var(--dag-border);box-sizing:border-box;position:relative;height:var(--dag-step-height);width:var(--dag-step-width)}.rectangle.error.svelte-117ceti{background-color:var(--dag-bg-error)}.rectangle.success.svelte-117ceti{background-color:var(--dag-bg-success)}.rectangle.running.svelte-117ceti{background-color:var(--dag-bg-running)}.level.svelte-117ceti{z-index:-1;filter:contrast(.5);position:absolute}.inner.svelte-117ceti{position:relative;height:100%;width:100%}.name.svelte-117ceti{font-weight:700;overflow:hidden;text-overflow:ellipsis;display:block}.description.svelte-117ceti{position:absolute;max-height:4rem;bottom:0;left:0;right:0;overflow:hidden;-webkit-line-clamp:4;line-clamp:4;display:-webkit-box;-webkit-box-orient:vertical}.overflown.description.svelte-117ceti{cursor:help}.current.svelte-117ceti .rectangle:where(.svelte-117ceti){box-shadow:0 0 10px var(--dag-selected)}.levelstoshow.svelte-117ceti{position:absolute;bottom:100%;right:0;font-size:.75rem;font-weight:100;text-align:right}.stepwrapper.svelte-18aex7a{display:flex;align-items:center;flex-direction:column;width:100%;position:relative;min-width:var(--dag-step-width)}.childwrapper.svelte-18aex7a{display:flex;width:100%}.gap.svelte-18aex7a{height:var(--dag-gap)}.title.svelte-117s0ws{text-align:left}.subtitle.svelte-lu9pnn{font-size:1rem;text-align:left}header.svelte-1ugmt5d{margin-bottom:var(--component-spacer)}figure.svelte-1x96yvr{background:var(--lt-grey);padding:1rem;border-radius:5px;text-align:center;margin:0 auto var(--component-spacer)}@media (min-width: 60rem){figure.svelte-1x96yvr{margin-bottom:0}}img.svelte-1x96yvr{max-width:100%;max-height:500px}.label.svelte-1x96yvr{font-weight:700;margin:.5rem 0}.description.svelte-1x96yvr{font-size:.9rem;font-style:italic;text-align:center;margin:.5rem 0}.log.svelte-1jhmsu{background:var(--lt-grey)!important;font-size:.9rem;padding:2rem}.page.svelte-v7ihqd:last-of-type{margin-bottom:var(--component-spacer)}.page:last-of-type section:last-of-type hr{display:none}progress.svelte-ljrmzp::-webkit-progress-bar{background-color:#fff!important;min-width:100%}progress.svelte-ljrmzp{background-color:#fff;color:#326cded9!important}progress.svelte-ljrmzp::-moz-progress-bar{background-color:#326cde!important}table .container{background:transparent!important;font-size:10px!important;padding:0!important}table progress{height:4px!important}.container.svelte-ljrmzp{display:flex;align-items:center;justify-content:center;font-size:12px;border-radius:3px;background:#edf5ff;padding:3rem}.inner.svelte-ljrmzp{max-width:410px;width:100%;text-align:center}.info.svelte-ljrmzp{display:flex;justify-content:space-between}table .info{text-align:left;flex-direction:column}label.svelte-ljrmzp{font-weight:700}.labelValue.svelte-ljrmzp{border-left:1px solid rgba(0,0,0,.1);margin-left:.25rem;padding-left:.5rem}.details.svelte-ljrmzp{font-family:var(--mono-font);font-size:8px;color:#333433;line-height:18px;overflow:hidden;white-space:nowrap}progress.svelte-ljrmzp{width:100%;border:none;border-radius:5px;height:8px;background:#fff}.heading.svelte-17n0qr8{margin-bottom:1.5rem}.sectionItems.svelte-17n0qr8{display:block}.sectionItems .imageContainer{max-height:500px}.container.svelte-17n0qr8{scroll-margin:var(--component-spacer)}hr.svelte-17n0qr8{background:var(--grey);border:none;height:1px;margin:var(--component-spacer) 0;padding:0}@media (min-width: 60rem){.sectionItems.svelte-17n0qr8{display:grid;grid-gap:2rem}}td.svelte-gl9h79{text-align:left}td.labelColumn.svelte-gl9h79{text-align:right;background-color:var(--lt-grey);font-weight:700;width:12%;white-space:nowrap}.tableContainer.svelte-q3hq57{overflow:auto}th.svelte-q3hq57{position:sticky;top:-1px;z-index:2;white-space:nowrap;background:var(--white)}.mainContainer.svelte-mqeomk{max-width:110rem}main.svelte-mqeomk{flex:0 1 auto;max-width:100rem;padding:1.5rem}@media (min-width: 60rem){main.svelte-mqeomk{margin-left:var(--aside-width)}}.embed main{margin:0 auto;min-width:80%}.modal.svelte-1hhf5ym{align-items:center;background:#00000080;cursor:pointer;display:flex;height:100%;justify-content:center;inset:0;overflow:hidden;position:fixed;width:100%;z-index:100}.modalContainer>*{background-color:#fff;border-radius:5px;cursor:default;flex:0 1 auto;padding:1rem;position:relative}.modal img{max-height:80vh!important}.cancelButton.svelte-1hhf5ym{color:#fff;cursor:pointer;font-size:2rem;position:absolute;right:1rem;top:1rem}.cancelButton.svelte-1hhf5ym:hover{color:var(--blue)}.nav.svelte-1kdpgko{border-radius:0 0 5px;display:none;margin:0;top:0}ul.navList.svelte-1kdpgko{list-style-type:none}ul.navList.svelte-1kdpgko ul:where(.svelte-1kdpgko){margin:.5rem 1rem 2rem}.navList.svelte-1kdpgko li:where(.svelte-1kdpgko){display:block;margin:0}.navItem.svelte-1kdpgko li:where(.svelte-1kdpgko):hover{color:var(--blue)}.pageId.svelte-1kdpgko{display:block;border-bottom:1px solid var(--grey);padding:0 .5rem;margin-bottom:1rem}@media (min-width: 60rem){.nav.svelte-1kdpgko{display:block}ul.navList.svelte-1kdpgko{text-align:left}.navList.svelte-1kdpgko li:where(.svelte-1kdpgko){display:block;margin:.5rem 0}}.container.svelte-teyund{width:100%;display:flex;flex-direction:column;position:relative}