-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStreamlit_Notebook_To_Script.py
More file actions
142 lines (121 loc) · 4.87 KB
/
Copy pathStreamlit_Notebook_To_Script.py
File metadata and controls
142 lines (121 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import streamlit as st
from pathlib import Path
import nbformat
st.title(".ipynb ↔ .py Converter")
st.write("""
Convert Jupyter Notebooks to Python scripts and vice versa.
- Markdown cells are optionally stripped or converted to comments.
- Code cells are preserved as executable code.
- Comments preserved and can be recovered as Markdown when converting back.
""")
st.divider()
st.header("1. Upload your file")
uploaded_file = st.file_uploader(
"Upload a .ipynb or .py file", type=['ipynb', 'py']
)
def notebook_to_py(file, strip_markdown=True):
"""Convert a Jupyter Notebook (.ipynb) to a Python script (.py).
Args:
file: Uploaded notebook file object.
strip_markdown (bool): If True, remove markdown cells; if False, convert markdown to comments.
Returns:
Tuple[str, str]: Converted Python script as text, and output file name.
"""
lines = []
nb = nbformat.read(file, as_version=4)
for cell in nb.cells:
if cell.cell_type == 'code':
# Add code cell content directly
lines.append(cell.source)
elif cell.cell_type == "markdown" and not strip_markdown:
# Convert markdown cell to commented lines
markdown_as_comment = "\n".join(
f"# {line}" for line in cell.source.splitlines())
lines.append(markdown_as_comment)
output_text = "\n\n".join(lines)
output_name = Path(file.name).stem + "_converted.py"
return output_text, output_name
def py_to_notebook(file):
"""
Convert a Python script (.py) to a Jupyter Notebook (.ipynb).
This function reads a Python file from a file-like object and creates a
notebook in memory. It preserves code as a single code cell per contiguous
code block and converts consecutive comment lines starting with `#` into
Markdown cells. Inline comments remain in the code cells.
Args:
file: A file-like object representing the Python script. The file
content is expected to be UTF-8 encoded.
Returns:
Tuple[str, str]:
- output_text: The notebook serialized as a JSON string (ready to
save as .ipynb or serve for download).
- output_name: Suggested filename for the notebook, generated by
appending '_converted.ipynb' to the stem of the input file's name.
Example:
with open("example.py", "rb") as f:
notebook_json, notebook_name = py_to_notebook(f)
"""
text = file.read().decode("utf-8")
nb = nbformat.v4.new_notebook()
lines = text.splitlines()
buffer = []
current_type = None
def flush_buffer():
nonlocal buffer, current_type
if not buffer:
return
if current_type == "code":
nb.cells.append(nbformat.v4.new_code_cell("\n".join(buffer)))
elif current_type == "markdown":
nb.cells.append(nbformat.v4.new_markdown_cell("\n".join(buffer)))
buffer = []
for line in lines:
stripped = line.strip()
if stripped.startswith("#"):
if current_type != "markdown" and buffer:
flush_buffer()
current_type = "markdown"
buffer.append(stripped.lstrip("# ").rstrip())
else:
if current_type != "code" and buffer:
flush_buffer()
current_type = "code"
buffer.append(line)
flush_buffer()
output_name = Path(file.name).stem + "_converted.ipynb"
output_text = nbformat.writes(nb)
return output_text, output_name
if uploaded_file:
# Checkbox to choose whether to strip markdown cells or convert to comments
strip_markdown = st.checkbox(
"Strip Markdown cells (unchecked to convert to comments)", value=True
)
file_ext = Path(uploaded_file.name).suffix
output_text = None
preview = ""
mime_type = ""
# Match file extension and convert accordingly
match file_ext:
case ".ipynb":
output_text, output_name = notebook_to_py(
uploaded_file, strip_markdown)
mime_type = "text/x-python"
preview = "\n".join(output_text.splitlines()[:20])
case ".py":
output_text, output_name = py_to_notebook(uploaded_file)
mime_type = "application/json"
uploaded_file.seek(0)
preview = "\n".join(uploaded_file.read().decode(
"utf-8").splitlines()[:20])
case _:
st.warning(f"Unsupported file type: {uploaded_file.name}")
if output_text:
st.success(f"✅ Converted: {uploaded_file.name} → {output_name}")
st.subheader("Preview (first 20 lines/cells):")
st.code(preview, language="python" if file_ext == ".ipynb" else "json")
st.download_button(
label="⬇️ Download Converted File",
data=output_text,
file_name=output_name,
mime=mime_type
)