MilanM commited on
Commit
910e21b
·
verified ·
1 Parent(s): 5165e29

Create FUNCTIONS/json_template_drafing_functions.py

Browse files
FUNCTIONS/json_template_drafing_functions.py ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import marimo as mo
2
+ import json
3
+
4
+
5
+ def create_widgets(widget_type, values, widget_dict=None, stack=None):
6
+ """
7
+ Create marimo widgets for a list of values.
8
+
9
+ Args:
10
+ widget_type: Default marimo widget type (e.g., mo.ui.text_area)
11
+ values: List of values to create widgets for
12
+ widget_dict: Optional dict mapping specific values to widget types
13
+ stack: 'horizontal' for hstack, 'vertical' for vstack, None for dict return
14
+ """
15
+ widgets = {}
16
+
17
+ for value in values:
18
+ # Use specific widget type if provided, otherwise use default
19
+ current_widget_type = (
20
+ widget_dict.get(value, widget_type) if widget_dict else widget_type
21
+ )
22
+ widgets[value] = current_widget_type(label=f"**{str(value)}**")
23
+
24
+ if stack == "horizontal":
25
+ return mo.hstack(list(widgets.values()), gap=1)
26
+ elif stack == "vertical":
27
+ return mo.vstack(list(widgets.values()), gap=1)
28
+ else:
29
+ return widgets
30
+
31
+
32
+ def json_to_marimo_ui(
33
+ data,
34
+ replicate_values=False,
35
+ label="",
36
+ label_containers=False,
37
+ label_nested_leaves=False,
38
+ ):
39
+ """
40
+ Convert a JSON structure to marimo UI elements.
41
+
42
+ Args:
43
+ data: JSON-like dict/list, or mo.ui.file element containing JSON
44
+ replicate_values: If True, populate widgets with existing values; if False, leave empty
45
+ label: Optional label for the root element
46
+ label_containers: If True, apply labels to nested dicts/arrays (causes double nesting display);
47
+ if False (default), only label leaf input widgets
48
+ label_nested_leaves: If True, label leaf widgets with their key names;
49
+ if False (default), only root label is applied, nested leaves have no labels
50
+
51
+ Returns:
52
+ mo.ui.dictionary for dicts, mo.ui.array for lists
53
+ """
54
+ # import marimo as mo
55
+ # import json
56
+
57
+ # Handle mo.ui.file input
58
+ if hasattr(data, "contents") and callable(data.contents):
59
+ file_contents = data.contents()
60
+ if file_contents is None:
61
+ return mo.ui.dictionary({}, label=label)
62
+ if isinstance(file_contents, bytes):
63
+ file_contents = file_contents.decode("utf-8")
64
+ data = json.loads(file_contents)
65
+
66
+ def _convert(obj, replicate, lbl="", is_root=False):
67
+ if isinstance(obj, dict):
68
+ elements = {
69
+ str(key): _convert(
70
+ value,
71
+ replicate,
72
+ lbl=str(key) if label_nested_leaves else "",
73
+ )
74
+ for key, value in obj.items()
75
+ }
76
+ container_label = lbl if (is_root or label_containers) else ""
77
+ return mo.ui.dictionary(elements, label=container_label)
78
+
79
+ elif isinstance(obj, list):
80
+ if not obj:
81
+ container_label = lbl if (is_root or label_containers) else ""
82
+ return mo.ui.array([], label=container_label)
83
+ elements = [
84
+ _convert(item, replicate, lbl="" if not label_nested_leaves else "")
85
+ for item in obj
86
+ ]
87
+ container_label = lbl if (is_root or label_containers) else ""
88
+ return mo.ui.array(elements, label=container_label)
89
+
90
+ elif isinstance(obj, bool):
91
+ leaf_label = lbl if (is_root or label_nested_leaves) else ""
92
+ return mo.ui.checkbox(
93
+ value=obj if replicate else False,
94
+ label=leaf_label,
95
+ )
96
+
97
+ elif isinstance(obj, int):
98
+ leaf_label = lbl if (is_root or label_nested_leaves) else ""
99
+ return mo.ui.number(
100
+ value=obj if replicate else None,
101
+ label=leaf_label,
102
+ full_width=True,
103
+ )
104
+
105
+ elif isinstance(obj, float):
106
+ leaf_label = lbl if (is_root or label_nested_leaves) else ""
107
+ return mo.ui.number(
108
+ value=obj if replicate else None,
109
+ step=0.01,
110
+ label=leaf_label,
111
+ full_width=True,
112
+ )
113
+
114
+ elif isinstance(obj, str):
115
+ val = obj if replicate else ""
116
+ leaf_label = lbl if (is_root or label_nested_leaves) else ""
117
+ if len(obj) > 40:
118
+ return mo.ui.text_area(value=val, label=leaf_label, full_width=True)
119
+ return mo.ui.text(value=val, label=leaf_label, full_width=True)
120
+
121
+ elif obj is None:
122
+ leaf_label = lbl if (is_root or label_nested_leaves) else ""
123
+ return mo.ui.text(value="", label=leaf_label, full_width=True)
124
+
125
+ else:
126
+ leaf_label = lbl if (is_root or label_nested_leaves) else ""
127
+ return mo.ui.text(
128
+ value=str(obj) if replicate else "",
129
+ label=leaf_label,
130
+ full_width=True,
131
+ )
132
+
133
+ return _convert(data, replicate_values, label, is_root=True)
134
+
135
+
136
+ def create_download_button(
137
+ widget_value, filename_prefix="download", add_uuid_suffix=True
138
+ ):
139
+ """Create a marimo download button appropriate for the widget value type.
140
+
141
+ Automatically detects data type and creates download button with correct format and MIME type.
142
+
143
+ Args:
144
+ widget_value: Data to download (dict/list as JSON, DataFrames as CSV,
145
+ str as text, bytes as binary, others converted to string)
146
+ filename_prefix (str): Filename prefix. Defaults to "download".
147
+ add_uuid_suffix (bool): Add 4-char UUID suffix to filename. Defaults to True.
148
+
149
+ Returns:
150
+ mo.download: Configured marimo download button widget.
151
+
152
+ Examples:
153
+ >>> data = {"key": "value", "numbers": [1, 2, 3]}
154
+ >>> button = create_download_button(data, "my_data")
155
+
156
+ >>> df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
157
+ >>> button = create_download_button(df, "dataframe")
158
+
159
+ Note:
160
+ Requires marimo (mo) and uuid modules. JSON formatted with 2-space indent.
161
+ CSV exports exclude index for pandas DataFrames.
162
+ """
163
+ import marimo as mo
164
+ import json
165
+ import uuid
166
+
167
+ if isinstance(widget_value, dict) or isinstance(widget_value, list):
168
+ # JSON data
169
+ data = json.dumps(widget_value, indent=2)
170
+ filename = f"{filename_prefix}.json"
171
+ if add_uuid_suffix:
172
+ uuid_suffix = str(uuid.uuid4())[:4]
173
+ filename = f"{filename_prefix}_{uuid_suffix}.json"
174
+ return mo.download(
175
+ data=data.encode(), filename=filename, mimetype="application/json"
176
+ )
177
+
178
+ elif hasattr(widget_value, "to_csv"):
179
+ # Pandas DataFrame
180
+ data = widget_value.to_csv(index=False)
181
+ filename = f"{filename_prefix}.csv"
182
+ if add_uuid_suffix:
183
+ uuid_suffix = str(uuid.uuid4())[:4]
184
+ filename = f"{filename_prefix}_{uuid_suffix}.csv"
185
+ return mo.download(data=data.encode(), filename=filename, mimetype="text/csv")
186
+
187
+ elif hasattr(widget_value, "write_csv"):
188
+ # Polars DataFrame
189
+ data = widget_value.write_csv()
190
+ filename = f"{filename_prefix}.csv"
191
+ if add_uuid_suffix:
192
+ uuid_suffix = str(uuid.uuid4())[:4]
193
+ filename = f"{filename_prefix}_{uuid_suffix}.csv"
194
+ return mo.download(data=data.encode(), filename=filename, mimetype="text/csv")
195
+
196
+ elif isinstance(widget_value, str):
197
+ # Text data
198
+ filename = f"{filename_prefix}.txt"
199
+ if add_uuid_suffix:
200
+ uuid_suffix = str(uuid.uuid4())[:4]
201
+ filename = f"{filename_prefix}_{uuid_suffix}.txt"
202
+ return mo.download(
203
+ data=widget_value.encode(),
204
+ filename=filename,
205
+ mimetype="text/plain",
206
+ )
207
+
208
+ elif isinstance(widget_value, bytes):
209
+ # Binary data
210
+ filename = f"{filename_prefix}.bin"
211
+ if add_uuid_suffix:
212
+ uuid_suffix = str(uuid.uuid4())[:4]
213
+ filename = f"{filename_prefix}_{uuid_suffix}.bin"
214
+ return mo.download(
215
+ data=widget_value,
216
+ filename=filename,
217
+ mimetype="application/octet-stream",
218
+ )
219
+
220
+ else:
221
+ # Fallback: convert to string
222
+ data = str(widget_value)
223
+ filename = f"{filename_prefix}.txt"
224
+ if add_uuid_suffix:
225
+ uuid_suffix = str(uuid.uuid4())[:4]
226
+ filename = f"{filename_prefix}_{uuid_suffix}.txt"
227
+ return mo.download(data=data.encode(), filename=filename, mimetype="text/plain")
228
+
229
+
230
+ if __name__ == "__main__":
231
+ print("Only Importable in Marimo Notebooks")