cryogenic22 commited on
Commit
08762b8
·
verified ·
1 Parent(s): e976836

Create code_playground.py

Browse files
Files changed (1) hide show
  1. src/code_playground.py +314 -0
src/code_playground.py ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import sys
3
+ from io import StringIO
4
+ from contextlib import redirect_stdout
5
+ import json
6
+ from datetime import datetime
7
+ from typing import Dict, List, Optional
8
+ import base64
9
+ from PIL import Image
10
+ import io
11
+
12
+ class CodePlayground:
13
+ def __init__(self):
14
+ self.initialize_session_state()
15
+
16
+ @staticmethod
17
+ def initialize_session_state():
18
+ """Initialize session state for artifacts and history"""
19
+ if 'artifacts' not in st.session_state:
20
+ st.session_state.artifacts = []
21
+ if 'code_history' not in st.session_state:
22
+ st.session_state.code_history = []
23
+ if 'current_artifact' not in st.session_state:
24
+ st.session_state.current_artifact = None
25
+
26
+ def display(self):
27
+ """Display the enhanced code playground interface"""
28
+ st.header("Interactive Learning Playground")
29
+
30
+ # Create tabs for different views
31
+ code_tab, artifacts_tab = st.tabs(["Code Editor", "Learning Artifacts"])
32
+
33
+ with code_tab:
34
+ self.display_code_editor()
35
+
36
+ with artifacts_tab:
37
+ self.display_artifacts()
38
+
39
+ def display_code_editor(self):
40
+ """Display the code editor interface"""
41
+ # Code editor
42
+ code = st.text_area(
43
+ "Write your Python code here",
44
+ height=200,
45
+ key="code_editor",
46
+ help="Write Python code to execute. You can use print() to see outputs."
47
+ )
48
+
49
+ # Button columns
50
+ col1, col2, col3 = st.columns(3)
51
+
52
+ with col1:
53
+ if st.button("Run Code", key="run_code"):
54
+ output, artifact_data = self.execute_code(code)
55
+ if artifact_data:
56
+ self.store_artifact(artifact_data)
57
+
58
+ with col2:
59
+ if st.button("Save as Artifact", key="save_artifact"):
60
+ self.create_manual_artifact(code)
61
+
62
+ with col3:
63
+ if st.button("Clear Output", key="clear_output"):
64
+ if 'code_output' in st.session_state:
65
+ del st.session_state.code_output
66
+
67
+ # Display output
68
+ if 'code_output' in st.session_state:
69
+ st.markdown("### Output:")
70
+ st.code(st.session_state.code_output)
71
+
72
+ def export_artifact(self, artifact: Dict, export_dir: str):
73
+ """Export a single artifact to the specified directory"""
74
+ # Create directory if it doesn't exist
75
+ artifact_dir = Path(export_dir) / str(artifact['id'])
76
+ artifact_dir.mkdir(parents=True, exist_ok=True)
77
+
78
+ # Export metadata
79
+ metadata = {
80
+ 'id': artifact['id'],
81
+ 'title': artifact['title'],
82
+ 'type': artifact['type'],
83
+ 'date': artifact['date']
84
+ }
85
+
86
+ with open(artifact_dir / 'metadata.json', 'w') as f:
87
+ json.dump(metadata, f, indent=2)
88
+
89
+ # Export content based on type
90
+ if artifact['type'] == "Code":
91
+ with open(artifact_dir / 'content.py', 'w') as f:
92
+ f.write(artifact['content'])
93
+
94
+ elif artifact['type'] == "Image":
95
+ img_data = base64.b64decode(artifact['content'])
96
+ with open(artifact_dir / 'content.png', 'wb') as f:
97
+ f.write(img_data)
98
+
99
+ elif artifact['type'] == "Text":
100
+ with open(artifact_dir / 'content.txt', 'w') as f:
101
+ f.write(artifact['content'])
102
+
103
+ elif artifact['type'] == "Mixed Media":
104
+ media_dir = artifact_dir / 'content'
105
+ media_dir.mkdir(exist_ok=True)
106
+
107
+ for idx, item in enumerate(artifact['content']):
108
+ if item['type'] == 'code':
109
+ with open(media_dir / f'code_{idx}.py', 'w') as f:
110
+ f.write(item['data'])
111
+ elif item['type'] == 'image':
112
+ img_data = base64.b64decode(item['data'])
113
+ with open(media_dir / f'image_{idx}.png', 'wb') as f:
114
+ f.write(img_data)
115
+ elif item['type'] == 'text':
116
+ with open(media_dir / f'text_{idx}.txt', 'w') as f:
117
+ f.write(item['data'])
118
+
119
+ def export_all_artifacts(self, export_dir: str):
120
+ """Export all artifacts to a directory and create a zip file"""
121
+ # Create temporary directory for exports
122
+ temp_dir = Path(export_dir) / 'temp_artifacts'
123
+ temp_dir.mkdir(parents=True, exist_ok=True)
124
+
125
+ try:
126
+ # Export each artifact
127
+ for artifact in st.session_state.artifacts:
128
+ self.export_artifact(artifact, str(temp_dir))
129
+
130
+ # Create zip file
131
+ zip_path = Path(export_dir) / 'learning_artifacts.zip'
132
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
133
+ for root, _, files in os.walk(temp_dir):
134
+ for file in files:
135
+ file_path = Path(root) / file
136
+ arcname = file_path.relative_to(temp_dir)
137
+ zipf.write(file_path, arcname)
138
+
139
+ return str(zip_path)
140
+ finally:
141
+ # Clean up temporary directory
142
+ shutil.rmtree(temp_dir)
143
+
144
+ def display_artifacts(self):
145
+ """Display stored learning artifacts"""
146
+ st.subheader("Learning Artifacts")
147
+
148
+ if not st.session_state.artifacts:
149
+ st.info("No artifacts created yet. Run some code or create manual artifacts to see them here!")
150
+ return
151
+
152
+ # Filter options
153
+ filter_type = st.selectbox(
154
+ "Filter by type",
155
+ options=["All", "Code", "Image", "Text", "Mixed Media"],
156
+ key="artifact_filter"
157
+ )
158
+
159
+ # Display artifacts in reverse chronological order
160
+ for artifact in reversed(st.session_state.artifacts):
161
+ if filter_type == "All" or artifact['type'] == filter_type:
162
+ with st.expander(f"{artifact['title']} - {artifact['date']}", expanded=False):
163
+ st.write(f"**Type:** {artifact['type']}")
164
+ st.write(f"**Created:** {artifact['date']}")
165
+
166
+ # Display content based on type
167
+ if artifact['type'] == "Code":
168
+ st.code(artifact['content'], language="python")
169
+ elif artifact['type'] == "Image":
170
+ st.image(base64.b64decode(artifact['content']))
171
+ elif artifact['type'] == "Text":
172
+ st.write(artifact['content'])
173
+ elif artifact['type'] == "Mixed Media":
174
+ for item in artifact['content']:
175
+ if item['type'] == "code":
176
+ st.code(item['data'], language="python")
177
+ elif item['type'] == "image":
178
+ st.image(base64.b64decode(item['data']))
179
+ elif item['type'] == "text":
180
+ st.write(item['data'])
181
+
182
+ # Artifact actions
183
+ col1, col2, col3 = st.columns(3)
184
+ with col1:
185
+ if st.button("Load in Editor", key=f"load_{artifact['id']}"):
186
+ if artifact['type'] == "Code":
187
+ st.session_state.code_editor = artifact['content']
188
+ st.rerun()
189
+
190
+ with col2:
191
+ if st.button("Export", key=f"export_{artifact['id']}"):
192
+ try:
193
+ # Use temporary directory for single artifact export
194
+ temp_dir = Path("temp_export_single")
195
+ temp_dir.mkdir(exist_ok=True)
196
+
197
+ # Export the artifact
198
+ self.export_artifact(artifact, str(temp_dir))
199
+
200
+ # Create zip file
201
+ zip_path = temp_dir / f"artifact_{artifact['id']}.zip"
202
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
203
+ for root, _, files in os.walk(temp_dir):
204
+ for file in files:
205
+ if file != f"artifact_{artifact['id']}.zip":
206
+ file_path = Path(root) / file
207
+ arcname = file_path.relative_to(temp_dir)
208
+ zipf.write(file_path, arcname)
209
+
210
+ # Read the zip file
211
+ with open(zip_path, "rb") as fp:
212
+ zip_data = fp.read()
213
+
214
+ # Create download button
215
+ st.download_
216
+
217
+ def execute_code(self, code: str) -> tuple:
218
+ """Execute code and capture outputs"""
219
+ output = StringIO()
220
+ artifact_data = None
221
+
222
+ try:
223
+ # Create a restricted environment
224
+ globals_dict = {
225
+ '__builtins__': __builtins__,
226
+ 'print': print,
227
+ 'Image': Image,
228
+ 'io': io,
229
+ 'base64': base64
230
+ }
231
+
232
+ # Capture stdout
233
+ with redirect_stdout(output):
234
+ # Execute the code
235
+ exec(code, globals_dict, {})
236
+
237
+ # Store output
238
+ output_text = output.getvalue()
239
+ st.session_state.code_output = output_text
240
+
241
+ # Check for generated artifacts in globals
242
+ if '_artifact_output' in globals_dict:
243
+ artifact_data = globals_dict['_artifact_output']
244
+
245
+ # Store in history
246
+ self.store_in_history(code, output_text)
247
+
248
+ return output_text, artifact_data
249
+
250
+ except Exception as e:
251
+ error_msg = f"Error: {str(e)}"
252
+ st.session_state.code_output = error_msg
253
+ return error_msg, None
254
+
255
+ def store_artifact(self, artifact_data: Dict):
256
+ """Store a new artifact"""
257
+ artifact = {
258
+ 'id': len(st.session_state.artifacts),
259
+ 'date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
260
+ **artifact_data
261
+ }
262
+ st.session_state.artifacts.append(artifact)
263
+ st.success(f"Created new artifact: {artifact['title']}")
264
+
265
+ def create_manual_artifact(self, code: str):
266
+ """Create a manual artifact from current code"""
267
+ title = st.text_input("Artifact Title")
268
+ if title:
269
+ artifact = {
270
+ 'id': len(st.session_state.artifacts),
271
+ 'title': title,
272
+ 'type': "Code",
273
+ 'content': code,
274
+ 'date': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
275
+ }
276
+ st.session_state.artifacts.append(artifact)
277
+ st.success(f"Created new artifact: {title}")
278
+
279
+ def delete_artifact(self, artifact_id: int):
280
+ """Delete an artifact"""
281
+ st.session_state.artifacts = [
282
+ a for a in st.session_state.artifacts if a['id'] != artifact_id
283
+ ]
284
+
285
+ def store_in_history(self, code: str, output: str):
286
+ """Store code execution in history"""
287
+ history_entry = {
288
+ 'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
289
+ 'code': code,
290
+ 'output': output
291
+ }
292
+ st.session_state.code_history.append(history_entry)
293
+
294
+ # Helper function to create artifacts from code
295
+ def create_artifact(title: str, content: any, artifact_type: str = "Mixed Media"):
296
+ """
297
+ Create an artifact from code execution.
298
+ Usage example in code:
299
+
300
+ # Create a text artifact
301
+ create_artifact("My Text", "Hello World", "Text")
302
+
303
+ # Create an image artifact
304
+ img = Image.new('RGB', (100, 100), color='red')
305
+ buffered = io.BytesIO()
306
+ img.save(buffered, format="PNG")
307
+ img_str = base64.b64encode(buffered.getvalue()).decode()
308
+ create_artifact("My Image", img_str, "Image")
309
+ """
310
+ globals()['_artifact_output'] = {
311
+ 'title': title,
312
+ 'type': artifact_type,
313
+ 'content': content
314
+ }