metaflow-checkpoint 0.0.1__tar.gz
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.
- metaflow_checkpoint-0.0.1/PKG-INFO +11 -0
- metaflow_checkpoint-0.0.1/README.md +3 -0
- metaflow_checkpoint-0.0.1/metaflow_checkpoint.egg-info/PKG-INFO +11 -0
- metaflow_checkpoint-0.0.1/metaflow_checkpoint.egg-info/SOURCES.txt +49 -0
- metaflow_checkpoint-0.0.1/metaflow_checkpoint.egg-info/dependency_links.txt +1 -0
- metaflow_checkpoint-0.0.1/metaflow_checkpoint.egg-info/top_level.txt +1 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/__init__.py +24 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/__init__.py +2 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/__init__.py +3 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/async_cards.py +135 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/deco_injection_mixin.py +70 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/extra_components.py +250 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/__init__.py +0 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/__init__.py +1 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/checkpoint_lister.py +411 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/diskspace_usage_card.py +192 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/lineage_card.py +103 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/checkpoint_storage.py +542 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/constants.py +10 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/constructors.py +99 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/core.py +433 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/decorator.py +522 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/final_api.py +206 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/lineage.py +67 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/task_utils.py +56 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/__init__.py +2 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/core.py +351 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/storage_injections.py +60 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/task_utils.py +69 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/utils.py +35 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastructures.py +384 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/exceptions.py +27 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/hf_hub/decorator.py +152 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/__init__.py +0 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/cards/model_card.py +268 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/core.py +301 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/decorator.py +171 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/model_storage.py +210 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/constants.py +1 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/disk_usage.py +139 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/flowspec_utils.py +87 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/general.py +109 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/identity_utils.py +145 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/__init__.py +5 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/base.py +14 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/tar.py +37 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/tar_utils.py +161 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/toplevel/__init__.py +1 -0
- metaflow_checkpoint-0.0.1/metaflow_extensions/obcheckpoint/toplevel/toplevel.py +14 -0
- metaflow_checkpoint-0.0.1/setup.cfg +4 -0
- metaflow_checkpoint-0.0.1/setup.py +24 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: metaflow-checkpoint
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: An EXPERIMENTAL checkpoint decorator for Metaflow
|
|
5
|
+
Author: Valay Dave
|
|
6
|
+
Author-email: help@outerbounds.com
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# Metaflow Checkpoint
|
|
10
|
+
|
|
11
|
+
TODO : Write readme
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: metaflow-checkpoint
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: An EXPERIMENTAL checkpoint decorator for Metaflow
|
|
5
|
+
Author: Valay Dave
|
|
6
|
+
Author-email: help@outerbounds.com
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# Metaflow Checkpoint
|
|
10
|
+
|
|
11
|
+
TODO : Write readme
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
metaflow_checkpoint.egg-info/PKG-INFO
|
|
4
|
+
metaflow_checkpoint.egg-info/SOURCES.txt
|
|
5
|
+
metaflow_checkpoint.egg-info/dependency_links.txt
|
|
6
|
+
metaflow_checkpoint.egg-info/top_level.txt
|
|
7
|
+
metaflow_extensions/obcheckpoint/plugins/__init__.py
|
|
8
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/__init__.py
|
|
9
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastructures.py
|
|
10
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/exceptions.py
|
|
11
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/__init__.py
|
|
12
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/async_cards.py
|
|
13
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/deco_injection_mixin.py
|
|
14
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/card_utils/extra_components.py
|
|
15
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/__init__.py
|
|
16
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/checkpoint_storage.py
|
|
17
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/constants.py
|
|
18
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/constructors.py
|
|
19
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/core.py
|
|
20
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/decorator.py
|
|
21
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/final_api.py
|
|
22
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/lineage.py
|
|
23
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/task_utils.py
|
|
24
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/__init__.py
|
|
25
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/checkpoint_lister.py
|
|
26
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/diskspace_usage_card.py
|
|
27
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/checkpoints/cards/lineage_card.py
|
|
28
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/__init__.py
|
|
29
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/core.py
|
|
30
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/storage_injections.py
|
|
31
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/task_utils.py
|
|
32
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/datastore/utils.py
|
|
33
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/hf_hub/decorator.py
|
|
34
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/__init__.py
|
|
35
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/core.py
|
|
36
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/decorator.py
|
|
37
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/model_storage.py
|
|
38
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/modeling_utils/cards/model_card.py
|
|
39
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/constants.py
|
|
40
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/disk_usage.py
|
|
41
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/flowspec_utils.py
|
|
42
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/general.py
|
|
43
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/identity_utils.py
|
|
44
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/tar_utils.py
|
|
45
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/__init__.py
|
|
46
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/base.py
|
|
47
|
+
metaflow_extensions/obcheckpoint/plugins/machine_learning_utilities/utils/serialization_handler/tar.py
|
|
48
|
+
metaflow_extensions/obcheckpoint/toplevel/__init__.py
|
|
49
|
+
metaflow_extensions/obcheckpoint/toplevel/toplevel.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
metaflow_extensions
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
STEP_DECORATORS_DESC = [
|
|
2
|
+
(
|
|
3
|
+
"checkpoint",
|
|
4
|
+
".machine_learning_utilities.checkpoints.decorator.CheckpointDecorator",
|
|
5
|
+
),
|
|
6
|
+
(
|
|
7
|
+
"model",
|
|
8
|
+
".machine_learning_utilities.modeling_utils.decorator.ModelDecorator",
|
|
9
|
+
),
|
|
10
|
+
(
|
|
11
|
+
"huggingface_hub",
|
|
12
|
+
".machine_learning_utilities.hf_hub.decorator.HuggingfaceHubDecorator",
|
|
13
|
+
),
|
|
14
|
+
(
|
|
15
|
+
"disk_profiler",
|
|
16
|
+
".machine_learning_utilities.checkpoints.cards.diskspace_usage_card.DiskUsageProfilerDecorator",
|
|
17
|
+
),
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
###
|
|
21
|
+
# CONFIGURE: Similar to datatools, you can make visible under metaflow.plugins.* other
|
|
22
|
+
# submodules not referenced in this file
|
|
23
|
+
###
|
|
24
|
+
__mf_promote_submodules__ = []
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
from metaflow.metaflow_current import current
|
|
2
|
+
import json
|
|
3
|
+
from threading import Thread, Event
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class InfoCollectorThread(Thread):
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
interval=1,
|
|
11
|
+
file_name=None,
|
|
12
|
+
):
|
|
13
|
+
super().__init__()
|
|
14
|
+
self._exit_event = Event()
|
|
15
|
+
self._interval = interval
|
|
16
|
+
assert file_name is not None, "file_name must be provided"
|
|
17
|
+
self._file_name = file_name
|
|
18
|
+
self.daemon = True
|
|
19
|
+
self._data = {}
|
|
20
|
+
self._has_errored = False
|
|
21
|
+
self._current_error = None
|
|
22
|
+
|
|
23
|
+
def read(self):
|
|
24
|
+
return self._data
|
|
25
|
+
|
|
26
|
+
def has_errored(self):
|
|
27
|
+
return self._has_errored
|
|
28
|
+
|
|
29
|
+
def get_error(self):
|
|
30
|
+
return self._current_error
|
|
31
|
+
|
|
32
|
+
def _safely_load(self):
|
|
33
|
+
try:
|
|
34
|
+
with open(self._file_name, "r") as f:
|
|
35
|
+
return json.load(f), None
|
|
36
|
+
except FileNotFoundError as e:
|
|
37
|
+
return {}, e
|
|
38
|
+
except json.JSONDecodeError as e:
|
|
39
|
+
return {}, e
|
|
40
|
+
except Exception as e:
|
|
41
|
+
return {}, e
|
|
42
|
+
|
|
43
|
+
def run(self):
|
|
44
|
+
while self._exit_event.is_set() is False:
|
|
45
|
+
data, self._current_error = self._safely_load()
|
|
46
|
+
if not self._current_error:
|
|
47
|
+
self._data = data
|
|
48
|
+
self._has_errored = True if self._current_error else False
|
|
49
|
+
time.sleep(self._interval)
|
|
50
|
+
|
|
51
|
+
def stop(self):
|
|
52
|
+
self._exit_event.set()
|
|
53
|
+
self.join()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class CardRefresher:
|
|
57
|
+
|
|
58
|
+
CARD_ID = None
|
|
59
|
+
|
|
60
|
+
REFRESHABLE = True
|
|
61
|
+
|
|
62
|
+
def on_startup(self, current_card):
|
|
63
|
+
raise NotImplementedError("make_card method must be implemented")
|
|
64
|
+
|
|
65
|
+
def on_error(self, current_card, error_message):
|
|
66
|
+
raise NotImplementedError("error_card method must be implemented")
|
|
67
|
+
|
|
68
|
+
def on_update(self, current_card, data_object):
|
|
69
|
+
raise NotImplementedError("update_card method must be implemented")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class CardUpdaterThread(Thread):
|
|
73
|
+
def __init__(
|
|
74
|
+
self,
|
|
75
|
+
card_refresher: CardRefresher,
|
|
76
|
+
interval=1,
|
|
77
|
+
file_name=None,
|
|
78
|
+
collector_thread: InfoCollectorThread = None,
|
|
79
|
+
):
|
|
80
|
+
super().__init__()
|
|
81
|
+
self._exit_event = Event()
|
|
82
|
+
self._interval = interval
|
|
83
|
+
self._refresher = card_refresher
|
|
84
|
+
self._file_name = file_name
|
|
85
|
+
self._collector_thread = collector_thread
|
|
86
|
+
self.daemon = True
|
|
87
|
+
|
|
88
|
+
def run(self):
|
|
89
|
+
if self._refresher.CARD_ID is None:
|
|
90
|
+
raise ValueError("CARD_ID must be defined")
|
|
91
|
+
current_card = current.card[self._refresher.CARD_ID]
|
|
92
|
+
self._refresher.on_startup(current_card)
|
|
93
|
+
while self._exit_event.is_set() is False:
|
|
94
|
+
data = self._collector_thread.read()
|
|
95
|
+
if self._collector_thread.has_errored():
|
|
96
|
+
self._refresher.on_error(
|
|
97
|
+
current_card, self._collector_thread.get_error()
|
|
98
|
+
)
|
|
99
|
+
self._refresher.on_update(current_card, data)
|
|
100
|
+
time.sleep(self._interval)
|
|
101
|
+
|
|
102
|
+
def stop(self):
|
|
103
|
+
self._exit_event.set()
|
|
104
|
+
self._collector_thread.stop()
|
|
105
|
+
self.join()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class AsyncPeriodicRefresher:
|
|
109
|
+
def __init__(
|
|
110
|
+
self,
|
|
111
|
+
card_referesher: CardRefresher,
|
|
112
|
+
updater_interval=1,
|
|
113
|
+
collector_interval=1,
|
|
114
|
+
file_name=None,
|
|
115
|
+
):
|
|
116
|
+
assert card_referesher.CARD_ID is not None, "CARD_ID must be defined"
|
|
117
|
+
self._collector_thread = None
|
|
118
|
+
self._collector_thread = InfoCollectorThread(
|
|
119
|
+
interval=collector_interval, file_name=file_name
|
|
120
|
+
)
|
|
121
|
+
self._collector_thread.start()
|
|
122
|
+
|
|
123
|
+
self._updater_thread = CardUpdaterThread(
|
|
124
|
+
card_refresher=card_referesher,
|
|
125
|
+
interval=updater_interval,
|
|
126
|
+
file_name=file_name,
|
|
127
|
+
collector_thread=self._collector_thread,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def start(self):
|
|
131
|
+
self._updater_thread.start()
|
|
132
|
+
|
|
133
|
+
def stop(self):
|
|
134
|
+
self._updater_thread.stop()
|
|
135
|
+
self._collector_thread.stop()
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from metaflow.exception import MetaflowException
|
|
2
|
+
from collections import defaultdict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CardDecoratorInjector:
|
|
6
|
+
"""
|
|
7
|
+
Mixin Useful for injecting @card decorators from other first class Metaflow decorators.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
_first_time_init = defaultdict(dict)
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def _get_first_time_init_cached_value(cls, step_name, card_id):
|
|
14
|
+
return cls._first_time_init.get(step_name, {}).get(card_id, None)
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def _set_first_time_init_cached_value(cls, step_name, card_id, value):
|
|
18
|
+
cls._first_time_init[step_name][card_id] = value
|
|
19
|
+
|
|
20
|
+
def _card_deco_already_attached(self, step, card_id):
|
|
21
|
+
for decorator in step.decorators:
|
|
22
|
+
if decorator.name == "card":
|
|
23
|
+
if decorator.attributes["id"] and card_id in decorator.attributes["id"]:
|
|
24
|
+
return True
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
def _get_step(self, flow, step_name):
|
|
28
|
+
for step in flow:
|
|
29
|
+
if step.name == step_name:
|
|
30
|
+
return step
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
def _first_time_init_check(self, step_dag_node, card_id):
|
|
34
|
+
""" """
|
|
35
|
+
return not self._card_deco_already_attached(step_dag_node, card_id)
|
|
36
|
+
|
|
37
|
+
def attach_card_decorator(
|
|
38
|
+
self,
|
|
39
|
+
flow,
|
|
40
|
+
step_name,
|
|
41
|
+
card_id,
|
|
42
|
+
card_type,
|
|
43
|
+
refresh_interval=5,
|
|
44
|
+
):
|
|
45
|
+
"""
|
|
46
|
+
This method is called `step_init` in your StepDecorator code since
|
|
47
|
+
this class is used as a Mixin
|
|
48
|
+
"""
|
|
49
|
+
from metaflow import decorators as _decorators
|
|
50
|
+
|
|
51
|
+
if not all([card_id, card_type]):
|
|
52
|
+
raise MetaflowException(
|
|
53
|
+
"`card_id` and `card_type` must be set in the `CardDecoratorInjector` Mixin"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
step_dag_node = self._get_step(flow, step_name)
|
|
57
|
+
if (
|
|
58
|
+
self._get_first_time_init_cached_value(step_name, card_id) is None
|
|
59
|
+
): # First check class level setting.
|
|
60
|
+
if self._first_time_init_check(step_dag_node, card_id):
|
|
61
|
+
self._set_first_time_init_cached_value(step_name, card_id, True)
|
|
62
|
+
_decorators._attach_decorators_to_step(
|
|
63
|
+
step_dag_node,
|
|
64
|
+
[
|
|
65
|
+
"card:type=%s,id=%s,refresh_interval=%s"
|
|
66
|
+
% (card_type, card_id, str(refresh_interval))
|
|
67
|
+
],
|
|
68
|
+
)
|
|
69
|
+
else:
|
|
70
|
+
self._set_first_time_init_cached_value(step_name, card_id, False)
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from metaflow.cards import VegaChart, MetaflowCardComponent, Artifact, Table
|
|
3
|
+
from typing import Optional, List, Union
|
|
4
|
+
import math
|
|
5
|
+
from metaflow.plugins.cards.card_modules.components import (
|
|
6
|
+
with_default_component_id,
|
|
7
|
+
TaskToDict,
|
|
8
|
+
ArtifactsComponent,
|
|
9
|
+
UserComponent,
|
|
10
|
+
TableComponent,
|
|
11
|
+
SectionComponent,
|
|
12
|
+
render_safely,
|
|
13
|
+
)
|
|
14
|
+
import datetime
|
|
15
|
+
from metaflow.metaflow_current import current
|
|
16
|
+
import json
|
|
17
|
+
from functools import wraps
|
|
18
|
+
from collections import defaultdict
|
|
19
|
+
from threading import Thread, Event
|
|
20
|
+
import time
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def update_spec_data(spec, data):
|
|
24
|
+
spec["data"]["values"] = data
|
|
25
|
+
return spec
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def update_data_object(data_object, data):
|
|
29
|
+
data_object["values"].append(data)
|
|
30
|
+
return data_object
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def line_chart_spec(
|
|
34
|
+
title=None,
|
|
35
|
+
x_name="u",
|
|
36
|
+
y_name="v",
|
|
37
|
+
xtitle=None,
|
|
38
|
+
ytitle=None,
|
|
39
|
+
width=600,
|
|
40
|
+
height=400,
|
|
41
|
+
with_params=True,
|
|
42
|
+
x_axis_temporal=False,
|
|
43
|
+
):
|
|
44
|
+
parameters = [
|
|
45
|
+
{
|
|
46
|
+
"name": "interpolate",
|
|
47
|
+
"value": "linear",
|
|
48
|
+
"bind": {
|
|
49
|
+
"input": "select",
|
|
50
|
+
"options": [
|
|
51
|
+
"basis",
|
|
52
|
+
"cardinal",
|
|
53
|
+
"catmull-rom",
|
|
54
|
+
"linear",
|
|
55
|
+
"monotone",
|
|
56
|
+
"natural",
|
|
57
|
+
"step",
|
|
58
|
+
"step-after",
|
|
59
|
+
"step-before",
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "tension",
|
|
65
|
+
"value": 0,
|
|
66
|
+
"bind": {"input": "range", "min": 0, "max": 1, "step": 0.05},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "strokeWidth",
|
|
70
|
+
"value": 2,
|
|
71
|
+
"bind": {"input": "range", "min": 0, "max": 10, "step": 0.5},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "strokeCap",
|
|
75
|
+
"value": "butt",
|
|
76
|
+
"bind": {"input": "select", "options": ["butt", "round", "square"]},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "strokeDash",
|
|
80
|
+
"value": [1, 0],
|
|
81
|
+
"bind": {
|
|
82
|
+
"input": "select",
|
|
83
|
+
"options": [[1, 0], [8, 8], [8, 4], [4, 4], [4, 2], [2, 1], [1, 1]],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
]
|
|
87
|
+
parameter_marks = {
|
|
88
|
+
"interpolate": {"expr": "interpolate"},
|
|
89
|
+
"tension": {"expr": "tension"},
|
|
90
|
+
"strokeWidth": {"expr": "strokeWidth"},
|
|
91
|
+
"strokeDash": {"expr": "strokeDash"},
|
|
92
|
+
"strokeCap": {"expr": "strokeCap"},
|
|
93
|
+
}
|
|
94
|
+
spec = {
|
|
95
|
+
"title": title if title else "Line Chart",
|
|
96
|
+
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
|
97
|
+
# "width": width,
|
|
98
|
+
# "height": height,
|
|
99
|
+
"params": parameters if with_params else [],
|
|
100
|
+
"data": {"name": "values", "values": []},
|
|
101
|
+
"mark": {
|
|
102
|
+
"type": "line",
|
|
103
|
+
"tooltip": True,
|
|
104
|
+
**(parameter_marks if with_params else {}),
|
|
105
|
+
},
|
|
106
|
+
"selection": {"grid": {"type": "interval", "bind": "scales"}},
|
|
107
|
+
"encoding": {
|
|
108
|
+
"x": {
|
|
109
|
+
"field": x_name,
|
|
110
|
+
"title": xtitle if xtitle else x_name,
|
|
111
|
+
**({"timeUnit": "seconds"} if x_axis_temporal else {}),
|
|
112
|
+
**({"type": "quantitative"} if not x_axis_temporal else {}),
|
|
113
|
+
},
|
|
114
|
+
"y": {
|
|
115
|
+
"field": y_name,
|
|
116
|
+
"type": "quantitative",
|
|
117
|
+
"title": ytitle if ytitle else y_name,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
**({"width": width, "height": height} if width and height else {}),
|
|
121
|
+
}
|
|
122
|
+
data = {"values": []}
|
|
123
|
+
return spec, data
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class LineChart(UserComponent):
|
|
127
|
+
REALTIME_UPDATABLE = True
|
|
128
|
+
|
|
129
|
+
def __init__(
|
|
130
|
+
self,
|
|
131
|
+
title,
|
|
132
|
+
xtitle,
|
|
133
|
+
ytitle,
|
|
134
|
+
x_name,
|
|
135
|
+
y_name,
|
|
136
|
+
with_params=False,
|
|
137
|
+
x_axis_temporal=False,
|
|
138
|
+
width=None,
|
|
139
|
+
height=None,
|
|
140
|
+
):
|
|
141
|
+
super().__init__()
|
|
142
|
+
|
|
143
|
+
self.spec, _ = line_chart_spec(
|
|
144
|
+
title=title,
|
|
145
|
+
xtitle=xtitle,
|
|
146
|
+
ytitle=ytitle,
|
|
147
|
+
x_name=x_name,
|
|
148
|
+
y_name=y_name,
|
|
149
|
+
with_params=with_params,
|
|
150
|
+
x_axis_temporal=x_axis_temporal,
|
|
151
|
+
width=width,
|
|
152
|
+
height=height,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def update(self, data): # Can take a diff
|
|
156
|
+
self.spec = update_spec_data(self.spec, data)
|
|
157
|
+
|
|
158
|
+
@with_default_component_id
|
|
159
|
+
def render(self):
|
|
160
|
+
vega_chart = VegaChart(self.spec, show_controls=True)
|
|
161
|
+
vega_chart.component_id = self.component_id
|
|
162
|
+
return vega_chart.render()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class ArtifactTable(Artifact):
|
|
166
|
+
def __init__(self, data_dict):
|
|
167
|
+
self._data = data_dict
|
|
168
|
+
self._task_to_dict = TaskToDict(only_repr=True)
|
|
169
|
+
|
|
170
|
+
@with_default_component_id
|
|
171
|
+
@render_safely
|
|
172
|
+
def render(self):
|
|
173
|
+
_art_list = []
|
|
174
|
+
for k, v in self._data.items():
|
|
175
|
+
_art = self._task_to_dict.infer_object(v)
|
|
176
|
+
_art["name"] = k
|
|
177
|
+
_art_list.append(_art)
|
|
178
|
+
|
|
179
|
+
af_component = ArtifactsComponent(data=_art_list)
|
|
180
|
+
af_component.component_id = self.component_id
|
|
181
|
+
return af_component.render()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class UpadateableTable(UserComponent):
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
Parameters
|
|
188
|
+
----------
|
|
189
|
+
data : List[List[str or MetaflowCardComponent]], optional
|
|
190
|
+
List (rows) of lists (columns). Each item can be a string or a `MetaflowCardComponent`.
|
|
191
|
+
headers : List[str], optional
|
|
192
|
+
Optional header row for the table.
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
REALTIME_UPDATABLE = True
|
|
196
|
+
|
|
197
|
+
def update(self, row: List[Union[str, MetaflowCardComponent]]):
|
|
198
|
+
self._data.append(row)
|
|
199
|
+
|
|
200
|
+
def __init__(
|
|
201
|
+
self,
|
|
202
|
+
data: Optional[List[List[Union[str, MetaflowCardComponent]]]] = None,
|
|
203
|
+
headers: Optional[List[str]] = None,
|
|
204
|
+
disable_updates: bool = False,
|
|
205
|
+
):
|
|
206
|
+
data = data or [[]]
|
|
207
|
+
headers = headers or []
|
|
208
|
+
header_bool, data_bool = TableComponent.validate(headers, data)
|
|
209
|
+
self._headers = []
|
|
210
|
+
self._data = [[]]
|
|
211
|
+
if header_bool:
|
|
212
|
+
self._headers = headers
|
|
213
|
+
if data_bool:
|
|
214
|
+
self._data = data
|
|
215
|
+
|
|
216
|
+
if disable_updates:
|
|
217
|
+
self.REALTIME_UPDATABLE = False
|
|
218
|
+
|
|
219
|
+
def _render_subcomponents(self):
|
|
220
|
+
for row in self._data:
|
|
221
|
+
for col in row:
|
|
222
|
+
if isinstance(col, VegaChart):
|
|
223
|
+
col._chart_inside_table = True
|
|
224
|
+
|
|
225
|
+
return [
|
|
226
|
+
SectionComponent.render_subcomponents(
|
|
227
|
+
row,
|
|
228
|
+
additional_allowed_types=[
|
|
229
|
+
str,
|
|
230
|
+
bool,
|
|
231
|
+
int,
|
|
232
|
+
float,
|
|
233
|
+
dict,
|
|
234
|
+
list,
|
|
235
|
+
tuple,
|
|
236
|
+
type(None),
|
|
237
|
+
],
|
|
238
|
+
allow_unknowns=True,
|
|
239
|
+
)
|
|
240
|
+
for row in self._data
|
|
241
|
+
]
|
|
242
|
+
|
|
243
|
+
@with_default_component_id
|
|
244
|
+
@render_safely
|
|
245
|
+
def render(self):
|
|
246
|
+
table_component = TableComponent(
|
|
247
|
+
headers=self._headers, data=self._render_subcomponents()
|
|
248
|
+
)
|
|
249
|
+
table_component.component_id = self.component_id
|
|
250
|
+
return table_component.render()
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .lineage_card import create_checkpoint_card, null_card
|