metaflow 2.18.9__py2.py3-none-any.whl → 2.18.10__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.
- metaflow/cards.py +3 -0
- metaflow/parameters.py +4 -0
- metaflow/plugins/argo/argo_workflows.py +6 -7
- metaflow/plugins/cards/card_modules/bundle.css +1 -1
- metaflow/plugins/cards/card_modules/components.py +341 -0
- metaflow/plugins/cards/card_modules/json_viewer.py +232 -0
- metaflow/plugins/cards/card_modules/main.js +54 -39
- metaflow/plugins/datatools/s3/s3op.py +14 -2
- metaflow/runner/click_api.py +12 -0
- metaflow/version.py +1 -1
- {metaflow-2.18.9.data → metaflow-2.18.10.data}/data/share/metaflow/devtools/Tiltfile +1 -0
- {metaflow-2.18.9.dist-info → metaflow-2.18.10.dist-info}/METADATA +2 -2
- {metaflow-2.18.9.dist-info → metaflow-2.18.10.dist-info}/RECORD +19 -18
- {metaflow-2.18.9.data → metaflow-2.18.10.data}/data/share/metaflow/devtools/Makefile +0 -0
- {metaflow-2.18.9.data → metaflow-2.18.10.data}/data/share/metaflow/devtools/pick_services.sh +0 -0
- {metaflow-2.18.9.dist-info → metaflow-2.18.10.dist-info}/WHEEL +0 -0
- {metaflow-2.18.9.dist-info → metaflow-2.18.10.dist-info}/entry_points.txt +0 -0
- {metaflow-2.18.9.dist-info → metaflow-2.18.10.dist-info}/licenses/LICENSE +0 -0
- {metaflow-2.18.9.dist-info → metaflow-2.18.10.dist-info}/top_level.txt +0 -0
@@ -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
|