Skip to content

Commit 227eeac

Browse files
committed
Enhance Colab badge functionality: Update script to add 'Open in Colab' badges to both template and solution notebooks. Modify badge generation to accommodate different notebook directories and ensure proper processing of both templates and solutions.
1 parent bc9ddee commit 227eeac

File tree

83 files changed

+2235
-890
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+2235
-890
lines changed

scripts/add_colab_badges.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
#!/usr/bin/env python3
2-
"""Add 'Open in Colab' badges to all template notebooks."""
2+
"""Add 'Open in Colab' badges to all template and solution notebooks."""
33

44
import json
55
from pathlib import Path
66

77
REPO = "duoan/TorchCode"
88
BRANCH = "master"
9-
TEMPLATES_DIR = Path(__file__).resolve().parent.parent / "templates"
9+
ROOT = Path(__file__).resolve().parent.parent
10+
TEMPLATES_DIR = ROOT / "templates"
11+
SOLUTIONS_DIR = ROOT / "solutions"
1012
BADGE_IMG = "https://colab.research.google.com/assets/colab-badge.svg"
1113

1214

13-
def colab_url(filename: str) -> str:
15+
def colab_url(filename: str, folder: str) -> str:
1416
return (
1517
f"https://colab.research.google.com/github/{REPO}"
16-
f"/blob/{BRANCH}/templates/{filename}"
18+
f"/blob/{BRANCH}/{folder}/{filename}"
1719
)
1820

1921

20-
def badge_markdown(filename: str) -> str:
21-
return f"[![Open In Colab]({BADGE_IMG})]({colab_url(filename)})"
22+
def badge_markdown(filename: str, folder: str) -> str:
23+
return f"[![Open In Colab]({BADGE_IMG})]({colab_url(filename, folder)})"
2224

2325

24-
def process_notebook(path: Path) -> bool:
26+
def process_notebook(path: Path, folder: str) -> bool:
2527
with open(path, "r", encoding="utf-8") as f:
2628
nb = json.load(f)
2729

@@ -34,7 +36,7 @@ def process_notebook(path: Path) -> bool:
3436
if "colab-badge.svg" in flat:
3537
return False
3638

37-
badge = badge_markdown(path.name)
39+
badge = badge_markdown(path.name, folder)
3840
cells[0]["source"] = [badge + "\n\n"] + (
3941
source_lines if isinstance(source_lines, list) else [source_lines]
4042
)
@@ -49,11 +51,17 @@ def process_notebook(path: Path) -> bool:
4951
def main() -> None:
5052
updated = 0
5153
for nb_path in sorted(TEMPLATES_DIR.glob("*.ipynb")):
52-
if process_notebook(nb_path):
53-
print(f" ✅ {nb_path.name}")
54+
if process_notebook(nb_path, "templates"):
55+
print(f" ✅ templates/{nb_path.name}")
5456
updated += 1
5557
else:
56-
print(f" ⏭️ {nb_path.name} (already has badge or skipped)")
58+
print(f" ⏭️ templates/{nb_path.name} (already has badge or skipped)")
59+
for nb_path in sorted(SOLUTIONS_DIR.glob("*.ipynb")):
60+
if process_notebook(nb_path, "solutions"):
61+
print(f" ✅ solutions/{nb_path.name}")
62+
updated += 1
63+
else:
64+
print(f" ⏭️ solutions/{nb_path.name} (already has badge or skipped)")
5765
print(f"\nDone — updated {updated} notebooks.")
5866

5967

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env python3
2+
"""Add Colab-only pip install of torch-judge to all notebooks that use torch_judge."""
3+
4+
import json
5+
from pathlib import Path
6+
7+
INSTALL_CELL_SOURCE = [
8+
"# Install torch-judge in Colab (no-op in JupyterLab/Docker)\n",
9+
"try:\n",
10+
" import google.colab\n",
11+
" get_ipython().run_line_magic('pip', 'install -q torch-judge')\n",
12+
"except ImportError:\n",
13+
" pass\n",
14+
]
15+
16+
MARKER = "get_ipython().run_line_magic('pip', 'install"
17+
18+
19+
def has_torch_judge(nb: dict) -> bool:
20+
for cell in nb.get("cells", []):
21+
src = cell.get("source", [])
22+
flat = "".join(src) if isinstance(src, list) else str(src)
23+
if "torch_judge" in flat:
24+
return True
25+
return False
26+
27+
28+
def already_has_install(nb: dict) -> bool:
29+
for cell in nb.get("cells", []):
30+
src = cell.get("source", [])
31+
flat = "".join(src) if isinstance(src, list) else str(src)
32+
if MARKER in flat and "torch-judge" in flat:
33+
return True
34+
return False
35+
36+
37+
def process_notebook(path: Path) -> bool:
38+
with open(path, "r", encoding="utf-8") as f:
39+
nb = json.load(f)
40+
41+
if not has_torch_judge(nb):
42+
return False
43+
if already_has_install(nb):
44+
return False
45+
46+
cells = nb["cells"]
47+
if not cells:
48+
return False
49+
50+
# Insert install cell at index 1 (after first cell, usually markdown title)
51+
install_cell = {
52+
"cell_type": "code",
53+
"metadata": {},
54+
"source": INSTALL_CELL_SOURCE,
55+
"outputs": [],
56+
"execution_count": None,
57+
}
58+
cells.insert(1, install_cell)
59+
60+
with open(path, "w", encoding="utf-8") as f:
61+
json.dump(nb, f, ensure_ascii=False, indent=1)
62+
f.write("\n")
63+
64+
return True
65+
66+
67+
def main() -> None:
68+
root = Path(__file__).resolve().parent.parent
69+
updated = 0
70+
for pattern in ["templates/*.ipynb", "solutions/*.ipynb"]:
71+
for path in sorted(root.glob(pattern)):
72+
if process_notebook(path):
73+
print(f" + {path.relative_to(root)}")
74+
updated += 1
75+
print(f"Updated {updated} notebooks.")
76+
77+
78+
if __name__ == "__main__":
79+
main()

solutions/01_relu_solution.ipynb

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,89 @@
11
{
2-
"nbformat": 4,
3-
"nbformat_minor": 5,
4-
"metadata": {
5-
"kernelspec": {
6-
"display_name": "Python 3",
7-
"language": "python",
8-
"name": "python3"
9-
},
10-
"language_info": {
11-
"name": "python",
12-
"version": "3.11.0"
13-
}
14-
},
152
"cells": [
163
{
174
"cell_type": "markdown",
5+
"id": "0556419b",
186
"metadata": {},
197
"source": [
8+
"[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/duoan/TorchCode/blob/master/solutions/01_relu_solution.ipynb)\n",
9+
"\n",
2010
"# 🟢 Solution: Implement ReLU\n",
2111
"\n",
2212
"Reference solution for the ReLU activation function.\n",
2313
"\n",
2414
"$$\\text{ReLU}(x) = \\max(0, x)$$"
25-
],
26-
"outputs": []
15+
]
2716
},
2817
{
2918
"cell_type": "code",
19+
"execution_count": null,
3020
"metadata": {},
21+
"outputs": [],
3122
"source": [
32-
"import torch"
33-
],
23+
"# Install torch-judge in Colab (no-op in JupyterLab/Docker)\n",
24+
"try:\n",
25+
" import google.colab\n",
26+
" get_ipython().run_line_magic('pip', 'install -q torch-judge')\n",
27+
"except ImportError:\n",
28+
" pass\n"
29+
]
30+
},
31+
{
32+
"cell_type": "code",
33+
"execution_count": null,
34+
"metadata": {},
3435
"outputs": [],
35-
"execution_count": null
36+
"source": [
37+
"import torch"
38+
]
3639
},
3740
{
3841
"cell_type": "code",
42+
"execution_count": null,
3943
"metadata": {},
44+
"outputs": [],
4045
"source": [
4146
"# ✅ SOLUTION\n",
4247
"\n",
4348
"def relu(x: torch.Tensor) -> torch.Tensor:\n",
4449
" return x * (x > 0).float()"
45-
],
46-
"outputs": [],
47-
"execution_count": null
50+
]
4851
},
4952
{
5053
"cell_type": "code",
54+
"execution_count": null,
5155
"metadata": {},
56+
"outputs": [],
5257
"source": [
5358
"# Verify\n",
5459
"x = torch.tensor([-2., -1., 0., 1., 2.])\n",
5560
"print(\"Input: \", x)\n",
5661
"print(\"Output:\", relu(x))"
57-
],
58-
"outputs": [],
59-
"execution_count": null
62+
]
6063
},
6164
{
6265
"cell_type": "code",
66+
"execution_count": null,
6367
"metadata": {},
68+
"outputs": [],
6469
"source": [
6570
"# Run judge\n",
6671
"from torch_judge import check\n",
6772
"check(\"relu\")"
68-
],
69-
"outputs": [],
70-
"execution_count": null
73+
]
7174
}
72-
]
73-
}
75+
],
76+
"metadata": {
77+
"kernelspec": {
78+
"display_name": "Python 3",
79+
"language": "python",
80+
"name": "python3"
81+
},
82+
"language_info": {
83+
"name": "python",
84+
"version": "3.11.0"
85+
}
86+
},
87+
"nbformat": 4,
88+
"nbformat_minor": 5
89+
}

solutions/02_softmax_solution.ipynb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"cell_type": "markdown",
1818
"metadata": {},
1919
"source": [
20+
"[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/duoan/TorchCode/blob/master/solutions/02_softmax_solution.ipynb)\n\n",
2021
"# 🟢 Solution: Implement Softmax\n",
2122
"\n",
2223
"Reference solution for the numerically-stable Softmax function.\n",
@@ -25,6 +26,20 @@
2526
],
2627
"outputs": []
2728
},
29+
{
30+
"cell_type": "code",
31+
"metadata": {},
32+
"source": [
33+
"# Install torch-judge in Colab (no-op in JupyterLab/Docker)\n",
34+
"try:\n",
35+
" import google.colab\n",
36+
" get_ipython().run_line_magic('pip', 'install -q torch-judge')\n",
37+
"except ImportError:\n",
38+
" pass\n"
39+
],
40+
"outputs": [],
41+
"execution_count": null
42+
},
2843
{
2944
"cell_type": "code",
3045
"metadata": {},
@@ -73,4 +88,4 @@
7388
"execution_count": null
7489
}
7590
]
76-
}
91+
}

solutions/03_linear_solution.ipynb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,27 @@
1717
"cell_type": "markdown",
1818
"metadata": {},
1919
"source": [
20+
"[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/duoan/TorchCode/blob/master/solutions/03_linear_solution.ipynb)\n\n",
2021
"# 🟡 Solution: Simple Linear Layer\n",
2122
"\n",
2223
"Reference solution for a fully-connected linear layer: **y = xW^T + b**"
2324
],
2425
"outputs": []
2526
},
27+
{
28+
"cell_type": "code",
29+
"metadata": {},
30+
"source": [
31+
"# Install torch-judge in Colab (no-op in JupyterLab/Docker)\n",
32+
"try:\n",
33+
" import google.colab\n",
34+
" get_ipython().run_line_magic('pip', 'install -q torch-judge')\n",
35+
"except ImportError:\n",
36+
" pass\n"
37+
],
38+
"outputs": [],
39+
"execution_count": null
40+
},
2641
{
2742
"cell_type": "code",
2843
"metadata": {},
@@ -77,4 +92,4 @@
7792
"execution_count": null
7893
}
7994
]
80-
}
95+
}

solutions/04_layernorm_solution.ipynb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"cell_type": "markdown",
1818
"metadata": {},
1919
"source": [
20+
"[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/duoan/TorchCode/blob/master/solutions/04_layernorm_solution.ipynb)\n\n",
2021
"# 🟡 Solution: Implement LayerNorm\n",
2122
"\n",
2223
"Reference solution for Layer Normalization.\n",
@@ -25,6 +26,20 @@
2526
],
2627
"outputs": []
2728
},
29+
{
30+
"cell_type": "code",
31+
"metadata": {},
32+
"source": [
33+
"# Install torch-judge in Colab (no-op in JupyterLab/Docker)\n",
34+
"try:\n",
35+
" import google.colab\n",
36+
" get_ipython().run_line_magic('pip', 'install -q torch-judge')\n",
37+
"except ImportError:\n",
38+
" pass\n"
39+
],
40+
"outputs": [],
41+
"execution_count": null
42+
},
2843
{
2944
"cell_type": "code",
3045
"metadata": {},
@@ -76,4 +91,4 @@
7691
"execution_count": null
7792
}
7893
]
79-
}
94+
}

0 commit comments

Comments
 (0)