ob-metaflow 2.10.7.4__py2.py3-none-any.whl → 2.10.9.2__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ob-metaflow might be problematic. Click here for more details.
- metaflow/cards.py +2 -0
- metaflow/decorators.py +1 -1
- metaflow/metaflow_config.py +4 -0
- metaflow/plugins/__init__.py +4 -0
- metaflow/plugins/airflow/airflow_cli.py +1 -1
- metaflow/plugins/argo/argo_workflows.py +5 -0
- metaflow/plugins/argo/argo_workflows_cli.py +1 -1
- metaflow/plugins/aws/aws_utils.py +1 -1
- metaflow/plugins/aws/batch/batch.py +4 -0
- metaflow/plugins/aws/batch/batch_cli.py +3 -0
- metaflow/plugins/aws/batch/batch_client.py +40 -11
- metaflow/plugins/aws/batch/batch_decorator.py +1 -0
- metaflow/plugins/aws/step_functions/step_functions.py +1 -0
- metaflow/plugins/aws/step_functions/step_functions_cli.py +1 -1
- metaflow/plugins/azure/azure_exceptions.py +1 -1
- metaflow/plugins/cards/card_cli.py +413 -28
- metaflow/plugins/cards/card_client.py +16 -7
- metaflow/plugins/cards/card_creator.py +228 -0
- metaflow/plugins/cards/card_datastore.py +124 -26
- metaflow/plugins/cards/card_decorator.py +40 -86
- metaflow/plugins/cards/card_modules/base.html +12 -0
- metaflow/plugins/cards/card_modules/basic.py +74 -8
- metaflow/plugins/cards/card_modules/bundle.css +1 -170
- metaflow/plugins/cards/card_modules/card.py +65 -0
- metaflow/plugins/cards/card_modules/components.py +446 -81
- metaflow/plugins/cards/card_modules/convert_to_native_type.py +9 -3
- metaflow/plugins/cards/card_modules/main.js +250 -21
- metaflow/plugins/cards/card_modules/test_cards.py +117 -0
- metaflow/plugins/cards/card_resolver.py +0 -2
- metaflow/plugins/cards/card_server.py +361 -0
- metaflow/plugins/cards/component_serializer.py +506 -42
- metaflow/plugins/cards/exception.py +20 -1
- metaflow/plugins/datastores/azure_storage.py +1 -2
- metaflow/plugins/datastores/gs_storage.py +1 -2
- metaflow/plugins/datastores/s3_storage.py +2 -1
- metaflow/plugins/datatools/s3/s3.py +24 -11
- metaflow/plugins/env_escape/client.py +2 -12
- metaflow/plugins/env_escape/client_modules.py +18 -14
- metaflow/plugins/env_escape/server.py +18 -11
- metaflow/plugins/env_escape/utils.py +12 -0
- metaflow/plugins/gcp/gs_exceptions.py +1 -1
- metaflow/plugins/gcp/gs_utils.py +1 -1
- metaflow/plugins/kubernetes/kubernetes.py +43 -6
- metaflow/plugins/kubernetes/kubernetes_cli.py +40 -1
- metaflow/plugins/kubernetes/kubernetes_decorator.py +73 -6
- metaflow/plugins/kubernetes/kubernetes_job.py +536 -161
- metaflow/plugins/pypi/conda_environment.py +5 -6
- metaflow/plugins/pypi/pip.py +2 -2
- metaflow/plugins/pypi/utils.py +15 -0
- metaflow/task.py +1 -0
- metaflow/version.py +1 -1
- {ob_metaflow-2.10.7.4.dist-info → ob_metaflow-2.10.9.2.dist-info}/METADATA +1 -1
- {ob_metaflow-2.10.7.4.dist-info → ob_metaflow-2.10.9.2.dist-info}/RECORD +57 -55
- {ob_metaflow-2.10.7.4.dist-info → ob_metaflow-2.10.9.2.dist-info}/LICENSE +0 -0
- {ob_metaflow-2.10.7.4.dist-info → ob_metaflow-2.10.9.2.dist-info}/WHEEL +0 -0
- {ob_metaflow-2.10.7.4.dist-info → ob_metaflow-2.10.9.2.dist-info}/entry_points.txt +0 -0
- {ob_metaflow-2.10.7.4.dist-info → ob_metaflow-2.10.9.2.dist-info}/top_level.txt +0 -0
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import os
|
|
3
|
-
import tempfile
|
|
4
|
-
import sys
|
|
5
|
-
import json
|
|
6
|
-
|
|
7
|
-
from typing import Dict, Any
|
|
8
|
-
|
|
9
|
-
from metaflow.decorators import StepDecorator, flow_decorators
|
|
1
|
+
from metaflow.decorators import StepDecorator
|
|
10
2
|
from metaflow.current import current
|
|
11
3
|
from metaflow.util import to_unicode
|
|
12
4
|
from .component_serializer import CardComponentCollector, get_card_class
|
|
5
|
+
from .card_creator import CardCreator
|
|
13
6
|
|
|
14
7
|
|
|
15
8
|
# from metaflow import get_metadata
|
|
@@ -17,6 +10,8 @@ import re
|
|
|
17
10
|
|
|
18
11
|
from .exception import CARD_ID_PATTERN, TYPE_CHECK_REGEX
|
|
19
12
|
|
|
13
|
+
ASYNC_TIMEOUT = 30
|
|
14
|
+
|
|
20
15
|
|
|
21
16
|
def warning_message(message, logger=None, ts=False):
|
|
22
17
|
msg = "[@card WARNING] %s" % message
|
|
@@ -51,6 +46,7 @@ class CardDecorator(StepDecorator):
|
|
|
51
46
|
"id": None,
|
|
52
47
|
"save_errors": True,
|
|
53
48
|
"customize": False,
|
|
49
|
+
"refresh_interval": 5,
|
|
54
50
|
}
|
|
55
51
|
allow_multiple = True
|
|
56
52
|
|
|
@@ -60,6 +56,8 @@ class CardDecorator(StepDecorator):
|
|
|
60
56
|
|
|
61
57
|
_called_once = {}
|
|
62
58
|
|
|
59
|
+
card_creator = None
|
|
60
|
+
|
|
63
61
|
def __init__(self, *args, **kwargs):
|
|
64
62
|
super(CardDecorator, self).__init__(*args, **kwargs)
|
|
65
63
|
self._task_datastore = None
|
|
@@ -70,6 +68,10 @@ class CardDecorator(StepDecorator):
|
|
|
70
68
|
self._card_uuid = None
|
|
71
69
|
self._user_set_card_id = None
|
|
72
70
|
|
|
71
|
+
@classmethod
|
|
72
|
+
def _set_card_creator(cls, card_creator):
|
|
73
|
+
cls.card_creator = card_creator
|
|
74
|
+
|
|
73
75
|
def _is_event_registered(self, evt_name):
|
|
74
76
|
return evt_name in self._called_once
|
|
75
77
|
|
|
@@ -89,7 +91,6 @@ class CardDecorator(StepDecorator):
|
|
|
89
91
|
def step_init(
|
|
90
92
|
self, flow, graph, step_name, decorators, environment, flow_datastore, logger
|
|
91
93
|
):
|
|
92
|
-
|
|
93
94
|
self._flow_datastore = flow_datastore
|
|
94
95
|
self._environment = environment
|
|
95
96
|
self._logger = logger
|
|
@@ -126,11 +127,18 @@ class CardDecorator(StepDecorator):
|
|
|
126
127
|
ubf_context,
|
|
127
128
|
inputs,
|
|
128
129
|
):
|
|
130
|
+
self._task_datastore = task_datastore
|
|
131
|
+
self._metadata = metadata
|
|
132
|
+
|
|
129
133
|
card_type = self.attributes["type"]
|
|
130
134
|
card_class = get_card_class(card_type)
|
|
135
|
+
|
|
136
|
+
self._is_runtime_card = False
|
|
131
137
|
if card_class is not None: # Card type was not found
|
|
132
138
|
if card_class.ALLOW_USER_COMPONENTS:
|
|
133
139
|
self._is_editable = True
|
|
140
|
+
self._is_runtime_card = card_class.RUNTIME_UPDATABLE
|
|
141
|
+
|
|
134
142
|
# We have a step counter to ensure that on calling the final card decorator's `task_pre_step`
|
|
135
143
|
# we call a `finalize` function in the `CardComponentCollector`.
|
|
136
144
|
# This can help ensure the behaviour of the `current.card` object is according to specification.
|
|
@@ -155,7 +163,11 @@ class CardDecorator(StepDecorator):
|
|
|
155
163
|
# we need to ensure that `current.card` has `CardComponentCollector` instantiated only once.
|
|
156
164
|
if not self._is_event_registered("pre-step"):
|
|
157
165
|
self._register_event("pre-step")
|
|
158
|
-
|
|
166
|
+
self._set_card_creator(CardCreator(self._create_top_level_args()))
|
|
167
|
+
|
|
168
|
+
current._update_env(
|
|
169
|
+
{"card": CardComponentCollector(self._logger, self.card_creator)}
|
|
170
|
+
)
|
|
159
171
|
|
|
160
172
|
# this line happens because of decospecs parsing.
|
|
161
173
|
customize = False
|
|
@@ -165,8 +177,12 @@ class CardDecorator(StepDecorator):
|
|
|
165
177
|
card_metadata = current.card._add_card(
|
|
166
178
|
self.attributes["type"],
|
|
167
179
|
self._user_set_card_id,
|
|
168
|
-
self.
|
|
169
|
-
|
|
180
|
+
self.attributes,
|
|
181
|
+
self.card_options,
|
|
182
|
+
editable=self._is_editable,
|
|
183
|
+
customize=customize,
|
|
184
|
+
runtime_card=self._is_runtime_card,
|
|
185
|
+
refresh_interval=self.attributes["refresh_interval"],
|
|
170
186
|
)
|
|
171
187
|
self._card_uuid = card_metadata["uuid"]
|
|
172
188
|
|
|
@@ -176,17 +192,20 @@ class CardDecorator(StepDecorator):
|
|
|
176
192
|
if self.step_counter == self.total_decos_on_step[step_name]:
|
|
177
193
|
current.card._finalize()
|
|
178
194
|
|
|
179
|
-
self._task_datastore = task_datastore
|
|
180
|
-
self._metadata = metadata
|
|
181
|
-
|
|
182
195
|
def task_finished(
|
|
183
196
|
self, step_name, flow, graph, is_task_ok, retry_count, max_user_code_retries
|
|
184
197
|
):
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
198
|
+
create_options = dict(
|
|
199
|
+
card_uuid=self._card_uuid,
|
|
200
|
+
user_set_card_id=self._user_set_card_id,
|
|
201
|
+
runtime_card=self._is_runtime_card,
|
|
202
|
+
decorator_attributes=self.attributes,
|
|
203
|
+
card_options=self.card_options,
|
|
204
|
+
logger=self._logger,
|
|
205
|
+
)
|
|
206
|
+
if is_task_ok:
|
|
207
|
+
self.card_creator.create(mode="render", final=True, **create_options)
|
|
208
|
+
self.card_creator.create(mode="refresh", final=True, **create_options)
|
|
190
209
|
|
|
191
210
|
@staticmethod
|
|
192
211
|
def _options(mapping):
|
|
@@ -200,7 +219,6 @@ class CardDecorator(StepDecorator):
|
|
|
200
219
|
yield to_unicode(value)
|
|
201
220
|
|
|
202
221
|
def _create_top_level_args(self):
|
|
203
|
-
|
|
204
222
|
top_level_options = {
|
|
205
223
|
"quiet": True,
|
|
206
224
|
"metadata": self._metadata.TYPE,
|
|
@@ -214,67 +232,3 @@ class CardDecorator(StepDecorator):
|
|
|
214
232
|
# the context of the main process
|
|
215
233
|
}
|
|
216
234
|
return list(self._options(top_level_options))
|
|
217
|
-
|
|
218
|
-
def _run_cards_subprocess(self, runspec, component_strings):
|
|
219
|
-
temp_file = None
|
|
220
|
-
if len(component_strings) > 0:
|
|
221
|
-
temp_file = tempfile.NamedTemporaryFile("w", suffix=".json")
|
|
222
|
-
json.dump(component_strings, temp_file)
|
|
223
|
-
temp_file.seek(0)
|
|
224
|
-
executable = sys.executable
|
|
225
|
-
cmd = [
|
|
226
|
-
executable,
|
|
227
|
-
sys.argv[0],
|
|
228
|
-
]
|
|
229
|
-
cmd += self._create_top_level_args() + [
|
|
230
|
-
"card",
|
|
231
|
-
"create",
|
|
232
|
-
runspec,
|
|
233
|
-
"--type",
|
|
234
|
-
self.attributes["type"],
|
|
235
|
-
# Add the options relating to card arguments.
|
|
236
|
-
# todo : add scope as a CLI arg for the create method.
|
|
237
|
-
]
|
|
238
|
-
if self.card_options is not None and len(self.card_options) > 0:
|
|
239
|
-
cmd += ["--options", json.dumps(self.card_options)]
|
|
240
|
-
# set the id argument.
|
|
241
|
-
|
|
242
|
-
if self.attributes["timeout"] is not None:
|
|
243
|
-
cmd += ["--timeout", str(self.attributes["timeout"])]
|
|
244
|
-
|
|
245
|
-
if self._user_set_card_id is not None:
|
|
246
|
-
cmd += ["--id", str(self._user_set_card_id)]
|
|
247
|
-
|
|
248
|
-
if self.attributes["save_errors"]:
|
|
249
|
-
cmd += ["--render-error-card"]
|
|
250
|
-
|
|
251
|
-
if temp_file is not None:
|
|
252
|
-
cmd += ["--component-file", temp_file.name]
|
|
253
|
-
|
|
254
|
-
response, fail = self._run_command(
|
|
255
|
-
cmd, os.environ, timeout=self.attributes["timeout"]
|
|
256
|
-
)
|
|
257
|
-
if fail:
|
|
258
|
-
resp = "" if response is None else response.decode("utf-8")
|
|
259
|
-
self._logger(
|
|
260
|
-
"Card render failed with error : \n\n %s" % resp,
|
|
261
|
-
timestamp=False,
|
|
262
|
-
bad=True,
|
|
263
|
-
)
|
|
264
|
-
|
|
265
|
-
def _run_command(self, cmd, env, timeout=None):
|
|
266
|
-
fail = False
|
|
267
|
-
timeout_args = {}
|
|
268
|
-
if timeout is not None:
|
|
269
|
-
timeout_args = dict(timeout=int(timeout) + 10)
|
|
270
|
-
try:
|
|
271
|
-
rep = subprocess.check_output(
|
|
272
|
-
cmd, env=env, stderr=subprocess.STDOUT, **timeout_args
|
|
273
|
-
)
|
|
274
|
-
except subprocess.CalledProcessError as e:
|
|
275
|
-
rep = e.output
|
|
276
|
-
fail = True
|
|
277
|
-
except subprocess.TimeoutExpired as e:
|
|
278
|
-
rep = e.output
|
|
279
|
-
fail = True
|
|
280
|
-
return rep, fail
|
|
@@ -18,16 +18,28 @@
|
|
|
18
18
|
<body>
|
|
19
19
|
<div class="card_app"></div>
|
|
20
20
|
<script>
|
|
21
|
+
var METAFLOW_RELOAD_TOKEN = "[METAFLOW_RELOAD_TOKEN]"
|
|
21
22
|
var mfCardDataId = "{{{card_data_id}}}";
|
|
22
23
|
|
|
23
24
|
if (!window.__MF_DATA__) {
|
|
24
25
|
window.__MF_DATA__ = {};
|
|
25
26
|
}
|
|
26
27
|
window.__MF_DATA__["{{{card_data_id}}}"] = "{{{task_data}}}"
|
|
28
|
+
|
|
27
29
|
</script>
|
|
28
30
|
<script>
|
|
29
31
|
{{{javascript}}}
|
|
30
32
|
</script>
|
|
33
|
+
{{#RENDER_COMPLETE}}
|
|
34
|
+
<script>
|
|
35
|
+
window.metaflow_card_update = undefined;
|
|
36
|
+
</script>
|
|
37
|
+
{{/RENDER_COMPLETE}}
|
|
38
|
+
{{^RENDER_COMPLETE}}
|
|
39
|
+
<script>
|
|
40
|
+
// This Card was Designed to be Realtime Updatable
|
|
41
|
+
</script>
|
|
42
|
+
{{/RENDER_COMPLETE}}
|
|
31
43
|
</body>
|
|
32
44
|
|
|
33
45
|
</html>
|
|
@@ -146,6 +146,8 @@ class ImageComponent(DefaultComponent):
|
|
|
146
146
|
label=self._label,
|
|
147
147
|
)
|
|
148
148
|
datadict.update(img_dict)
|
|
149
|
+
if self.component_id is not None:
|
|
150
|
+
datadict["id"] = self.component_id
|
|
149
151
|
return datadict
|
|
150
152
|
|
|
151
153
|
|
|
@@ -194,6 +196,8 @@ class TableComponent(DefaultComponent):
|
|
|
194
196
|
datadict["columns"] = self._headers
|
|
195
197
|
datadict["data"] = self._data
|
|
196
198
|
datadict["vertical"] = self._vertical
|
|
199
|
+
if self.component_id is not None:
|
|
200
|
+
datadict["id"] = self.component_id
|
|
197
201
|
return datadict
|
|
198
202
|
|
|
199
203
|
|
|
@@ -295,6 +299,8 @@ class ArtifactsComponent(DefaultComponent):
|
|
|
295
299
|
def render(self):
|
|
296
300
|
datadict = super().render()
|
|
297
301
|
datadict["data"] = self._data
|
|
302
|
+
if self.component_id is not None:
|
|
303
|
+
datadict["id"] = self.component_id
|
|
298
304
|
return datadict
|
|
299
305
|
|
|
300
306
|
|
|
@@ -308,6 +314,8 @@ class MarkdownComponent(DefaultComponent):
|
|
|
308
314
|
def render(self):
|
|
309
315
|
datadict = super().render()
|
|
310
316
|
datadict["source"] = self._text
|
|
317
|
+
if self.component_id is not None:
|
|
318
|
+
datadict["id"] = self.component_id
|
|
311
319
|
return datadict
|
|
312
320
|
|
|
313
321
|
|
|
@@ -319,7 +327,13 @@ class TaskInfoComponent(MetaflowCardComponent):
|
|
|
319
327
|
"""
|
|
320
328
|
|
|
321
329
|
def __init__(
|
|
322
|
-
self,
|
|
330
|
+
self,
|
|
331
|
+
task,
|
|
332
|
+
page_title="Task Info",
|
|
333
|
+
only_repr=True,
|
|
334
|
+
graph=None,
|
|
335
|
+
components=[],
|
|
336
|
+
runtime=False,
|
|
323
337
|
):
|
|
324
338
|
self._task = task
|
|
325
339
|
self._only_repr = only_repr
|
|
@@ -328,6 +342,7 @@ class TaskInfoComponent(MetaflowCardComponent):
|
|
|
328
342
|
self._page_title = page_title
|
|
329
343
|
self.final_component = None
|
|
330
344
|
self.page_component = None
|
|
345
|
+
self.runtime = runtime
|
|
331
346
|
|
|
332
347
|
def render(self):
|
|
333
348
|
"""
|
|
@@ -340,7 +355,8 @@ class TaskInfoComponent(MetaflowCardComponent):
|
|
|
340
355
|
self._task, graph=self._graph
|
|
341
356
|
)
|
|
342
357
|
# ignore the name as an artifact
|
|
343
|
-
|
|
358
|
+
if "name" in task_data_dict["data"]:
|
|
359
|
+
del task_data_dict["data"]["name"]
|
|
344
360
|
|
|
345
361
|
_metadata = dict(version=1, template="defaultCardTemplate")
|
|
346
362
|
# try to parse out metaflow version from tags, but let it go if unset
|
|
@@ -370,11 +386,12 @@ class TaskInfoComponent(MetaflowCardComponent):
|
|
|
370
386
|
"Task Created On": task_data_dict["created_at"],
|
|
371
387
|
"Task Finished On": task_data_dict["finished_at"],
|
|
372
388
|
# Remove Microseconds from timedelta
|
|
373
|
-
"Task Duration": str(self._task.finished_at - self._task.created_at).split(
|
|
374
|
-
"."
|
|
375
|
-
)[0],
|
|
376
389
|
"Tags": ", ".join(tags),
|
|
377
390
|
}
|
|
391
|
+
if not self.runtime:
|
|
392
|
+
task_metadata_dict["Task Duration"] = str(
|
|
393
|
+
self._task.finished_at - self._task.created_at
|
|
394
|
+
).split(".")[0]
|
|
378
395
|
if len(user_info) > 0:
|
|
379
396
|
task_metadata_dict["User"] = user_info[0].split("user:")[1]
|
|
380
397
|
|
|
@@ -434,8 +451,12 @@ class TaskInfoComponent(MetaflowCardComponent):
|
|
|
434
451
|
p.id for p in self._task.parent.parent["_parameters"].task if p.id != "name"
|
|
435
452
|
]
|
|
436
453
|
if len(param_ids) > 0:
|
|
454
|
+
# Extract parameter from the Parameter Task. That is less brittle.
|
|
455
|
+
parameter_data = TaskToDict(
|
|
456
|
+
only_repr=self._only_repr, runtime=self.runtime
|
|
457
|
+
)(self._task.parent.parent["_parameters"].task, graph=self._graph)
|
|
437
458
|
param_component = ArtifactsComponent(
|
|
438
|
-
data=[
|
|
459
|
+
data=[parameter_data["data"][pid] for pid in param_ids]
|
|
439
460
|
)
|
|
440
461
|
else:
|
|
441
462
|
param_component = TitleComponent(text="No Parameters")
|
|
@@ -580,6 +601,10 @@ class DefaultCard(MetaflowCard):
|
|
|
580
601
|
|
|
581
602
|
ALLOW_USER_COMPONENTS = True
|
|
582
603
|
|
|
604
|
+
RUNTIME_UPDATABLE = True
|
|
605
|
+
|
|
606
|
+
RELOAD_POLICY = MetaflowCard.RELOAD_POLICY_ONCHANGE
|
|
607
|
+
|
|
583
608
|
type = "default"
|
|
584
609
|
|
|
585
610
|
def __init__(self, options=dict(only_repr=True), components=[], graph=None):
|
|
@@ -589,7 +614,7 @@ class DefaultCard(MetaflowCard):
|
|
|
589
614
|
self._only_repr = options["only_repr"]
|
|
590
615
|
self._components = components
|
|
591
616
|
|
|
592
|
-
def render(self, task):
|
|
617
|
+
def render(self, task, runtime=False):
|
|
593
618
|
RENDER_TEMPLATE = read_file(RENDER_TEMPLATE_PATH)
|
|
594
619
|
JS_DATA = read_file(JS_PATH)
|
|
595
620
|
CSS_DATA = read_file(CSS_PATH)
|
|
@@ -598,6 +623,7 @@ class DefaultCard(MetaflowCard):
|
|
|
598
623
|
only_repr=self._only_repr,
|
|
599
624
|
graph=self._graph,
|
|
600
625
|
components=self._components,
|
|
626
|
+
runtime=runtime,
|
|
601
627
|
).render()
|
|
602
628
|
pt = self._get_mustache()
|
|
603
629
|
data_dict = dict(
|
|
@@ -608,14 +634,36 @@ class DefaultCard(MetaflowCard):
|
|
|
608
634
|
title=task.pathspec,
|
|
609
635
|
css=CSS_DATA,
|
|
610
636
|
card_data_id=uuid.uuid4(),
|
|
637
|
+
RENDER_COMPLETE=not runtime,
|
|
611
638
|
)
|
|
612
639
|
return pt.render(RENDER_TEMPLATE, data_dict)
|
|
613
640
|
|
|
641
|
+
def render_runtime(self, task, data):
|
|
642
|
+
return self.render(task, runtime=True)
|
|
643
|
+
|
|
644
|
+
def refresh(self, task, data):
|
|
645
|
+
return data["components"]
|
|
646
|
+
|
|
647
|
+
def reload_content_token(self, task, data):
|
|
648
|
+
"""
|
|
649
|
+
The reload token will change when the component array has changed in the Metaflow card.
|
|
650
|
+
The change in the component array is signified by the change in the component_update_ts.
|
|
651
|
+
"""
|
|
652
|
+
if task.finished:
|
|
653
|
+
return "final"
|
|
654
|
+
# `component_update_ts` will never be None. It is set to a default value when the `ComponentStore` is instantiated
|
|
655
|
+
# And it is updated when components added / removed / changed from the `ComponentStore`.
|
|
656
|
+
return "runtime-%s" % (str(data["component_update_ts"]))
|
|
657
|
+
|
|
614
658
|
|
|
615
659
|
class BlankCard(MetaflowCard):
|
|
616
660
|
|
|
617
661
|
ALLOW_USER_COMPONENTS = True
|
|
618
662
|
|
|
663
|
+
RUNTIME_UPDATABLE = True
|
|
664
|
+
|
|
665
|
+
RELOAD_POLICY = MetaflowCard.RELOAD_POLICY_ONCHANGE
|
|
666
|
+
|
|
619
667
|
type = "blank"
|
|
620
668
|
|
|
621
669
|
def __init__(self, options=dict(title=""), components=[], graph=None):
|
|
@@ -625,7 +673,7 @@ class BlankCard(MetaflowCard):
|
|
|
625
673
|
self._title = options["title"]
|
|
626
674
|
self._components = components
|
|
627
675
|
|
|
628
|
-
def render(self, task, components=[]):
|
|
676
|
+
def render(self, task, components=[], runtime=False):
|
|
629
677
|
RENDER_TEMPLATE = read_file(RENDER_TEMPLATE_PATH)
|
|
630
678
|
JS_DATA = read_file(JS_PATH)
|
|
631
679
|
CSS_DATA = read_file(CSS_PATH)
|
|
@@ -650,9 +698,27 @@ class BlankCard(MetaflowCard):
|
|
|
650
698
|
title=task.pathspec,
|
|
651
699
|
css=CSS_DATA,
|
|
652
700
|
card_data_id=uuid.uuid4(),
|
|
701
|
+
RENDER_COMPLETE=not runtime,
|
|
653
702
|
)
|
|
654
703
|
return pt.render(RENDER_TEMPLATE, data_dict)
|
|
655
704
|
|
|
705
|
+
def render_runtime(self, task, data):
|
|
706
|
+
return self.render(task, runtime=True)
|
|
707
|
+
|
|
708
|
+
def refresh(self, task, data):
|
|
709
|
+
return data["components"]
|
|
710
|
+
|
|
711
|
+
def reload_content_token(self, task, data):
|
|
712
|
+
"""
|
|
713
|
+
The reload token will change when the component array has changed in the Metaflow card.
|
|
714
|
+
The change in the component array is signified by the change in the component_update_ts.
|
|
715
|
+
"""
|
|
716
|
+
if task.finished:
|
|
717
|
+
return "final"
|
|
718
|
+
# `component_update_ts` will never be None. It is set to a default value when the `ComponentStore` is instantiated
|
|
719
|
+
# And it is updated when components added / removed / changed from the `ComponentStore`.
|
|
720
|
+
return "runtime-%s" % (str(data["component_update_ts"]))
|
|
721
|
+
|
|
656
722
|
|
|
657
723
|
class TaskSpecCard(MetaflowCard):
|
|
658
724
|
type = "taskspec_card"
|
|
@@ -1,170 +1 @@
|
|
|
1
|
-
.container.svelte-teyund{width:100%;display:flex;flex-direction:column;position:relative}.mf-card * {
|
|
2
|
-
box-sizing: border-box;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.mf-card {
|
|
6
|
-
background: var(--bg);
|
|
7
|
-
color: var(--black);
|
|
8
|
-
font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
|
9
|
-
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
10
|
-
sans-serif;
|
|
11
|
-
font-size: 14px;
|
|
12
|
-
font-weight: 400;
|
|
13
|
-
line-height: 1.5;
|
|
14
|
-
text-size-adjust: 100%;
|
|
15
|
-
margin: 0;
|
|
16
|
-
min-height: 100vh;
|
|
17
|
-
overflow-y: visible;
|
|
18
|
-
padding: 0;
|
|
19
|
-
text-align: left;
|
|
20
|
-
-moz-osx-font-smoothing: grayscale;
|
|
21
|
-
-webkit-font-smoothing: antialiased;
|
|
22
|
-
width: 100%;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.embed .mf-card {
|
|
26
|
-
min-height: var(--embed-card-min-height);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.mf-card :is(.mono, code.mono, pre.mono) {
|
|
30
|
-
font-family: var(--mono-font);
|
|
31
|
-
font-weight: lighter;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.mf-card :is(table, th, td) {
|
|
35
|
-
border-spacing: 1px;
|
|
36
|
-
text-align: center;
|
|
37
|
-
color: var(--black);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.mf-card table {
|
|
41
|
-
position: relative;
|
|
42
|
-
min-width: 100%;
|
|
43
|
-
table-layout: inherit !important;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.mf-card td {
|
|
47
|
-
padding: 0.66rem 1.25rem;
|
|
48
|
-
background: var(--lt-lt-grey);
|
|
49
|
-
border: none;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.mf-card th {
|
|
53
|
-
border: none;
|
|
54
|
-
color: var(--dk-grey);
|
|
55
|
-
font-weight: normal;
|
|
56
|
-
padding: 0.5rem;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.mf-card :is(h1, h2, h3, h4, h5) {
|
|
60
|
-
font-weight: 700;
|
|
61
|
-
margin: 0.5rem 0;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.mf-card ul {
|
|
65
|
-
margin: 0;
|
|
66
|
-
padding: 0;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.mf-card p {
|
|
70
|
-
margin: 0 0 1rem;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.mf-card p:last-of-type {
|
|
74
|
-
margin: 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.mf-card button {
|
|
78
|
-
font-size: 1rem;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.mf-card .textButton {
|
|
82
|
-
cursor: pointer;
|
|
83
|
-
text-align: left;
|
|
84
|
-
background: none;
|
|
85
|
-
border: 1px solid transparent;
|
|
86
|
-
outline: none;
|
|
87
|
-
padding: 0;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.mf-card :is(button.textButton:focus, a:focus, button.textButton:active) {
|
|
91
|
-
border: 1px dashed var(--grey);
|
|
92
|
-
background: transparent;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
.mf-card button.textButton:hover {
|
|
96
|
-
color: var(--blue);
|
|
97
|
-
text-decoration: none;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.mf-card :is(:not(pre) > code[class*="language-"], pre[class*="language-"]) {
|
|
101
|
-
background: transparent !important;
|
|
102
|
-
text-shadow: none;
|
|
103
|
-
user-select: auto;
|
|
104
|
-
}
|
|
105
|
-
/* PrismJS 1.25.0
|
|
106
|
-
https://prismjs.com/download.html#themes=prism&languages=clike+python */
|
|
107
|
-
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:hsla(0,0%,100%,.5)}.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}
|
|
108
|
-
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap");
|
|
109
|
-
|
|
110
|
-
:root {
|
|
111
|
-
--bg: #ffffff;
|
|
112
|
-
--black: #333;
|
|
113
|
-
--blue: #0c66de;
|
|
114
|
-
--dk-grey: #767676;
|
|
115
|
-
--dk-primary: #ef863b;
|
|
116
|
-
--dk-secondary: #13172d;
|
|
117
|
-
--dk-tertiary: #0f426e;
|
|
118
|
-
--error: #cf483e;
|
|
119
|
-
--grey: rgba(0, 0, 0, 0.125);
|
|
120
|
-
--highlight: #f8d9d8;
|
|
121
|
-
--lt-blue: #4fa7ff;
|
|
122
|
-
--lt-grey: #f3f3f3;
|
|
123
|
-
--lt-lt-grey: #f9f9f9;
|
|
124
|
-
--lt-primary: #ffcb8b;
|
|
125
|
-
--lt-secondary: #434d81;
|
|
126
|
-
--lt-tertiary: #4189c9;
|
|
127
|
-
--primary: #faab4a;
|
|
128
|
-
--quadrary: #f8d9d8;
|
|
129
|
-
--secondary: #2e3454;
|
|
130
|
-
--tertiary: #2a679d;
|
|
131
|
-
--white: #ffffff;
|
|
132
|
-
|
|
133
|
-
--component-spacer: 3rem;
|
|
134
|
-
--aside-width: 20rem;
|
|
135
|
-
--embed-card-min-height: 12rem;
|
|
136
|
-
|
|
137
|
-
--mono-font: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
|
|
138
|
-
"Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
|
|
139
|
-
"Fira Mono", "Droid Sans Mono", "Courier New", monospace;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
html, body {
|
|
143
|
-
margin: 0;
|
|
144
|
-
min-height: 100vh;
|
|
145
|
-
overflow-y: visible;
|
|
146
|
-
padding: 0;
|
|
147
|
-
width: 100%;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.card_app {
|
|
151
|
-
width: 100%;
|
|
152
|
-
min-height: 100vh;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
.embed .card_app {
|
|
156
|
-
min-height: var(--embed-card-min-height);
|
|
157
|
-
}
|
|
158
|
-
.mainContainer.svelte-13ho8jo{max-width:110rem}main.svelte-13ho8jo{flex:0 1 auto;max-width:100rem;padding:1.5rem}@media(min-width: 60rem){main.svelte-13ho8jo{margin-left:var(--aside-width)}}.embed main{margin:0 auto}.modal.svelte-1hhf5ym{align-items:center;background:rgba(0, 0, 0, 0.5);bottom:0;cursor:pointer;display:flex;height:100%;justify-content:center;left:0;overflow:hidden;position:fixed;right:0;top:0;width:100%;z-index:100}.modalContainer > *{background-color:white;border-radius:5px;cursor:default;flex:0 1 auto;padding:1rem;position:relative}.modal img{max-height:80vh !important}.cancelButton.svelte-1hhf5ym{color:white;cursor:pointer;font-size:2rem;position:absolute;right:1rem;top:1rem}.cancelButton.svelte-1hhf5ym:hover{color:var(--blue)}.nav.svelte-1kdpgko.svelte-1kdpgko{border-radius:0 0 5px 0;display:none;margin:0;top:0}ul.navList.svelte-1kdpgko.svelte-1kdpgko{list-style-type:none}ul.navList.svelte-1kdpgko ul.svelte-1kdpgko{margin:0.5rem 1rem 2rem}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:0}.navItem.svelte-1kdpgko li.svelte-1kdpgko:hover{color:var(--blue)}.pageId.svelte-1kdpgko.svelte-1kdpgko{display:block;border-bottom:1px solid var(--grey);padding:0 0.5rem;margin-bottom:1rem}@media(min-width: 60rem){.nav.svelte-1kdpgko.svelte-1kdpgko{display:block}ul.navList.svelte-1kdpgko.svelte-1kdpgko{text-align:left}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:0.5rem 0}}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}.container.svelte-ubs992{width:100%;overflow:auto}table.svelte-ubs992{width:100%}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:bold;margin:0.5rem 0}.description.svelte-1x96yvr{font-size:0.9rem;font-style:italic;text-align:center;margin:0.5rem 0}.log.svelte-1jhmsu{background:var(--lt-grey) !important;font-size:0.9rem;padding:2rem}.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}}.subtitle.svelte-lu9pnn{font-size:1rem;text-align:left}.page.svelte-v7ihqd:last-of-type{margin-bottom:var(--component-spacer)}.page:last-of-type section:last-of-type hr{display:none}.title.svelte-117s0ws{text-align:left}.idCell.svelte-pt8vzv{font-weight:bold;text-align:right;background:var(--lt-grey);width:12%}.codeCell.svelte-pt8vzv{text-align:left;user-select:all}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)}.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)}:root {
|
|
159
|
-
--dag-border: #282828;
|
|
160
|
-
--dag-bg-static: var(--lt-grey);
|
|
161
|
-
--dag-bg-success: #a5d46a;
|
|
162
|
-
--dag-bg-running: #ffdf80;
|
|
163
|
-
--dag-bg-error: #ffa080;
|
|
164
|
-
--dag-connector: #cccccc;
|
|
165
|
-
--dag-gap: 5rem;
|
|
166
|
-
--dag-step-height: 6.25rem;
|
|
167
|
-
--dag-step-width: 11.25rem;
|
|
168
|
-
--dag-selected: #ffd700;
|
|
169
|
-
}
|
|
170
|
-
.wrapper.svelte-117ceti.svelte-117ceti{position:relative;z-index:1}.step.svelte-117ceti.svelte-117ceti{font-size:0.75rem;padding:0.5rem;color:var(--dk-grey)}.rectangle.svelte-117ceti.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.svelte-117ceti{background-color:var(--dag-bg-error)}.rectangle.success.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-success)}.rectangle.running.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-running)}.level.svelte-117ceti.svelte-117ceti{z-index:-1;filter:contrast(0.5);position:absolute}.inner.svelte-117ceti.svelte-117ceti{position:relative;height:100%;width:100%}.name.svelte-117ceti.svelte-117ceti{font-weight:bold;overflow:hidden;text-overflow:ellipsis;display:block}.description.svelte-117ceti.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.svelte-117ceti{cursor:help}.current.svelte-117ceti .rectangle.svelte-117ceti{box-shadow:0 0 10px var(--dag-selected)}.levelstoshow.svelte-117ceti.svelte-117ceti{position:absolute;bottom:100%;right:0;font-size:0.75rem;font-weight:100;text-align:right}.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:0.5rem;--strokeColor:var(--dag-connector);--borderRadius:1.25rem;box-sizing:border-box}.straightLine.svelte-1hyaq5f{position:absolute;top:0;bottom:0;left:0;right: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)}
|
|
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;top:0;bottom:0;left:0;right: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.svelte-117ceti{position:relative;z-index:1}.step.svelte-117ceti.svelte-117ceti{font-size:.75rem;padding:.5rem;color:var(--dk-grey)}.rectangle.svelte-117ceti.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.svelte-117ceti{background-color:var(--dag-bg-error)}.rectangle.success.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-success)}.rectangle.running.svelte-117ceti.svelte-117ceti{background-color:var(--dag-bg-running)}.level.svelte-117ceti.svelte-117ceti{z-index:-1;filter:contrast(.5);position:absolute}.inner.svelte-117ceti.svelte-117ceti{position:relative;height:100%;width:100%}.name.svelte-117ceti.svelte-117ceti{font-weight:700;overflow:hidden;text-overflow:ellipsis;display:block}.description.svelte-117ceti.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.svelte-117ceti{cursor:help}.current.svelte-117ceti .rectangle.svelte-117ceti{box-shadow:0 0 10px var(--dag-selected)}.levelstoshow.svelte-117ceti.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;bottom:0;cursor:pointer;display:flex;height:100%;justify-content:center;left:0;overflow:hidden;position:fixed;right:0;top:0;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.svelte-1kdpgko{border-radius:0 0 5px;display:none;margin:0;top:0}ul.navList.svelte-1kdpgko.svelte-1kdpgko{list-style-type:none}ul.navList.svelte-1kdpgko ul.svelte-1kdpgko{margin:.5rem 1rem 2rem}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:0}.navItem.svelte-1kdpgko li.svelte-1kdpgko:hover{color:var(--blue)}.pageId.svelte-1kdpgko.svelte-1kdpgko{display:block;border-bottom:1px solid var(--grey);padding:0 .5rem;margin-bottom:1rem}@media (min-width: 60rem){.nav.svelte-1kdpgko.svelte-1kdpgko{display:block}ul.navList.svelte-1kdpgko.svelte-1kdpgko{text-align:left}.navList.svelte-1kdpgko li.svelte-1kdpgko{display:block;margin:.5rem 0}}.container.svelte-teyund{width:100%;display:flex;flex-direction:column;position:relative}
|